Esempio n. 1
0
    def make_precon(self, atoms, recalc_mu=None):

        if self.r_NN is None:
            self.r_NN = estimate_nearest_neighbour_distance(atoms)

        if self.r_cut is None:
            # This is the first time this function has been called, and no
            # cutoff radius has been specified, so calculate it automatically.
            self.r_cut = 2.0 * self.r_NN
        elif self.r_cut < self.r_NN:
            warning = ('WARNING: r_cut (%.2f) < r_NN (%.2f), '
                       'increasing to 1.1*r_NN = %.2f' % (self.r_cut,
                                                          self.r_NN,
                                                          1.1 * self.r_NN))
            logger.info(warning)
            print(warning)
            self.r_cut = 1.1 * self.r_NN

        if recalc_mu is None:
            # The caller has not specified whether or not to recalculate mu,
            # so the Precon's setting is used.
            recalc_mu = self.recalc_mu

        if self.mu is None:
            # Regardless of what the caller has specified, if we don't
            # currently have a value of mu, then we need one.
            recalc_mu = True

        if recalc_mu:
            self.estimate_mu(atoms)

        if self.P is not None:
            real_atoms = atoms
            if isinstance(atoms, Filter):
                real_atoms = atoms.atoms
            if self.old_positions is None:
                self.old_positions = wrap_positions(real_atoms.positions,
                                                    real_atoms.cell)
            displacement = wrap_positions(real_atoms.positions,
                                          real_atoms.cell) - self.old_positions
            self.old_positions = real_atoms.get_positions()
            max_abs_displacement = abs(displacement).max()
            logger.info('max(abs(displacements)) = %.2f A (%.2f r_NN)',
                        max_abs_displacement,
                        max_abs_displacement / self.r_NN)
            if max_abs_displacement < 0.5 * self.r_NN:
                return self.P

        start_time = time.time()

        # Create the preconditioner:
        self._make_sparse_precon(atoms, force_stab=self.force_stab)

        logger.info('--- Precon created in %s seconds ---',
                    time.time() - start_time)
        return self.P
Esempio n. 2
0
    def get_check_point(self):

        if hasattr(self, 'log'):
            states = [
                torch.Tensor(self.log[key][-1]).to(self.device)
                for key in self.log
            ]

            if self.wrap:
                wrapped_xyz = wrap_positions(self.log['positions'][-1],
                                             self.system.get_cell())
                states[1] = torch.Tensor(wrapped_xyz).to(self.device)

            return states
        else:
            raise ValueError("No log available")
Esempio n. 3
0
def cell_to_hmatrix_impl(cell, positions, pbc):
    """
    Rotate ASE atoms cell to the h-matrix format used by LAMMPS.

    Arguments:
        cell: 3x3 array-like, the 3x3 cell matrix.
        positions: array-like, positions of atoms.
        pbc: tuple of bools, whether the cell is periodic in the direction?

    Returns:
        cell and positions under the new h-matrix coordination system.
    """
    a, b, c = cell
    an, bn, cn = [np.linalg.norm(v) for v in cell]

    alpha = np.arccos(np.dot(b, c)/(bn*cn))
    beta  = np.arccos(np.dot(a, c)/(an*cn))
    gamma = np.arccos(np.dot(a, b)/(an*bn))

    xhi = an
    xyp = np.cos(gamma)*bn
    yhi = np.sin(gamma)*bn
    xzp = np.cos(beta)*cn
    yzp = (bn*cn*np.cos(alpha) - xyp*xzp)/yhi
    zhi = np.sqrt(cn**2 - xzp**2 - yzp**2)
    Hpre = np.array([[xhi, 0.0, 0.0], [xyp, yhi, 0.0], [xzp, yzp, zhi]])
    R = np.dot(np.linalg.inv(cell), Hpre)

    def fold(vec, pvec, i):
        p = pvec[i]
        x = vec[i] + 0.5*p
        n = (np.mod(x, p) - x) / p
        return vec + n*pvec

    Hpre[1, :] = fold(Hpre[1, :], Hpre[0, :], 0)
    Hpre[2, :] = fold(Hpre[2, :], Hpre[1, :], 1)
    Hpre[2, :] = fold(Hpre[2, :], Hpre[0, :], 0)

    H = Hpre

    rot_positions = np.dot(positions, R)

    rot_positions = wrap_positions(rot_positions, H, pbc)

    return H, rot_positions
Esempio n. 4
0
    def vector_to_lammps(self, vec, wrap=False):
        """Rotate vector from ase coordinate system to lammps one

        :param vec: to be rotated ase-vector
        :returns: lammps-vector
        :rtype: np.array

        """
        # !TODO: right eps-limit
        # lammps might not like atoms outside the cell
        if wrap:
            return wrap_positions(
                np.dot(vec, self.rot_mat),
                self.lammps_cell,
                pbc=self.pbc,
                eps=1e-18,
            )

        return np.dot(vec, self.rot_mat)
Esempio n. 5
0
def proj_dict_to_string(dct, atoms):
    site = []
    site_outside_pc = False
    if 'csite' in dct:
        coords = np.array(dct['csite'])
        # Check coords are inside the cell
        [wrapped_coords] = wrap_positions([coords], atoms.cell)
        if np.linalg.norm(wrapped_coords - coords) > 1e-3:
            site_outside_pc = True
            coords = wrapped_coords
        site.append('c=' + ','.join([str(c) for c in coords]))
    elif 'fsite' in dct:
        coords = dct['fsite']
        # Check coords are inside the cell
        if any([x // 1 != 0 for x in coords]):
            site_outside_pc = True
            coords = [x % 1 for x in coords]
        site.append('f=' + ','.join([str(c) for c in coords]))
    elif 'site' in dct:
        site.append(dct['site'])
    else:
        raise ValueError('w90 projections block is missing a "site" entry')

    if site_outside_pc:
        warnings.warn('A projection site lies outside the primitive cell. It has been wrapped.')

    if 'ang_mtm' not in dct:
        raise ValueError('w90 projections block is missing an "ang_mtm" entry')
    site.append(dct['ang_mtm'])

    if 'zaxis' in dct:
        site.append('z=' + ','.join(str(x) for x in dct['zaxis']))

    if 'xaxis' in dct:
        site.append('x=' + ','.join(str(x) for x in dct['zaxis']))

    if 'radial' in dct:
        site.append(f'r={dct["radial"]}')

    if 'zona' in dct:
        site.append(f'zona={dct["zona"]}')

    return ':'.join(site)
Esempio n. 6
0
    def set_lammps_pos(self, atoms):
        # Create local copy of positions that are wrapped along any periodic
        # directions
        pos = wrap_positions(atoms.get_positions(), atoms.get_cell(),
                             atoms.get_pbc())
        pos = convert(pos, "distance", "ASE", self.units)

        # If necessary, transform the positions to new coordinate system
        if self.coord_transform is not None:
            pos = np.dot(self.coord_transform, pos.transpose())
            pos = pos.transpose()

        # Convert ase position matrix to lammps-style position array
        # contiguous in memory
        lmp_positions = list(pos.ravel())

        # Convert that lammps-style array into a C object
        c_double_array = (ctypes.c_double * len(lmp_positions))
        lmp_c_positions = c_double_array(*lmp_positions)
        #        self.lmp.put_coosrds(lmp_c_positions)
        self.lmp.scatter_atoms('x', 1, 3, lmp_c_positions)
Esempio n. 7
0
def unpack_ase(frame, wrap_pos=False):
    """
    Convert ASE Atoms object to rascal's equivalent

    Parameters
    ----------
    frame : ase.Atoms
        Atomic structure

    Returns
    -------
    StructureManagerCenters
        base structure manager.

    If the frame has an ase.atoms.arrays entry called
    'center_atoms_mask' then it will be used as the center mask
    (surprise) for any representations computed on this
    StructureManager.
    """
    cell = frame.get_cell()
    positions = frame.get_positions()
    numbers = frame.get_atomic_numbers()
    pbc = frame.get_pbc().astype(int)

    if wrap_pos:
        positions = wrap_positions(positions, cell, frame.get_pbc(), eps=1e-11)

    if "center_atoms_mask" in frame.arrays.keys():
        center_atoms_mask = frame.get_array("center_atoms_mask")
    else:
        center_atoms_mask = np.ones_like(numbers, dtype=bool)

    return adapt_structure(
        cell=cell,
        positions=positions,
        atom_types=numbers,
        pbc=pbc,
        center_atoms_mask=center_atoms_mask,
    )
Esempio n. 8
0
    def set_lammps_pos(self, atoms):
        # Create local copy of positions that are wrapped along any periodic
        # directions
        cell = convert(atoms.cell, "distance", "ASE", self.units)
        pos = convert(atoms.positions, "distance", "ASE", self.units)

        # If necessary, transform the positions to new coordinate system
        if self.coord_transform is not None:
            pos = np.dot(pos, self.coord_transform.T)
            cell = np.dot(cell, self.coord_transform.T)

        # wrap only after scaling and rotating to reduce chances of
        # lammps neighbor list bugs.
        pos = wrap_positions(pos, cell, atoms.get_pbc())

        # Convert ase position matrix to lammps-style position array
        # contiguous in memory
        lmp_positions = list(pos.ravel())

        # Convert that lammps-style array into a C object
        c_double_array = (ctypes.c_double * len(lmp_positions))
        lmp_c_positions = c_double_array(*lmp_positions)
        #        self.lmp.put_coosrds(lmp_c_positions)
        self.lmp.scatter_atoms('x', 1, 3, lmp_c_positions)
def moveAtoms( atoms, n_atoms_to_shift, alat=4.05 ):
    """
    To move an atom from A->B or B->C it has to be translated
    a distance r*(1,1/sqrt(3) ) in the plane orthogonal to the (1,1,1) plane
    r is the radius of the spheres
    """
    r = alat/(2.0*np.sqrt(2.0)) # For FCC lattice
    xhat = np.array( [1,-1,0] )/np.sqrt(2)
    yhat = np.array( [1,1,-2] )/np.sqrt(6)

    # Translation vec normal t0 (1,1,1)
    d = np.array( [1.0,1/np.sqrt(3),0] )*r
    translation = np.zeros(3)
    translation += d[0]*xhat
    translation += d[1]*yhat

    for i in range(n_atoms_to_shift):
        atoms[i].x += translation[0]
        atoms[i].y += translation[1]

    # Wrap positions to cell
    positions = geometry.wrap_positions( atoms.get_positions(), atoms.get_cell() )
    atoms.set_positions( positions )
    return atoms
Esempio n. 10
0
    def make_precon(self, atoms, recalc_mu=None):
        """Create a preconditioner matrix based on the passed set of atoms.

        Creates a general-purpose preconditioner for use with optimization
        algorithms, based on examining distances between pairs of atoms in the
        lattice. The matrix will be stored in the attribute self.P and
        returned.

        Args:
            atoms: the Atoms object used to create the preconditioner.
                Can also
            recalc_mu: if True, self.mu (and self.mu_c for variable cell)
                will be recalculated by calling self.estimate_mu(atoms)
                before the preconditioner matrix is created. If False, self.mu
                will be calculated only if it does not currently have a value
                (ie, the first time this function is called).

        Returns:
            A two-element tuple:
                P: A sparse scipy csr_matrix. BE AWARE that using
                    numpy.dot() with sparse matrices will result in
                    errors/incorrect results - use the .dot method directly
                    on the matrix instead.
        """

        if self.r_NN is None:
            self.r_NN = estimate_nearest_neighbour_distance(atoms)

        if self.r_cut is None:
            # This is the first time this function has been called, and no
            # cutoff radius has been specified, so calculate it automatically.
            self.r_cut = 2.0 * self.r_NN
        elif self.r_cut < self.r_NN:
            warning = ('WARNING: r_cut (%.2f) < r_NN (%.2f), '
                       'increasing to 1.1*r_NN = %.2f' % (self.r_cut,
                                                          self.r_NN,
                                                          1.1 * self.r_NN))
            warnings.warn(warning)
            self.r_cut = 1.1 * self.r_NN

        if recalc_mu is None:
            # The caller has not specified whether or not to recalculate mu,
            # so the Precon's setting is used.
            recalc_mu = self.recalc_mu

        if self.mu is None:
            # Regardless of what the caller has specified, if we don't
            # currently have a value of mu, then we need one.
            recalc_mu = True

        if recalc_mu:
            self.estimate_mu(atoms)

        if self.P is not None:
            real_atoms = atoms
            if isinstance(atoms, Filter):
                real_atoms = atoms.atoms
            if self.old_positions is None:
                self.old_positions = wrap_positions(real_atoms.positions,
                                                    real_atoms.cell)
            displacement = wrap_positions(real_atoms.positions,
                                          real_atoms.cell) - self.old_positions
            self.old_positions = real_atoms.get_positions()
            max_abs_displacement = abs(displacement).max()
            #print('max(abs(displacements)) = %.2f A (%.2f r_NN)' %
            #            (max_abs_displacement, max_abs_displacement / self.r_NN))
            if max_abs_displacement < 0.5 * self.r_NN:
                return self.P

        #start_time = time.time()

        # Create the preconditioner:
        self._make_sparse_precon(atoms, force_stab=self.force_stab)

        #print('--- Precon created in %s seconds ---' %
        #            (time.time() - start_time))
        return self.P
def surface_energy():
    conc_args = {
        "conc_ratio_min_1": [[64, 0, 0]],
        "conc_ratio_max_1": [[24, 40, 0]],
        "conc_ratio_min_2": [[64, 0, 0]],
        "conc_ratio_max_2": [[22, 21, 21]]
    }

    kwargs = {
        "crystalstructure": "fcc",
        "a": 4.05,
        "size": [4, 4, 4],
        "basis_elements": [["Al", "Mg", "Si"]],
        "conc_args": conc_args,
        "db_name": "data/almgsi.db",
        "max_cluster_size": 4
    }

    ceBulk = CEBulk(**kwargs)
    eci_file = "data/almgsi_fcc_eci_newconfig.json"
    with open(eci_file, 'r') as infile:
        ecis = json.load(infile)
    size = (8, 8, 8)
    db_name = "large_cell_db{}x{}x{}.db".format(size[0], size[1], size[2])
    calc = get_ce_calc(ceBulk, kwargs, ecis, size=size, db_name=db_name)
    print(calc.get_energy() / len(calc.atoms))
    ceBulk = calc.BC
    ceBulk.atoms.set_calculator(calc)

    # Get the energy of MgSi
    mgsi = wrap_and_sort_by_position(get_mgsi() * (4, 4, 4))
    symbs = [atom.symbol for atom in mgsi]
    calc.set_symbols(symbs)
    view(calc.atoms)
    mgsi_energy = calc.get_energy() / len(calc.atoms)
    print("Energy MgSi: {} eV/atom".format(mgsi_energy))

    # Get the energy of pure al
    symbs = ["Al" for _ in range(len(mgsi))]
    calc.set_symbols(symbs)
    view(calc.atoms)
    al_energy = calc.get_energy() / len(calc.atoms)
    print("Energy Al: {} eV/atom".format(al_energy))

    # Get the energy of a 50% mixture
    mgsi = wrap_and_sort_by_position(get_mgsi() * (4, 4, 2))
    # mgsi = get_mgsi_surface100_si_si()
    from scipy.spatial import cKDTree as KDTree
    cell = calc.atoms.get_cell()
    tree = KDTree(calc.atoms.get_positions())
    symbs = [atom.symbol for atom in calc.atoms]
    for atom in mgsi:
        pos = np.zeros((1, 3))
        pos[0, :] = atom.position
        wrapped = wrap_positions(pos, cell)
        if not np.allclose(wrapped, atom.position):
            continue
        _, indx = tree.query(atom.position)
        symbs[indx] = atom.symbol
    calc.set_symbols(symbs)
    view(calc.atoms)

    # Surface energy
    mix_energy = calc.get_energy()
    print("Mix energy: {} eV ({} eV/atom)".format(mix_energy, mix_energy /
                                                  len(calc.atoms)))
    num_al = 0
    num_mgsi = 0
    for atom in calc.atoms:
        if atom.symbol == "Al":
            num_al += 1
        elif atom.symbol == "Mg" or atom.symbol == "Si":
            num_mgsi += 1
    assert num_al + num_mgsi == len(calc.atoms)
    dE = mix_energy - num_al * al_energy - num_mgsi * mgsi_energy
    cell = calc.atoms.get_cell()
    a1 = cell[0, :]
    a2 = cell[1, :]
    normal = np.cross(a1, a2)
    area = np.sqrt(normal.dot(normal))

    # Convert units
    surface_tension = dE / area
    mJ = J / 1000.0  # milli joules
    surface_tension *= (m * m / mJ)
    unit_normal = normal / area
    print("Surface tension: {} mJ/m^2".format(surface_tension))
    print("Direction: {}".format(unit_normal))
Esempio n. 12
0
    def build(self, pbc, cell, coordinates):
        """Build the list.

        Coordinates are taken to be scaled or not according
        to self.use_scaled_positions.
        """
        self.pbc = pbc = np.array(pbc, copy=True)
        self.cell = cell = Cell(cell)
        self.coordinates = coordinates = np.array(coordinates, copy=True)

        if len(self.cutoffs) != len(coordinates):
            raise ValueError('Wrong number of cutoff radii: {0} != {1}'.format(
                len(self.cutoffs), len(coordinates)))

        if len(self.cutoffs) > 0:
            rcmax = self.cutoffs.max()
        else:
            rcmax = 0.0

        if self.use_scaled_positions:
            positions0 = cell.cartesian_positions(coordinates)
        else:
            positions0 = coordinates

        rcell, op = minkowski_reduce(cell, pbc)
        positions = wrap_positions(positions0, rcell, pbc=pbc, eps=0)

        natoms = len(positions)
        self.nneighbors = 0
        self.npbcneighbors = 0
        self.neighbors = [np.empty(0, int) for a in range(natoms)]
        self.displacements = [np.empty((0, 3), int) for a in range(natoms)]
        self.nupdates += 1
        if natoms == 0:
            return

        N = []
        ircell = np.linalg.pinv(rcell)
        for i in range(3):
            if self.pbc[i]:
                v = ircell[:, i]
                h = 1 / np.linalg.norm(v)
                n = int(2 * rcmax / h) + 1
            else:
                n = 0
            N.append(n)

        tree = cKDTree(positions, copy_data=True)
        offsets = cell.scaled_positions(positions - positions0)
        offsets = offsets.round().astype(np.int)

        for n1, n2, n3 in itertools.product(range(0, N[0] + 1),
                                            range(-N[1], N[1] + 1),
                                            range(-N[2], N[2] + 1)):
            if n1 == 0 and (n2 < 0 or n2 == 0 and n3 < 0):
                continue

            displacement = (n1, n2, n3) @ rcell
            for a in range(natoms):

                indices = tree.query_ball_point(positions[a] - displacement,
                                                r=self.cutoffs[a] + rcmax)
                if not len(indices):
                    continue

                indices = np.array(indices)
                delta = positions[indices] + displacement - positions[a]
                cutoffs = self.cutoffs[indices] + self.cutoffs[a]
                i = indices[np.linalg.norm(delta, axis=1) < cutoffs]
                if n1 == 0 and n2 == 0 and n3 == 0:
                    if self.self_interaction:
                        i = i[i >= a]
                    else:
                        i = i[i > a]

                self.nneighbors += len(i)
                self.neighbors[a] = np.concatenate((self.neighbors[a], i))

                disp = (n1, n2, n3) @ op + offsets[i] - offsets[a]
                self.npbcneighbors += disp.any(1).sum()
                self.displacements[a] = np.concatenate(
                    (self.displacements[a], disp))

        if self.bothways:
            neighbors2 = [[] for a in range(natoms)]
            displacements2 = [[] for a in range(natoms)]
            for a in range(natoms):
                for b, disp in zip(self.neighbors[a], self.displacements[a]):
                    neighbors2[b].append(a)
                    displacements2[b].append(-disp)
            for a in range(natoms):
                nbs = np.concatenate((self.neighbors[a], neighbors2[a]))
                disp = np.array(
                    list(self.displacements[a]) + displacements2[a])
                # Force correct type and shape for case of no neighbors:
                self.neighbors[a] = nbs.astype(int)
                self.displacements[a] = disp.astype(int).reshape((-1, 3))

        if self.sorted:
            for a, i in enumerate(self.neighbors):
                mask = (i < a)
                if mask.any():
                    j = i[mask]
                    offsets = self.displacements[a][mask]
                    for b, offset in zip(j, offsets):
                        self.neighbors[b] = np.concatenate(
                            (self.neighbors[b], [a]))
                        self.displacements[b] = np.concatenate(
                            (self.displacements[b], [-offset]))
                    mask = np.logical_not(mask)
                    self.neighbors[a] = self.neighbors[a][mask]
                    self.displacements[a] = self.displacements[a][mask]
Esempio n. 13
0
def test_geometry():
    """Test the ase.geometry module and ase.build.cut() function."""

    import numpy as np

    from ase.build import cut, bulk, fcc111
    from ase.cell import Cell
    from ase.geometry import get_layers, wrap_positions
    from ase.spacegroup import crystal, get_spacegroup

    al = crystal('Al', [(0, 0, 0)], spacegroup=225, cellpar=4.05)

    # Cut out slab of 5 Al(001) layers
    al001 = cut(al, nlayers=5)
    correct_pos = np.array([[0., 0., 0.],
                            [0., 0.5, 0.2],
                            [0.5, 0., 0.2],
                            [0.5, 0.5, 0.],
                            [0., 0., 0.4],
                            [0., 0.5, 0.6],
                            [0.5, 0., 0.6],
                            [0.5, 0.5, 0.4],
                            [0., 0., 0.8],
                            [0.5, 0.5, 0.8]])
    assert np.allclose(correct_pos, al001.get_scaled_positions())

    # Check layers along 001
    tags, levels = get_layers(al001, (0, 0, 1))
    assert np.allclose(tags, [0, 1, 1, 0, 2, 3, 3, 2, 4, 4])
    assert np.allclose(levels, [0., 2.025, 4.05, 6.075, 8.1])

    # Check layers along 101
    tags, levels = get_layers(al001, (1, 0, 1))
    assert np.allclose(tags, [0, 1, 5, 3, 2, 4, 8, 7, 6, 9])
    assert np.allclose(levels, [0.000, 0.752, 1.504, 1.880, 2.256, 2.632, 3.008,
                                3.384, 4.136, 4.888],
                       atol=0.001)

    # Check layers along 111
    tags, levels = get_layers(al001, (1, 1, 1))
    assert np.allclose(tags, [0, 2, 2, 4, 1, 5, 5, 6, 3, 7])
    assert np.allclose(levels, [0.000, 1.102, 1.929, 2.205, 2.756, 3.031, 3.858,
                                4.960],
                       atol=0.001)

    # Cut out slab of three Al(111) layers
    al111 = cut(al, (1, -1, 0), (0, 1, -1), nlayers=3)
    correct_pos = np.array([[0.5, 0., 0.],
                            [0., 0.5, 0.],
                            [0.5, 0.5, 0.],
                            [0., 0., 0.],
                            [1 / 6., 1 / 3., 1 / 3.],
                            [1 / 6., 5 / 6., 1 / 3.],
                            [2 / 3., 5 / 6., 1 / 3.],
                            [2 / 3., 1 / 3., 1 / 3.],
                            [1 / 3., 1 / 6., 2 / 3.],
                            [5 / 6., 1 / 6., 2 / 3.],
                            [5 / 6., 2 / 3., 2 / 3.],
                            [1 / 3., 2 / 3., 2 / 3.]])
    assert np.allclose(correct_pos, al111.get_scaled_positions())

    # Cut out cell including all corner and edge atoms (non-periodic structure)
    al = cut(al, extend=1.1)
    correct_pos = np.array([[0., 0., 0.],
                            [0., 2.025, 2.025],
                            [2.025, 0., 2.025],
                            [2.025, 2.025, 0.],
                            [0., 0., 4.05],
                            [2.025, 2.025, 4.05],
                            [0., 4.05, 0.],
                            [2.025, 4.05, 2.025],
                            [0., 4.05, 4.05],
                            [4.05, 0., 0.],
                            [4.05, 2.025, 2.025],
                            [4.05, 0., 4.05],
                            [4.05, 4.05, 0.],
                            [4.05, 4.05, 4.05]])
    assert np.allclose(correct_pos, al.positions)

    # Create an Ag(111)/Si(111) interface
    ag = crystal(['Ag'], basis=[(0, 0, 0)], spacegroup=225, cellpar=4.09)
    si = crystal(['Si'], basis=[(0, 0, 0)], spacegroup=227, cellpar=5.43)
    try:
        assert get_spacegroup(ag).no == 225
        assert get_spacegroup(si).no == 227
    except ImportError:
        pass

    ag111 = cut(ag, a=(4, -4, 0), b=(4, 4, -8), nlayers=5)  # noqa
    si111 = cut(si, a=(3, -3, 0), b=(3, 3, -6), nlayers=5)  # noqa
    #
    # interface = stack(ag111, si111)
    # assert len(interface) == 1000
    # assert np.allclose(interface.positions[::100],
    #                   [[  4.08125   ,  -2.040625  ,   -2.040625  ],
    #                    [  8.1625    ,   6.121875  ,  -14.284375  ],
    #                    [ 10.211875  ,   0.00875   ,    2.049375  ],
    #                    [ 24.49041667,  -4.07833333,  -16.32208333],
    #                    [ 18.37145833,  14.29020833,  -24.48166667],
    #                    [ 24.49916667,  12.25541667,  -20.39458333],
    #                    [ 18.36854167,  16.32791667,  -30.60645833],
    #                    [ 19.0575    ,   0.01166667,    5.45333333],
    #                    [ 23.13388889,   6.80888889,    1.36722222],
    #                    [ 35.3825    ,   5.45333333,  -16.31333333]])
    #

    # Test the wrap_positions function.
    positions = np.array([
        [4.0725, -4.0725, -1.3575],
        [1.3575, -1.3575, -1.3575],
        [2.715, -2.715, 0.],
        [4.0725, 1.3575, -1.3575],
        [0., 0., 0.],
        [2.715, 2.715, 0.],
        [6.7875, -1.3575, -1.3575],
        [5.43, 0., 0.]])
    cell = np.array([[5.43, 5.43, 0.0], [5.43, -5.43, 0.0], [0.00, 0.00, 40.0]])
    positions += np.array([6.1, -0.1, 10.1])
    result_positions = wrap_positions(positions=positions, cell=cell)
    correct_pos = np.array([
        [4.7425, 1.2575, 8.7425],
        [7.4575, -1.4575, 8.7425],
        [3.385, 2.615, 10.1],
        [4.7425, -4.1725, 8.7425],
        [6.1, -0.1, 10.1],
        [3.385, -2.815, 10.1],
        [2.0275, -1.4575, 8.7425],
        [0.67, -0.1, 10.1]])
    assert np.allclose(correct_pos, result_positions)

    positions = wrap_positions(positions, cell, pbc=[False, True, False])
    correct_pos = np.array([
        [4.7425, 1.2575, 8.7425],
        [7.4575, -1.4575, 8.7425],
        [3.385, 2.615, 10.1],
        [10.1725, 1.2575, 8.7425],
        [6.1, -0.1, 10.1],
        [8.815, 2.615, 10.1],
        [7.4575, 3.9725, 8.7425],
        [6.1, 5.33, 10.1]])
    assert np.allclose(correct_pos, positions)

    # Test center away from values 0, 0.5
    result_positions = wrap_positions(positions, cell,
                                      pbc=[True, True, False],
                                      center=0.2)
    correct_pos = [[4.7425, 1.2575, 8.7425],
                   [2.0275, 3.9725, 8.7425],
                   [3.385, 2.615, 10.1],
                   [-0.6875, 1.2575, 8.7425],
                   [6.1, -0.1, 10.1],
                   [3.385, -2.815, 10.1],
                   [2.0275, -1.4575, 8.7425],
                   [0.67, -0.1, 10.1]]
    assert np.allclose(correct_pos, result_positions)

    # Test pretty_translation keyword
    positions = np.array([
        [0, 0, 0],
        [0, 1, 1],
        [1, 0, 1],
        [1, 1, 0.]])
    cell = np.diag([2, 2, 2])
    result = wrap_positions(positions, cell, pbc=[True, True, True],
                            pretty_translation=True)
    assert np.max(result) < 1 + 1E-10
    assert np.min(result) > -1E-10

    result = wrap_positions(positions - 5, cell, pbc=[True, True, True],
                            pretty_translation=True)
    assert np.max(result) < 1 + 1E-10

    result = wrap_positions(positions - 5, cell, pbc=[False, True, True],
                            pretty_translation=True)
    assert np.max(result[:, 0]) < -3
    assert np.max(result[:, 1:]) < 1 + 1E-10

    # Get the correct crystal structure from a range of different cells

    def checkcell(cell, name):
        cell = Cell.ascell(cell)
        lat = cell.get_bravais_lattice()
        assert lat.name == name, (lat.name, name)

    checkcell(bulk('Al').cell, 'FCC')
    checkcell(bulk('Fe').cell, 'BCC')
    checkcell(bulk('Zn').cell, 'HEX')
    checkcell(fcc111('Au', size=(1, 1, 3), periodic=True).cell, 'HEX')
    checkcell([[1, 0, 0], [0, 1, 0], [0, 0, 1]], 'CUB')
    checkcell([[1, 0, 0], [0, 1, 0], [0, 0, 2]], 'TET')
    checkcell([[1, 0, 0], [0, 2, 0], [0, 0, 3]], 'ORC')
    checkcell([[1, 0, 0], [0, 2, 0], [0.5, 0, 3]], 'ORCC')
    checkcell([[1, 0, 0], [0, 2, 0], [0.501, 0, 3]], 'MCL')
    checkcell([[1, 0, 0], [0.5, 3**0.5 / 2, 0], [0, 0, 3]], 'HEX')
Esempio n. 14
0
#                    [ 35.3825    ,   5.45333333,  -16.31333333]])
#

# Test the wrap_positions function.
positions = np.array([
    [4.0725, -4.0725, -1.3575],
    [1.3575, -1.3575, -1.3575],
    [2.715, -2.715, 0.],
    [4.0725, 1.3575, -1.3575],
    [0., 0., 0.],
    [2.715, 2.715, 0.],
    [6.7875, -1.3575, -1.3575],
    [5.43, 0., 0.]])
cell = np.array([[5.43, 5.43, 0.0], [5.43, -5.43, 0.0], [0.00, 0.00, 40.0]])
positions += np.array([6.1, -0.1, 10.1])
result_positions = wrap_positions(positions=positions, cell=cell)
correct_pos = np.array([
    [4.7425, 1.2575, 8.7425],
    [7.4575, -1.4575, 8.7425],
    [3.385, 2.615, 10.1],
    [4.7425, -4.1725, 8.7425],
    [6.1, -0.1, 10.1],
    [3.385, -2.815, 10.1],
    [2.0275, -1.4575, 8.7425],
    [0.67, -0.1, 10.1]])
assert np.allclose(correct_pos, result_positions)

positions = wrap_positions(positions, cell, pbc=[False, True, False])
correct_pos = np.array([
    [4.7425, 1.2575, 8.7425],
    [7.4575, -1.4575, 8.7425],
# so you want it to wrap to the higher value (e.g., BAZJET).
centercorrection = np.identity(3) * 0.00001
center1 = np.full(DIM, 0.5) + np.dot(centercorrection, deltapos)
#center2 = np.full(DIM,0.5) - np.dot(centercorrection,deltapos)

# Wrap node positions so they start in the same unit cell
# because zeo++ sometimes gives position of node1 in the
# extended unit cell.
# (Not sure this is also happening with node2, but wrap just in case)
#node1 = [x1,y1,z1]
# wrap node 1
node1 = [x1, y1, z1]
node2 = [x2, y2, z2]
print("node1: ", node1)
print("node2: ", node2)
node1 = geometry.wrap_positions([node1], cell, center=center1)[0]
node1_frac = cartn_to_frac(node1, invcell)
# wrap node 2 to same image as node 1
node2 = geometry.wrap_positions([node2], cell, center=node1_frac)[0]

# translate node2 if across unit cell
#node2 = shift_point(node2, deltapos, cell)
print("wrapped node1: ", node1)
print("wrapped node2: ", node2)

# compute midpoint and vectors
mid = np.zeros(DIM)  # FIXME declare array of length DIM
edgevec = np.zeros(DIM)
edgelength = 0.0
normvec = np.zeros(DIM)
for i in range(DIM):
Esempio n. 16
0
#                    [ 35.3825    ,   5.45333333,  -16.31333333]])
#

# Test the wrap_positions function.
positions = np.array([
    [4.0725, -4.0725, -1.3575],
    [1.3575, -1.3575, -1.3575],
    [2.715, -2.715, 0.],
    [4.0725, 1.3575, -1.3575],
    [0., 0., 0.],
    [2.715, 2.715, 0.],
    [6.7875, -1.3575, -1.3575],
    [5.43, 0., 0.]])
cell = np.array([[5.43, 5.43, 0.0], [5.43, -5.43, 0.0], [0.00, 0.00, 40.0]])
positions += np.array([6.1, -0.1, 10.1])
result_positions = wrap_positions(positions=positions, cell=cell)
correct_pos = np.array([
    [4.7425, 1.2575, 8.7425],
    [7.4575, -1.4575, 8.7425],
    [3.385, 2.615, 10.1],
    [4.7425, -4.1725, 8.7425],
    [6.1, -0.1, 10.1],
    [3.385, -2.815, 10.1],
    [2.0275, -1.4575, 8.7425],
    [0.67, -0.1, 10.1]])
assert np.allclose(correct_pos, result_positions)

positions = wrap_positions(positions, cell, pbc=[False, True, False])
correct_pos = np.array([
    [4.7425, 1.2575, 8.7425],
    [7.4575, -1.4575, 8.7425],
Esempio n. 17
0
    def make_precon(self, atoms, recalc_mu=None):
        """Create a preconditioner matrix based on the passed set of atoms.

        Creates a general-purpose preconditioner for use with optimization
        algorithms, based on examining distances between pairs of atoms in the
        lattice. The matrix will be stored in the attribute self.P and
        returned.

        Args:
            atoms: the Atoms object used to create the preconditioner.
                Can also
            recalc_mu: if True, self.mu (and self.mu_c for variable cell)
                will be recalculated by calling self.estimate_mu(atoms)
                before the preconditioner matrix is created. If False, self.mu
                will be calculated only if it does not currently have a value
                (ie, the first time this function is called).

        Returns:
            A two-element tuple:
                P: A sparse scipy csr_matrix. BE AWARE that using
                    numpy.dot() with sparse matrices will result in
                    errors/incorrect results - use the .dot method directly
                    on the matrix instead.
        """

        if self.r_NN is None:
            self.r_NN = estimate_nearest_neighbour_distance(atoms)

        if self.r_cut is None:
            # This is the first time this function has been called, and no
            # cutoff radius has been specified, so calculate it automatically.
            self.r_cut = 2.0 * self.r_NN
        elif self.r_cut < self.r_NN:
            warning = ('WARNING: r_cut (%.2f) < r_NN (%.2f), '
                       'increasing to 1.1*r_NN = %.2f' % (self.r_cut,
                                                          self.r_NN,
                                                          1.1 * self.r_NN))
            logger.info(warning)
            print(warning)
            self.r_cut = 1.1 * self.r_NN

        if recalc_mu is None:
            # The caller has not specified whether or not to recalculate mu,
            # so the Precon's setting is used.
            recalc_mu = self.recalc_mu

        if self.mu is None:
            # Regardless of what the caller has specified, if we don't
            # currently have a value of mu, then we need one.
            recalc_mu = True

        if recalc_mu:
            self.estimate_mu(atoms)

        if self.P is not None:
            real_atoms = atoms
            if isinstance(atoms, Filter):
                real_atoms = atoms.atoms
            if self.old_positions is None:
                self.old_positions = wrap_positions(real_atoms.positions,
                                                    real_atoms.cell)
            displacement = wrap_positions(real_atoms.positions,
                                          real_atoms.cell) - self.old_positions
            self.old_positions = real_atoms.get_positions()
            max_abs_displacement = abs(displacement).max()
            logger.info('max(abs(displacements)) = %.2f A (%.2f r_NN)',
                        max_abs_displacement, max_abs_displacement / self.r_NN)
            if max_abs_displacement < 0.5 * self.r_NN:
                return self.P

        start_time = time.time()

        # Create the preconditioner:
        self._make_sparse_precon(atoms, force_stab=self.force_stab)

        logger.info('--- Precon created in %s seconds ---',
                    time.time() - start_time)
        return self.P
Esempio n. 18
0
#                    [ 35.3825    ,   5.45333333,  -16.31333333]])
#

# Test the wrap_positions function.
positions = np.array([
    [4.0725, -4.0725, -1.3575],
    [1.3575, -1.3575, -1.3575],
    [2.715, -2.715, 0.],
    [4.0725, 1.3575, -1.3575],
    [0., 0., 0.],
    [2.715, 2.715, 0.],
    [6.7875, -1.3575, -1.3575],
    [5.43, 0., 0.]])
cell = np.array([[5.43, 5.43, 0.0], [5.43, -5.43, 0.0], [0.00, 0.00, 40.0]])
positions += np.array([6.1, -0.1, 10.1])
result_positions = wrap_positions(positions=positions, cell=cell)
correct_pos = np.array([
    [4.7425, 1.2575, 8.7425],
    [7.4575, -1.4575, 8.7425],
    [3.385, 2.615, 10.1],
    [4.7425, -4.1725, 8.7425],
    [6.1, -0.1, 10.1],
    [3.385, -2.815, 10.1],
    [2.0275, -1.4575, 8.7425],
    [0.67, -0.1, 10.1]])
assert np.allclose(correct_pos, result_positions)

positions = wrap_positions(positions, cell, pbc=[False, True, False])
correct_pos = np.array([
    [4.7425, 1.2575, 8.7425],
    [7.4575, -1.4575, 8.7425],