Ejemplo n.º 1
0
def test_inputs():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Al", "Al"]
    Al = Atoms(lattice_mat=box, coords=coords, elements=elements)
    spg = Spacegroup3D(atoms=Al)
    Al = spg.conventional_standard_structure
    box = LammpsData().atoms_to_lammps(atoms=Al)
    td = box.to_dict()
    fd = LammpsData.from_dict(td)
    box.write_file(filename=data)
    d = box.to_dict()
    # print ('d=',d)
    reload_d = LammpsData.from_dict(d)
    # print ('d=',reload_d)
    atoms = box.lammps_to_atoms()
    lmp = LammpsData().read_data(filename=data, potential_file=pot)
    lmp = LammpsData().atoms_to_lammps(atoms=atoms)
    pair_coeff = "abc"
    inp = LammpsInput(LammpsDataObj=lmp).write_lammps_in(
        lammps_in=init,
        lammps_in1=pot,
        lammps_in2=inm,
        parameters={
            "pair_style": "eam/alloy",
            "pair_coeff": pair_coeff,
            "atom_style": "charge",
            "control_file": "/users/knc6/inelast.mod",
        },
    )
    d = LammpsInput(LammpsDataObj=lmp).to_dict()
    d = LammpsInput.from_dict(d)
    assert (lmp._lammps_box[1], atoms.num_atoms) == (5.43, 8)
Ejemplo n.º 2
0
def get_jarvis_atoms(optimade_structure: OptimadeStructure) -> Atoms:
    """Get jarvis `Atoms` from OPTIMADE structure.

    Caution:
        Cannot handle partial occupancies.

    Parameters:
        optimade_structure: OPTIMADE structure.

    Returns:
        A jarvis `Atoms` object.

    """
    if "optimade.adapters" in repr(globals().get("Atoms")):
        warn(JARVIS_NOT_FOUND)
        return None

    attributes = optimade_structure.attributes

    # Cannot handle partial occupancies
    if StructureFeatures.DISORDER in attributes.structure_features:
        raise ConversionError(
            "jarvis-tools cannot handle structures with partial occupancies."
        )

    return Atoms(
        lattice_mat=attributes.lattice_vectors,
        elements=[specie.name for specie in attributes.species],
        coords=attributes.cartesian_site_positions,
        cartesian=True,
    )
Ejemplo n.º 3
0
def test_kp():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    lattice_mat = Si.lattice_mat
    kp = Kpoints3D().automatic_length_mesh(lattice_mat=lattice_mat, length=20)
    td = kp.to_dict()
    fd = Kpoints3D.from_dict(td)
    sym = kp.high_symm_path(Si)._path
    x, y = kp.interpolated_points(Si)
    kpath = generate_kpath(kpath=[[0, 0, 0], [0, 0.5, 0.5]], num_k=5)
    kps = generate_kgrid(grid=[5, 5, 5])
    new_file, filename = tempfile.mkstemp()
    kp.write_file(filename)
    sym = kp.high_symm_path(s1)._path
    sym = kp.high_symm_path(s2)._path
    sym = kp.high_symm_path(s3)._path
    sym = kp.high_symm_path(s4)._path
    sym = kp.high_symm_path(s5)._path
    sym = kp.high_symm_path(s6)._path
    sym = kp.high_symm_path(s7)._path
    assert (len(x), x[0][0], y[0], kpath[0][0], kps[0][0]) == (
        166,
        0,
        "\Gamma",
        0.0,
        0.0,
    )
    kp = Kpoints3D().kpath(atoms=Si, unique_kp_only=True)
Ejemplo n.º 4
0
def test_win():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    Wannier90win(struct=Si, efermi=0.0).write_win(name=win)
    w = Wannier90win(struct=Si, efermi=0.0)
    td = w.to_dict()
    fd = Wannier90win.from_dict(td)
    assert (os.path.isfile(win)) == (True)
    os.remove(win)

    Wannier90win(struct=s1, efermi=0.0).write_win(name=win)
    assert (os.path.isfile(win)) == (True)
    Wannier90win(struct=s1, efermi=0.0).write_hr_win(prev_win=win)
    os.remove(win)

    Wannier90win(struct=s2, efermi=0.0).write_win(name=win)
    assert (os.path.isfile(win)) == (True)
    os.remove(win)

    Wannier90win(struct=s3, efermi=0.0).write_win(name=win)
    assert (os.path.isfile(win)) == (True)
    os.remove(win)
    cmd = 'rm *.win'
    os.system(cmd)
Ejemplo n.º 5
0
def read_pdb(filename=""):
    """Read PDB file and make Atoms object."""
    f = open(filename, "r")
    lines = f.read().splitlines()
    f.close()
    coords = []
    species = []
    for i in lines:
        tmp = i.split()
        if "ATOM " in i and "REMARK" not in i and "SITE" not in i:
            coord = [float(tmp[6]), float(tmp[7]), float(tmp[8])]
            coords.append(coord)
            species.append(tmp[11])
            # print (coord,tmp[11])
    coords = np.array(coords)

    max_c = np.max(coords, axis=0)
    min_c = np.min(coords, axis=0)
    box = np.zeros((3, 3))
    for j in range(3):
        box[j, j] = abs(max_c[j] - min_c[j])
    pdb = Atoms(lattice_mat=box, elements=species,
                coords=coords, cartesian=True)
    mol = VacuumPadding(pdb, vacuum=20.0).get_effective_molecule()
    return mol
Ejemplo n.º 6
0
def get_jarvis_atoms(optimade_structure: OptimadeStructure) -> Atoms:
    """ Get jarvis Atoms from OPTIMADE structure

    NOTE: Cannot handle partial occupancies

    :param optimade_structure: OPTIMADE structure
    :return: jarvis.core.Atoms
    """
    if globals().get("Atoms", None) is None:
        warn(JARVIS_NOT_FOUND)
        return None

    attributes = optimade_structure.attributes

    # Cannot handle partial occupancies
    if "disorder" in attributes.structure_features:
        raise ConversionError(
            "jarvis-tools cannot handle structures with partial occupancies."
        )

    cartesian_site_positions, _ = pad_positions(attributes.cartesian_site_positions)

    return Atoms(
        lattice_mat=attributes.lattice_vectors,
        elements=[specie.name for specie in attributes.species],
        coords=cartesian_site_positions,
        cartesian=True,
    )
Ejemplo n.º 7
0
 def final_structure(self):
     """Get final atoms."""
     elements = []
     pos = []
     lat = []
     lat.append([
         float(i) for i in self.data["qes:espresso"]["step"][-1]
         ["atomic_structure"]["cell"]["a1"].split()
     ])
     lat.append([
         float(i) for i in self.data["qes:espresso"]["step"][-1]
         ["atomic_structure"]["cell"]["a2"].split()
     ])
     lat.append([
         float(i) for i in self.data["qes:espresso"]["step"][-1]
         ["atomic_structure"]["cell"]["a3"].split()
     ])
     for i in self.data["qes:espresso"]["step"][-1]["atomic_structure"][
             "atomic_positions"]["atom"]:
         elements.append(i["@name"])
         pos.append([float(j) for j in i["#text"].split()])
     atoms = Atoms(elements=elements,
                   coords=pos,
                   lattice_mat=lat,
                   cartesian=True)
     return atoms
Ejemplo n.º 8
0
    def get_atoms(structure):
        """
        Returns JARVIS Atoms object from pymatgen structure.

        Args:
            structure: pymatgen.core.structure.Structure

        Returns:
            JARVIS Atoms object
        """
        if not structure.is_ordered:
            raise ValueError("JARVIS Atoms only supports ordered structures")
        if not jarvis_loaded:
            raise ImportError(
                "JarvisAtomsAdaptor requires jarvis-tools package.\nUse `pip install -U jarvis-tools`"
            )
        elements = [str(site.specie.symbol) for site in structure]
        coords = [site.frac_coords for site in structure]
        lattice_mat = structure.lattice.matrix
        return Atoms(
            lattice_mat=lattice_mat,
            elements=elements,
            coords=coords,
            cartesian=False,
        )
Ejemplo n.º 9
0
def test_nbors():
    box = [[5.493642, 0, 0], [0, 5.493642, 0], [0, 0, 5.493642]]
    elements = ["Si", "Si", "Si", "Si", "Si", "Si", "Si", "Si"]
    coords = [
        [0, 0, 0],
        [0.25, 0.25, 0.25],
        [0.000000, 0.500000, 0.500000],
        [0.250000, 0.750000, 0.750000],
        [0.500000, 0.000000, 0.500000],
        [0.750000, 0.250000, 0.750000],
        [0.500000, 0.500000, 0.000000],
        [0.750000, 0.750000, 0.250000],
    ]
    coords = np.array(coords)
    # box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    # coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    # elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    nbr = NeighborsAnalysis(Si)
    nb = nbr.get_all_distributions
    tmp = round((nb["rdf"][-3]), 2)
    assert (tmp) == (4.08)
    nbr.get_rdf(plot=True)
    # nbr.ang_dist(nbor_info=info,plot=True)
    nbr.ang_dist_first(plot=True)
    nbr.ang_dist_second(plot=True)
    nbr.get_ddf(plot=True)
    angs = nbr.atomwise_angle_dist()
    ardf = nbr.atomwise_radial_dist()
    cmd = "rm *.png"
    os.system(cmd)
Ejemplo n.º 10
0
def test_spg():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    spg = Spacegroup3D(atoms=Si)  # .spacegroup_data()
    cvn = spg.conventional_standard_structure
    ml = symmetrically_distinct_miller_indices(max_index=3, cvn_atoms=cvn)
    # print ('ml',ml)
    x = get_wyckoff_position_operators(488)
    # print  (x['wyckoff'][0]['letter'])
    assert (
        spg.space_group_number,
        spg.space_group_symbol,
        cvn.num_atoms,
        ml[0][0],
        x["wyckoff"][0]["letter"],
    ) == (227, "Fd-3m", 8, 1, "l")
    spg = Spacegroup3D(atoms=s1)
    assert spg.space_group_number == 191
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    spg = Spacegroup3D(atoms=s2)
    assert spg.space_group_number == 166
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    spg = Spacegroup3D(atoms=s3)
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    assert spg.space_group_number == 139
    spg = Spacegroup3D(atoms=s4)
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    assert spg.space_group_number == 63

    spg = Spacegroup3D(atoms=s5)
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    assert spg.space_group_number == 39

    spg = Spacegroup3D(atoms=s6)
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    assert spg.space_group_number == 12

    spg = Spacegroup3D(atoms=s7)
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    assert spg.space_group_number == 7

    spg = Spacegroup3D(atoms=s8)
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    assert spg.space_group_number == 2

    spg = Spacegroup3D(atoms=s9)
    print(spg.space_group_number)
    cvn = spg.conventional_standard_structure
    assert spg.space_group_number == 11
Ejemplo n.º 11
0
def test_input():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    spg = Spacegroup3D(Si)
    Si_cvn = spg.conventional_standard_structure
    p = PhonopyInputs(atoms=Si_cvn).generate_all_files()
Ejemplo n.º 12
0
def test_kp():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.2, 0.25]]
    elements = ["Si", "Si"]
    s = Atoms(lattice_mat=box, coords=coords, elements=elements)
    data = get_wien_kpoints(atoms=s, write_file=True)
    cmd = "rm MyKpoints"
    os.system(cmd)
Ejemplo n.º 13
0
def test_cal():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.2, 0.25]]
    elements = ["Si", "Si"]
    atoms = Atoms(lattice_mat=box, coords=coords, elements=elements)
    decorated_atoms, hall_number, wsymbols = get_selective_dyn_decorated_atoms(
        atoms)
    assert (wsymbols, hall_number) == (["i", "i"], 63)
Ejemplo n.º 14
0
def get_selective_dyn_decorated_atoms(atoms):
    """Freeze coordinates based on symmetry."""
    spg = Spacegroup3D(atoms=atoms)  # .spacegroup_data()
    frac_coords = atoms.frac_coords
    hall_number = spg._dataset["hall_number"]
    wdata = get_wyckoff_position_operators(hall_number)["wyckoff"]
    wsymbols = spg._dataset["wyckoffs"]
    info = defaultdict()
    for i in wdata:
        info[i["letter"]] = i["positions"]

    props = []
    for i, j in zip(wsymbols, frac_coords):
        ops = info[i]
        # print ('ops,j',ops, j)

        arr = ops
        new_arr = []
        for ii in arr:
            a = ii.split(",")
            b = []
            for jj in a:
                ind = jj
                if "(" in jj:
                    ind = jj.split("(")[1]  # .split(')')[0]
                if ")" in jj:
                    ind = jj.split(")")[0]  # .split(')')[0]
                # print (a,ind,j)
                if "/" in ind:
                    try:
                        tmp = ind.split("/")
                        ind = float(tmp[0]) / float(tmp[1])
                    except Exception:
                        pass
                try:
                    ind = float(ind)
                except Exception:
                    pass
                b.append(ind)

            new_arr.append(b)
        # print ('arr',arr)
        # print ('coord',j)
        # print ()
        arr_T_F = decorate_T_F(options=new_arr, coord=j)
        props.append(arr_T_F)
        # print ('new_arr',new_arr,j, arr_T_F)
        # print ()
        # print ()
        # print ()
    decorated_atoms = Atoms(
        lattice_mat=atoms.lattice_mat,
        elements=atoms.elements,
        coords=frac_coords,
        cartesian=False,
        props=props,
    )
    return decorated_atoms, hall_number, wsymbols
Ejemplo n.º 15
0
def test_cal():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.2, 0.25]]
    elements = ["Si", "Si"]
    atoms = Atoms(lattice_mat=box, coords=coords, elements=elements)
    decorated_atoms, hall_number, wsymbols = get_selective_dyn_decorated_atoms(
        atoms)
    print(decorated_atoms)
    p = Poscar(decorated_atoms)
    p.write_file('POSCAR')
    #p2 = Poscar.from_file('POSCAR')
    #print (p2)
    assert (wsymbols, hall_number) == (["i", "i"], 63)
Ejemplo n.º 16
0
 def vrun_structure_to_atoms(self, s={}):
     """Convert structure to Atoms object."""
     tmp = s["crystal"]["varray"][0]["v"]
     lattice_mat = np.array([[float(j) for j in i.split()] for i in tmp])
     frac_coords = np.array(
         [[float(j) for j in i.split()] for i in s["varray"]["v"]]
     )
     elements = self.elements
     atoms = Atoms(
         lattice_mat=lattice_mat,
         elements=elements,
         coords=frac_coords,
         cartesian=False,
     )
     return atoms
Ejemplo n.º 17
0
 def final_structure(self):
     """Get final atoms."""
     line = self.data["qes:espresso"][self.set_key]
     if isinstance(line, list):
         line = line[-1]
     elements = []
     pos = []
     lat = []
     lat.append(
         [float(i) for i in line["atomic_structure"]["cell"]["a1"].split()])
     lat.append(
         [float(i) for i in line["atomic_structure"]["cell"]["a2"].split()])
     lat.append(
         [float(i) for i in line["atomic_structure"]["cell"]["a3"].split()])
     if isinstance(line["atomic_structure"]["atomic_positions"]["atom"],
                   list):
         for i in line["atomic_structure"]["atomic_positions"]["atom"]:
             elements.append(i["@name"])
             pos.append([float(j) for j in i["#text"].split()])
         atoms = Atoms(elements=elements,
                       coords=pos,
                       lattice_mat=lat,
                       cartesian=True)
     else:
         elements = [
             line["atomic_structure"]["atomic_positions"]["atom"]["@name"]
         ]
         pos = [[
             float(j) for j in line["atomic_structure"]["atomic_positions"]
             ["atom"]["#text"].split()
         ]]
         atoms = Atoms(elements=elements,
                       coords=pos,
                       lattice_mat=lat,
                       cartesian=True)
     return atoms
Ejemplo n.º 18
0
def test_vacancy():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    v = Vacancy(atoms=Si)
    vacs = v.generate_defects(enforce_c_size=10.0)
    td = vacs[0].to_dict()
    fd = Vacancy.from_dict(td)
    # print ( len(vacs),(vacs[0].to_dict()["defect_structure"].num_atoms))
    # print (vacs[0].to_dict()["defect_structure"])
    assert (
        len(vacs),
        Atoms.from_dict(vacs[0].to_dict()["defect_structure"]).num_atoms,
    ) == (1, 53)
Ejemplo n.º 19
0
def test_inputs():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    print(Si)
    kp = Kpoints3D().automatic_length_mesh(lattice_mat=Si.lattice_mat,
                                           length=20)
    new_file, filename = tempfile.mkstemp()
    qe = QEinfile(Si, kp)
    qe.write_file(filename)
    kp = Kpoints3D().kpath(atoms=Si)
    qe = QEinfile(Si, kp)
    qe.write_file(filename)
    sp = qe.atomic_species_string()
    sp = qe.atomic_cell_params()
    assert qe.input_params['system_params']['nat'] == 2
Ejemplo n.º 20
0
 def refined_atoms(self):
     """Refine atoms based on spacegroup data."""
     phonopy_atoms = (
         self._atoms.lattice_mat,
         self._atoms.frac_coords,
         self._atoms.atomic_numbers,
     )
     lattice, scaled_positions, numbers = spglib.refine_cell(
         phonopy_atoms, self._symprec, self._angle_tolerance)
     elements = self._atoms.elements
     el_dict = {}
     for i in elements:
         el_dict.setdefault(Specie(i).Z, i)
     ref_elements = [el_dict[i] for i in numbers]
     ref_atoms = Atoms(
         lattice_mat=lattice,
         elements=ref_elements,
         coords=scaled_positions,
         cartesian=False,
     )
     return ref_atoms
Ejemplo n.º 21
0
 def primitive_atoms(self):
     """Get primitive atoms."""
     phonopy_atoms = (
         self._atoms.lattice_mat,
         self._atoms.frac_coords,
         self._atoms.atomic_numbers,
     )
     lattice, scaled_positions, numbers = spglib.find_primitive(
         phonopy_atoms, symprec=self._symprec)
     elements = self._atoms.elements
     el_dict = {}
     for i in elements:
         el_dict.setdefault(Specie(i).Z, i)
     prim_elements = [el_dict[i] for i in numbers]
     prim_atoms = Atoms(
         lattice_mat=lattice,
         elements=prim_elements,
         coords=scaled_positions,
         cartesian=False,
     )
     return prim_atoms
Ejemplo n.º 22
0
def test_nbors():
    box = [[5.493642, 0, 0], [0, 5.493642, 0], [0, 0, 5.493642]]
    elements = ["Si", "Si", "Si", "Si", "Si", "Si", "Si", "Si"]
    coords = [
        [0, 0, 0],
        [0.25, 0.25, 0.25],
        [0.000000, 0.500000, 0.500000],
        [0.250000, 0.750000, 0.750000],
        [0.500000, 0.000000, 0.500000],
        [0.750000, 0.250000, 0.750000],
        [0.500000, 0.500000, 0.000000],
        [0.750000, 0.750000, 0.250000],
    ]
    coords = np.array(coords)
    # box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    # coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    # elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    nb = NeighborsAnalysis(Si).get_all_distributions
    tmp = round((nb["rdf"][-3]), 2)
    assert (tmp) == (4.08)
Ejemplo n.º 23
0
    def from_string(lines):
        """Read Poscar from strings, useful in reading files/streams."""
        text = lines.splitlines()
        comment = text[0]
        scale = float(text[1])
        lattice_mat = []
        lattice_mat.append([float(i) for i in text[2].split()])
        lattice_mat.append([float(i) for i in text[3].split()])
        lattice_mat.append([float(i) for i in text[4].split()])
        lattice_mat = scale * np.array(lattice_mat)

        uniq_elements = text[5].split()
        element_count = np.array([int(i) for i in text[6].split()])
        elements = []
        for i, ii in enumerate(element_count):
            for j in range(ii):
                elements.append(uniq_elements[i])
        cartesian = True
        if "d" in text[7] or "D" in text[7]:
            cartesian = False
        # print ('cartesian poscar=',cartesian,text[7])
        num_atoms = int(np.sum(element_count))
        coords = []
        for i in range(num_atoms):
            coords.append([float(i) for i in text[8 + i].split()[0:3]])
        coords = np.array(coords)
        atoms = Atoms(
            lattice_mat=lattice_mat,
            coords=coords,
            elements=elements,
            cartesian=cartesian,
        )
        # print (atoms)
        # formula = atoms.composition.formula

        return Poscar(atoms, comment=comment)
Ejemplo n.º 24
0
 def lammps_to_atoms(self):
     """Convert Lammps data to Atoms object."""
     # n_atoms = len(self._species)
     # n_atom_types = len(self._element_order)
     box = self._lammps_box
     xhi = box[1]
     xlo = box[0]
     yhi = box[3]
     ylo = box[2]
     zhi = box[5]
     zlo = box[4]
     xy = box[6]
     xz = box[7]
     yz = box[8]
     lat = np.array([[xhi - xlo, 0.0, 0.0], [xy, yhi - ylo, 0.0],
                     [xz, yz, zhi - zlo]])
     elements = [self._element_order[i - 1] for i in self._species]
     atoms = Atoms(
         lattice_mat=lat,
         elements=elements,
         coords=self._cart_coords,
         cartesian=True,
     )
     return atoms
Ejemplo n.º 25
0
def test_surf():
    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.25, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    surface = Surface(atoms=Si, indices=[1, 1, 1])
    s = surface.make_surface()
    # print (s.lattice_mat[0][0])
    td = surface.to_dict()
    fd = Surface.from_dict(td)
    print(fd)
    su = [
        0.8582640971273426,
        0.9334963319196496,
        0.9360461382184894,
        0.9419095687284446,
        0.9802042233627004,
        0.9875446840480956,
        1.0120634294466684,
        1.0126231880823566,
        1.0241538763302507,
        1.0315901848682645,
        1.0318271257831195,
        1.0331286888257398,
        1.0344297141291043,
        1.0388709097092674,
        1.040277640596931,
        1.042494119906149,
        1.04453679643896,
        1.0450598648770613,
        1.045076130339553,
        1.0469310544190567,
        1.0491015867538047,
        1.0495494553198788,
        1.0534717916897114,
        1.0535201391639715,
        1.054233162444997,
        1.0579157863887743,
        1.0595676718662346,
        1.0601381085497692,
        1.109580394178689,
    ]

    ml = [
        [0, 0, 1],
        [2, 0, 3],
        [2, 0, 1],
        [1, 0, 1],
        [3, 0, 2],
        [1, 0, 3],
        [3, 1, 1],
        [3, 0, 1],
        [3, 1, 3],
        [3, -1, 1],
        [3, 1, 0],
        [3, 2, 1],
        [3, 3, 1],
        [1, 0, 0],
        [2, 2, 1],
        [3, -1, 3],
        [3, -1, 2],
        [3, 3, 2],
        [3, 2, 2],
        [2, -1, 3],
        [3, 2, 0],
        [3, 2, 3],
        [1, 1, 1],
        [1, 0, 2],
        [3, 1, 2],
        [2, -1, 2],
        [3, -1, 0],
        [2, 2, 3],
        [1, 1, 0],
    ]
    nm = wulff_normals(miller_indices=ml, surface_energies=su)
    # print (nm)
    tmp = [
        [1.0, [0, 0, 1]],
        [3.921600474095634, [2, 0, 3]],
        [2.438716476826076, [2, 0, 1]],
        [1.552041255230461, [1, 0, 1]],
        [4.117819444608784, [3, 0, 2]],
        [3.638612524088821, [1, 0, 3]],
        [3.910957793469126, [3, 1, 1]],
        [3.7310143772286937, [3, 0, 1]],
        [5.201409757790036, [3, 1, 3]],
        [3.9864158271014745, [3, -1, 1]],
        [3.801771366110844, [3, 1, 0]],
        [4.5039907913791675, [3, 2, 1]],
        [5.2535980512015135, [3, 3, 1]],
        [1.2104326782239008, [1, 0, 0]],
        [3.6362151606205986, [2, 2, 1]],
        [5.294555059585646, [3, -1, 3]],
        [4.553725168318604, [3, -1, 2]],
        [5.711255167942817, [3, 3, 2]],
        [5.020551700372963, [3, 2, 2]],
        [4.564163089568084, [2, -1, 3]],
        [4.407255968031299, [3, 2, 0]],
        [5.735790792628303, [3, 2, 3]],
        [2.1259967341689543, [1, 1, 1]],
        [2.744775943349465, [1, 0, 2]],
        [4.595997097917879, [3, 1, 2]],
        [3.6978680219632056, [2, -1, 2]],
        [3.9039815243280183, [3, -1, 0]],
        [5.092909529739627, [2, 2, 3]],
        [1.8283225958570692, [1, 1, 0]],
    ]
    assert (round(s.lattice_mat[0][0], 2), nm) == (7.68, tmp)
Ejemplo n.º 26
0
def test_basic_atoms():

    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.2, 0.25]]
    elements = ["Si", "Si"]
    Si = Atoms(lattice_mat=box, coords=coords, elements=elements)
    dim = get_supercell_dims(Si)
    assert dim == [3, 3, 3]
    polar = Si.check_polar
    Si.props = ["a", "a"]
    vac_pad = VacuumPadding(Si)
    den_2d = round(vac_pad.get_effective_2d_slab().density, 2)
    den_0d = round(vac_pad.get_effective_molecule().density, 2)
    den_lll_red = round(Si.get_lll_reduced_structure().density, 2)
    strng = Si.get_string()
    scell_nat = Si.make_supercell([2, 2, 2]).num_atoms
    scell_nat2 = Si.make_supercell_matrix([[2, 0, 0], [0, 2, 0],
                                           [0, 0, 2]]).num_atoms
    # print("scell_nat,scell_nat2", scell_nat, scell_nat2)
    # print(Si.make_supercell([2, 2, 2]))
    # print()
    # print(Si.make_supercell_matrix([[2, 0, 0], [0, 2, 0], [0, 0, 2]]))
    com = round(Si.get_center_of_mass()[0], 3)
    rem = (Si.make_supercell([2, 2, 2]).remove_site_by_index(site=0)).num_atoms
    prim = Si.get_primitive_atoms
    print(prim.cart_coords)
    assert round(prim.cart_coords[0][0], 2) == round(4.37815150, 2)
    # print ('raw_distance_matrix', prim.raw_distance_matrix)
    # print ('raw_distance_matrix', Si.raw_distance_matrix)
    # print ('distance_matrix', Si.pymatgen_converter().distance_matrix)
    assert round(prim.raw_distance_matrix[0][1],
                 2) == round(4.42386329832851, 2)
    print(prim.raw_angle_matrix)
    d = Si.to_dict()
    new_at = Atoms.from_dict(d)
    angs_a = d["angles"][0]
    Si_2_den = Atoms(
        lattice_mat=d["lattice_mat"],
        coords=d["coords"],
        elements=d["elements"],
    ).density
    Si_xyz = Si.get_xyz_string
    Si.write_xyz(filename="atoms.xyz")
    tmp = Atoms.from_xyz(filename="atoms.xyz")
    cmd = 'rm atoms.xyz'
    os.system(cmd)
    Si.center_around_origin()
    # print ('scell_nat', Si_2)
    assert (
        round(Si.volume, 2),
        Si.atomic_numbers,
        Si.num_atoms,
        Si.frac_coords[0][0],
        Si.cart_coords[0][0],
        round(Si.density, 2),
        Si.spacegroup(),
        Si.pymatgen_converter() != {},
        polar,
        Si.props[0],
        den_2d,
        den_0d,
        round(Si.packing_fraction, 2),
        Si.composition.to_dict(),
        strng != "",
        den_lll_red,
        scell_nat,
        com,
        rem,
        angs_a,
        round(Si_2_den, 2),
    ) == (
        40.03,
        [14, 14],
        2,
        0,
        0.0,
        2.33,
        "C2/m (12)",
        True,
        False,
        "a",
        0.35,
        0.01,
        0.28,
        {
            "Si": 2
        },
        True,
        2.33,
        16,
        0.679,
        15,
        60.0,
        2.33,
    )
    cc = Si.center()
    cc = Si.center(axis=[0, 0, 1])

    m1 = Atoms.from_dict(get_jid_data("JVASP-6640")["atoms"])
    assert m1.check_polar == True
    print("Strain test")
    print(m1)
    m1.apply_strain(0.1)
    print(m1)
    assert m1.lattice_mat[2][2] == 32.8717576
    m1.apply_strain([0, 0, 0.1])
    assert m1.lattice_mat[2][2] == 36.158933360000006
    filename = "atoms.cif"
    m1.write_cif(filename)
    a = Atoms.from_cif(filename)
    filename = "POSCAR"
    m1.write_poscar(filename)
    m2 = Atoms.from_poscar(filename)

    filename = "atoms.xyz"
    m1.write_xyz(filename)
    m3 = Atoms.from_xyz(filename)

    cmd = "rm atoms.xyz POSCAR atoms.cif"
    os.system(cmd)
Ejemplo n.º 27
0
    def conventional_standard_structure(self,
                                        tol=1e-5,
                                        international_monoclinic=True):
        """
        Give a conventional cell according to certain conventions.

        The conventionss are defined in Setyawan, W., & Curtarolo,
        S. (2010). High-throughput electronic band structure calculations:
        Challenges and tools. Computational Materials Science,
        49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010
        They basically enforce as much as possible
        norm(a1)<norm(a2)<norm(a3)
        Returns:
            The structure in a conventional standardized cell
        """
        struct = self.refined_atoms
        latt = struct.lattice
        latt_type = self.lattice_system
        sorted_lengths = sorted(latt.abc)
        sorted_dic = sorted(
            [{
                "vec": latt.matrix[i],
                "length": latt.abc[i],
                "orig_index": i
            } for i in [0, 1, 2]],
            key=lambda k: k["length"],
        )

        if latt_type in ("orthorhombic", "cubic"):
            # you want to keep the c axis where it is
            # to keep the C- settings
            transf = np.zeros(shape=(3, 3))
            if self.space_group_symbol.startswith("C"):
                transf[2] = [0, 0, 1]
                a, b = sorted(latt.abc[:2])
                sorted_dic = sorted(
                    [{
                        "vec": latt.matrix[i],
                        "length": latt.abc[i],
                        "orig_index": i
                    } for i in [0, 1]],
                    key=lambda k: k["length"],
                )
                for i in range(2):
                    transf[i][sorted_dic[i]["orig_index"]] = 1
                c = latt.abc[2]
            elif self.space_group_symbol.startswith(
                    "A"
            ):  # change to C-centering to match Setyawan/Curtarolo convention
                transf[2] = [1, 0, 0]
                a, b = sorted(latt.abc[1:])
                sorted_dic = sorted(
                    [{
                        "vec": latt.matrix[i],
                        "length": latt.abc[i],
                        "orig_index": i
                    } for i in [1, 2]],
                    key=lambda k: k["length"],
                )
                for i in range(2):
                    transf[i][sorted_dic[i]["orig_index"]] = 1
                c = latt.abc[0]
            else:
                for i in range(len(sorted_dic)):
                    transf[i][sorted_dic[i]["orig_index"]] = 1
                a, b, c = sorted_lengths
            latt = Lattice.orthorhombic(a, b, c)

        elif latt_type == "tetragonal":
            # find the "a" vectors
            # it is basically the vector repeated two times
            transf = np.zeros(shape=(3, 3))
            a, b, c = sorted_lengths
            for d in range(len(sorted_dic)):
                transf[d][sorted_dic[d]["orig_index"]] = 1

            if abs(b - c) < tol and abs(a - c) > tol:
                a, c = c, a
                transf = np.dot([[0, 0, 1], [0, 1, 0], [1, 0, 0]], transf)
            latt = Lattice.tetragonal(a, c)
        elif latt_type in ("hexagonal", "rhombohedral"):
            # for the conventional cell representation,
            # we allways show the rhombohedral lattices as hexagonal

            # check first if we have the refined structure shows a rhombohedral
            # cell
            # if so, make a supercell
            a, b, c = latt.abc
            if np.all(np.abs([a - b, c - b, a - c]) < 0.001):
                struct.make_supercell(((1, -1, 0), (0, 1, -1), (1, 1, 1)))
                a, b, c = sorted(struct.lattice.abc)

            if abs(b - c) < 0.001:
                a, c = c, a
            new_matrix = [
                [a / 2, -a * np.sqrt(3) / 2, 0],
                [a / 2, a * np.sqrt(3) / 2, 0],
                [0, 0, c],
            ]
            latt = Lattice(new_matrix)
            transf = np.eye(3, 3)

        elif latt_type == "monoclinic":
            # You want to keep the c axis where it is to keep the C- settings

            if self.space_group_symbol.startswith("C"):
                transf = np.zeros(shape=(3, 3))
                transf[2] = [0, 0, 1]
                sorted_dic = sorted(
                    [{
                        "vec": latt.matrix[i],
                        "length": latt.abc[i],
                        "orig_index": i
                    } for i in [0, 1]],
                    key=lambda k: k["length"],
                )
                a = sorted_dic[0]["length"]
                b = sorted_dic[1]["length"]
                c = latt.abc[2]
                new_matrix = None
                for t in itertools.permutations(list(range(2)), 2):
                    m = latt.matrix
                    latt2 = Lattice([m[t[0]], m[t[1]], m[2]])
                    lengths = latt2.abc
                    angles = latt2.angles
                    if angles[0] > 90:
                        # if the angle is > 90 we invert a and b to get
                        # an angle < 90
                        a, b, c, alpha, beta, gamma = Lattice(
                            [-m[t[0]], -m[t[1]], m[2]]).parameters
                        transf = np.zeros(shape=(3, 3))
                        transf[0][t[0]] = -1
                        transf[1][t[1]] = -1
                        transf[2][2] = 1
                        alpha = np.pi * alpha / 180
                        new_matrix = [
                            [a, 0, 0],
                            [0, b, 0],
                            [0, c * cos(alpha), c * sin(alpha)],
                        ]
                        continue

                    elif angles[0] < 90:
                        transf = np.zeros(shape=(3, 3))
                        # print ('464-470')
                        transf[0][t[0]] = 1
                        transf[1][t[1]] = 1
                        transf[2][2] = 1
                        a, b, c = lengths
                        alpha = np.pi * angles[0] / 180
                        new_matrix = [
                            [a, 0, 0],
                            [0, b, 0],
                            [0, c * cos(alpha), c * sin(alpha)],
                        ]

                if new_matrix is None:
                    # print ('479-482')
                    # this if is to treat the case
                    # where alpha==90 (but we still have a monoclinic sg
                    new_matrix = [[a, 0, 0], [0, b, 0], [0, 0, c]]
                    transf = np.zeros(shape=(3, 3))
                    for c in range(len(sorted_dic)):
                        transf[c][sorted_dic[c]["orig_index"]] = 1
            # if not C-setting
            else:
                # try all permutations of the axis
                # keep the ones with the non-90 angle=alpha
                # and b<c
                new_matrix = None
                for t in itertools.permutations(list(range(3)), 3):
                    m = latt.matrix
                    a, b, c, alpha, beta, gamma = Lattice(
                        [m[t[0]], m[t[1]], m[t[2]]]).parameters
                    if alpha > 90 and b < c:
                        a, b, c, alpha, beta, gamma = Lattice(
                            [-m[t[0]], -m[t[1]], m[t[2]]]).parameters
                        transf = np.zeros(shape=(3, 3))
                        transf[0][t[0]] = -1
                        transf[1][t[1]] = -1
                        transf[2][t[2]] = 1
                        alpha = np.pi * alpha / 180
                        new_matrix = [
                            [a, 0, 0],
                            [0, b, 0],
                            [0, c * cos(alpha), c * sin(alpha)],
                        ]
                        continue
                    elif alpha < 90 and b < c:
                        # print ('510-515')
                        transf = np.zeros(shape=(3, 3))
                        transf[0][t[0]] = 1
                        transf[1][t[1]] = 1
                        transf[2][t[2]] = 1
                        alpha = np.pi * alpha / 180
                        new_matrix = [
                            [a, 0, 0],
                            [0, b, 0],
                            [0, c * cos(alpha), c * sin(alpha)],
                        ]
                if new_matrix is None:
                    # print ('523-530')
                    # this if is to treat the case
                    # where alpha==90 (but we still have a monoclinic sg
                    new_matrix = [
                        [sorted_lengths[0], 0, 0],
                        [0, sorted_lengths[1], 0],
                        [0, 0, sorted_lengths[2]],
                    ]
                    transf = np.zeros(shape=(3, 3))
                    for c in range(len(sorted_dic)):
                        transf[c][sorted_dic[c]["orig_index"]] = 1

            if international_monoclinic:
                # The above code makes alpha the non-right angle.
                # The following will convert to proper international convention
                # that beta is the non-right angle.
                op = [[0, 1, 0], [1, 0, 0], [0, 0, -1]]
                transf = np.dot(op, transf)
                new_matrix = np.dot(op, new_matrix)
                beta = Lattice(new_matrix).beta
                if beta < 90:
                    op = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]]
                    transf = np.dot(op, transf)
                    new_matrix = np.dot(op, new_matrix)

            latt = Lattice(new_matrix)

        elif latt_type == "triclinic":
            # we use a LLL Minkowski-like reduction for the triclinic cells
            struct = struct.get_lll_reduced_structure()

            a, b, c = latt.abc  # lengths
            alpha, beta, gamma = [np.pi * i / 180 for i in latt.angles]
            new_matrix = None
            test_matrix = [
                [a, 0, 0],
                [b * cos(gamma), b * sin(gamma), 0.0],
                [
                    c * cos(beta),
                    c * (cos(alpha) - cos(beta) * cos(gamma)) / sin(gamma),
                    c * np.sqrt(
                        sin(gamma)**2 - cos(alpha)**2 - cos(beta)**2 +
                        2 * cos(alpha) * cos(beta) * cos(gamma)) / sin(gamma),
                ],
            ]

            def is_all_acute_or_obtuse(m):
                recp_angles = np.array(Lattice(m).reciprocal_lattice().angles)
                return np.all(recp_angles <= 90) or np.all(recp_angles > 90)

            if is_all_acute_or_obtuse(test_matrix):
                transf = np.eye(3)
                new_matrix = test_matrix

            test_matrix = [
                [-a, 0, 0],
                [b * cos(gamma), b * sin(gamma), 0.0],
                [
                    -c * cos(beta),
                    -c * (cos(alpha) - cos(beta) * cos(gamma)) / sin(gamma),
                    -c * np.sqrt(
                        sin(gamma)**2 - cos(alpha)**2 - cos(beta)**2 +
                        2 * cos(alpha) * cos(beta) * cos(gamma)) / sin(gamma),
                ],
            ]

            if is_all_acute_or_obtuse(test_matrix):
                transf = [[-1, 0, 0], [0, 1, 0], [0, 0, -1]]
                new_matrix = test_matrix

            test_matrix = [
                [-a, 0, 0],
                [-b * cos(gamma), -b * sin(gamma), 0.0],
                [
                    c * cos(beta),
                    c * (cos(alpha) - cos(beta) * cos(gamma)) / sin(gamma),
                    c * np.sqrt(
                        sin(gamma)**2 - cos(alpha)**2 - cos(beta)**2 +
                        2 * cos(alpha) * cos(beta) * cos(gamma)) / sin(gamma),
                ],
            ]

            if is_all_acute_or_obtuse(test_matrix):
                transf = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]]
                new_matrix = test_matrix

            test_matrix = [
                [a, 0, 0],
                [-b * cos(gamma), -b * sin(gamma), 0.0],
                [
                    -c * cos(beta),
                    -c * (cos(alpha) - cos(beta) * cos(gamma)) / sin(gamma),
                    -c * np.sqrt(
                        sin(gamma)**2 - cos(alpha)**2 - cos(beta)**2 +
                        2 * cos(alpha) * cos(beta) * cos(gamma)) / sin(gamma),
                ],
            ]
            if is_all_acute_or_obtuse(test_matrix):
                transf = [[1, 0, 0], [0, -1, 0], [0, 0, -1]]
                new_matrix = test_matrix

            latt = Lattice(new_matrix)

        new_coords = np.dot(transf, np.transpose(struct.frac_coords)).T
        new_struct = Atoms(
            lattice_mat=latt.matrix,
            elements=struct.elements,
            coords=new_coords,
            cartesian=False,
        )
        return new_struct
Ejemplo n.º 28
0
    def read_data(
        self,
        filename="lammps.data",
        element_order=[],
        potential_file="pot.mod",
        verbose=True,
    ):
        """Read Lammps data file."""
        # n_atoms = len(self._species)
        if element_order == []:
            # Reading potential file for element order
            if verbose:
                print("element_order is empty, reading from", potential_file)
            pot_file = open(potential_file, "r")
            lines = pot_file.read().splitlines()
            pot_file.close()
            symb = []
            # count = 0

            for i, line in enumerate(lines):
                if "pair_coeff" in line.split():
                    sp = line.split()
                    # print("spsplit", sp, os.getcwd())
                    for el in sp:
                        try:
                            if str(Specie(el).Z) != "nan":
                                # if el=='M':
                                #    el='Mo'
                                # count=count+1
                                # if count >4:
                                symb.append(Specie(el).symbol)
                        except Exception:
                            pass
        else:
            symb = [Specie(i).symbol for i in element_order]

        # print("symb=", symb)
        f = open(filename, "r")
        lines = f.read().splitlines()
        for i, line in enumerate(lines):
            if "atoms" in line.split():
                natoms = int(line.split()[0])
            if "types" in line.split():
                # print(line)
                ntypes = int(line.split()[0])
            if "xlo" in line.split():
                xlo = float(line.split()[0])
                xhi = float(line.split()[1])
            if "ylo" in line.split():
                ylo = float(line.split()[0])
                yhi = float(line.split()[1])
            if "zlo" in line.split():
                zlo = float(line.split()[0])
                zhi = float(line.split()[1])
            if "xy" in line.split():
                xy = float(line.split()[0])
                xz = float(line.split()[1])
                yz = float(line.split()[2])
        if len(symb) != ntypes:
            ValueError("Something wrong in atom type assignment", len(symb),
                       ntypes)
        lat = np.array([[xhi - xlo, 0.0, 0.0], [xy, yhi - ylo, 0.0],
                        [xz, yz, zhi - zlo]])
        typ = np.empty((natoms), dtype="S20")
        x = np.zeros((natoms))
        y = np.zeros((natoms))
        z = np.zeros((natoms))
        q = np.zeros((natoms))
        coords = list()
        for i, line in enumerate(lines):
            if "Atoms" in line.split():
                for j in range(0, natoms):
                    # print int(((lines[j+2]).split()[1]))-1
                    typ[j] = symb[int(((lines[i + j + 2]).split()[1])) - 1]
                    q[j] = (lines[i + j + 2]).split()[2]
                    x[j] = (lines[i + j + 2]).split()[3]
                    y[j] = (lines[i + j + 2]).split()[4]
                    z[j] = (lines[i + j + 2]).split()[5]
                    coords.append([x[j], y[j], z[j]])
        f.close()
        # print ("info",(typ),'coo',(coords),'latt',lat)
        typ_sp = [str(i, "utf-8") for i in typ]
        # print ('typ_sp',typ_sp)
        atoms = Atoms(
            lattice_mat=lat,
            elements=typ_sp,
            coords=np.array(coords),
            cartesian=True,
        )
        return atoms
Ejemplo n.º 29
0
            found = False
            for hkl2 in unique.keys():
                if is_perm(hkl1, hkl2):
                    found = True
                    unique[hkl2].append(hkl1)
                    break
            if not found:
                unique[hkl1].append(hkl1)

        pretty_unique = {}
        for k, v in unique.items():
            pretty_unique[sorted(v)[-1]] = len(v)

        return pretty_unique


if __name__ == "__main__":
    # h=create_index()
    # print (h,len(h))
    from jarvis.core.atoms import Atoms

    box = [[2.715, 2.715, 0], [0, 2.715, 2.715], [2.715, 0, 2.715]]
    coords = [[0, 0, 0], [0.25, 0.2, 0.25]]
    elements = ["Si", "Si"]
    atoms = Atoms(lattice_mat=box, coords=coords, elements=elements)
    a, b, c, d = XRD().simulate(atoms=atoms)
    # print("theta,d_hkls,intens", a, b, c)
    print("a=", a)
    print("b=", b)
    print("c=", c)
Ejemplo n.º 30
0
    def make_surface(self):
        """Generate specified surface. Modified from ase package."""
        atoms = self.atoms
        h_index, k_index, l_index = self.indices
        h0, k0, l0 = self.indices == 0
        if h0 and k0 or h0 and l0 or k0 and l0:  # if two indices are zero
            if not h0:
                c1, c2, c3 = [(0, 1, 0), (0, 0, 1), (1, 0, 0)]
            if not k0:
                c1, c2, c3 = [(0, 0, 1), (1, 0, 0), (0, 1, 0)]
            if not l0:
                c1, c2, c3 = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
        else:
            p, q = ext_gcd(k_index, l_index)
            a1, a2, a3 = self.atoms.lattice_mat  # .lat_lengths()

            # constants describing the dot product of basis c1 and c2:
            # dot(c1,c2) = k1+i*k2, i in Z
            k1 = np.dot(
                p * (k_index * a1 - h_index * a2) + q *
                (l_index * a1 - h_index * a3),
                l_index * a2 - k_index * a3,
            )
            k2 = np.dot(
                l_index * (k_index * a1 - h_index * a2) - k_index *
                (l_index * a1 - h_index * a3),
                l_index * a2 - k_index * a3,
            )

            if abs(k2) > self.tol:
                i = -int(round(k1 / k2))
                p, q = p + i * l_index, q - i * k_index

            a, b = ext_gcd(p * k_index + q * l_index, h_index)

            c1 = (p * k_index + q * l_index, -p * h_index, -q * h_index)
            c2 = np.array((0, l_index, -k_index)) // abs(gcd(l_index, k_index))
            c3 = (b, a * p, a * q)
        lattice = atoms.lattice_mat  # .lat_lengths()
        basis = np.array([c1, c2, c3])
        scaled = np.linalg.solve(basis.T, np.array(atoms.frac_coords).T).T
        scaled -= np.floor(scaled + self.tol)
        new_coords = scaled
        tmp_cell = np.dot(basis, lattice)
        M = np.linalg.solve(lattice, tmp_cell)
        cart_coords = np.dot(scaled, lattice)
        new_coords = np.dot(cart_coords, M)

        new_atoms = Atoms(
            lattice_mat=tmp_cell,
            coords=new_coords,
            elements=atoms.elements,
            cartesian=True,
        )

        surf_atoms = new_atoms.make_supercell_matrix([1, 1, self.layers])
        # print("supercell_cart_coords", surf_atoms.frac_coords)

        new_lat = surf_atoms.lattice_mat  # lat_lengths()
        a1 = new_lat[0]
        a2 = new_lat[1]
        a3 = new_lat[2]
        new_lat = np.array([
            a1,
            a2,
            np.cross(a1, a2) * np.dot(a3, np.cross(a1, a2)) /
            norm(np.cross(a1, a2))**2,
        ])

        a1 = new_lat[0]
        a2 = new_lat[1]
        a3 = new_lat[2]
        # print("a1,a2,a3", new_lat)

        latest_lat = np.array([
            (np.linalg.norm(a1), 0, 0),
            (
                np.dot(a1, a2) / np.linalg.norm(a1),
                np.sqrt(
                    np.linalg.norm(a2)**2 -
                    (np.dot(a1, a2) / np.linalg.norm(a1))**2),
                0,
            ),
            (0, 0, np.linalg.norm(a3)),
        ])

        M = np.linalg.solve(new_lat, latest_lat)

        new_cart_coords = surf_atoms.cart_coords  # np.dot(scaled,lattice)

        new_coords = np.dot(new_cart_coords, M)

        new_atoms = Atoms(
            lattice_mat=latest_lat,
            elements=surf_atoms.elements,
            coords=new_coords,
            cartesian=True,
        ).center_around_origin()

        frac_coords = new_atoms.frac_coords

        frac_coords[:] = frac_coords[:] % 1
        new_atoms = Atoms(
            lattice_mat=latest_lat,
            elements=surf_atoms.elements,
            coords=frac_coords,
            cartesian=False,
        )
        new_lat = new_atoms.lattice_mat
        new_cart_coords = new_atoms.cart_coords
        elements = new_atoms.elements
        new_lat[2][2] = new_lat[2][2] + self.vacuum
        with_vacuum_atoms = Atoms(
            lattice_mat=new_lat,
            elements=elements,
            coords=new_cart_coords,
            cartesian=True,
        )
        # new_atoms.center()
        # print (with_vacuum_atoms)
        return with_vacuum_atoms