def test_species_order():
    lattice = Lattice.orthorhombic(5, 6, 7)
    coords = [
        [0.0, 0.0, 0.0],
        [0.5, 0.5, 0.0],
        [0.5, 0.0, 0.5],
        [0.0, 0.5, 0.5],

        [0.0, 0.0, 0.5],
        [0.0, 0.5, 0.0],
        [0.5, 0.0, 0.0],
        [0.5, 0.5, 0.5],
    ]
    structure = Structure(lattice=lattice,
                          species=["H"] * 4 + ["He"] * 4,
                          coords=coords)
    supercell = structure * [1, 1, 2]
    actual = [e.specie for e in StructureSymmetrizer(supercell).conventional]
    expected = [Element.H] * 4 + [Element.He] * 4
    assert actual == expected
Exemple #2
0
    def __init__(self,
                 primitive_structure: IStructure,
                 matrix_to_conv_cell: Optional[List[List[int]]] = None,
                 symprec: float = defaults.symmetry_length_tolerance,
                 angle_tolerance: float = defaults.symmetry_angle_tolerance,
                 raise_error: bool = True,
                 **supercell_kwargs):

        self.primitive_structure = primitive_structure
        self.symmetrizer = StructureSymmetrizer(
            primitive_structure,
            symprec=symprec,
            angle_tolerance=angle_tolerance)
        if primitive_structure != self.symmetrizer.primitive:
            logger.warning(
                "The input structure is different from the primitive one,"
                "which might be due to the difference of symprec used in"
                "the pydefect and unitcell conversion.")
            logger.warning("\n".join([
                "Input lattice:", f"{primitive_structure.lattice}", "",
                "Primitive structure lattice:",
                f"{self.symmetrizer.primitive.lattice}", "",
                "Input structure:", f"{primitive_structure}", "",
                "Primitive structure:", f"{self.symmetrizer.primitive}"
            ]))
            if raise_error:
                raise NotPrimitiveError

        self.sg_symbol = self.symmetrizer.spglib_sym_data["international"]
        self.conv_structure = self.symmetrizer.conventional
        crystal_system, center = str(self.symmetrizer.bravais)

        centering = Centering(center)
        self.conv_multiplicity = centering.conv_multiplicity
        self.conv_trans_mat = centering.primitive_to_conv

        self._matrix = matrix_to_conv_cell
        self._supercell_kwargs = supercell_kwargs

        self._generate_supercell(crystal_system)
        self._generate_supercell_info()
def test_symmetrize_defect_structure():
    structure = Structure.from_str(fmt="POSCAR",
                                   input_string="""Mg4 O3
1.00000000000000
5 0 0
0 5 0
0 0 5
Mg   O
4     3
Direct
0.0051896248240553  0.9835077947659414  0.9945137498637422
0.0047282952713914  0.4827940046010823  0.4942929782542009
0.5040349492352973  0.9821499237428384  0.4944941755970405
0.5058945352747628  0.4828206016032297  0.9940420309511140
0.5045613848356609  0.4811103128264023  0.4933877756337353
0.0013796816599694  0.9829379087234287  0.4953360299212051
0.0083465288988691  0.4848714537370853  0.9941122597789658""")
    structure_symmetrizer = StructureSymmetrizer(
        structure, defaults.symmetry_length_tolerance,
        defaults.symmetry_angle_tolerance)
    actual = symmetrize_defect_structure(structure_symmetrizer,
                                         anchor_atom_idx=1,
                                         anchor_atom_coord=np.array(
                                             [0.0, 0.5, 0.5]))
    expected = Structure.from_str(fmt="POSCAR",
                                  input_string="""Mg4 O3
1.00000000000000
5 0 0
0 5 0
0 0 5
Mg   O
4     3
Direct
0.0 0.0 0.0
0.0 0.5 0.5
0.5 0.0 0.5
0.5 0.5 0.0
0.5 0.5 0.5
0.0 0.0 0.5
0.0 0.5 0.0""")
    assert actual == expected
def test_symmetrize_defect_structure_wo_anchor():
    structure = Structure.from_str(fmt="POSCAR",
                                   input_string="""Mg4 O3
1.00000000000000
5 0 0
0 5 0
0 0 5
Mg   O
4     3
Direct
0.01 0.01 0.01
0.01 0.51 0.51
0.51 0.01 0.51
0.51 0.51 0.01
0.51 0.51 0.51
0.01 0.01 0.51
0.01 0.51 0.01""")
    structure_symmetrizer = StructureSymmetrizer(structure)
    actual = symmetrize_defect_structure(
        structure_symmetrizer=structure_symmetrizer)
    expected = Structure.from_str(fmt="POSCAR",
                                  input_string="""Mg4 O3
1.00000000000000
5 0 0
0 5 0
0 0 5
Mg   O
4     3
Direct
0.01 0.01 0.01
0.01 0.51 0.51
0.51 0.01 0.51
0.51 0.51 0.01
0.51 0.51 0.51
0.01 0.01 0.51
0.01 0.51 0.01""")
    assert actual == expected
Exemple #5
0
    def _create_defect_structures(
        self, defect: SimpleDefect
    ) -> Tuple[IStructure, Coords, str, Optional[IStructure], Optional[Tuple[
            PerturbedSite, ...]], Optional[str]]:

        structure = copy_to_structure(self.supercell_info.structure)

        if defect.out_atom[0] == "i":
            index = int(defect.out_atom[1:]) - 1
            site = self.supercell_info.interstitials[index]
            cutoff = self.supercell_info.interstitial_coords(index).cutoff
            coords = self.supercell_info.interstitials[index].frac_coords
        else:
            site = self.supercell_info.sites[defect.out_atom]
            cutoff = self.supercell_info.coords(defect.out_atom).cutoff
            removed_site_index = site.equivalent_atoms[0]
            coords = structure.pop(removed_site_index).frac_coords

        if defaults.displace_distance:
            p_structure, p_sites = perturb_structure(structure, coords, cutoff)

            p_site_symmetry = StructureSymmetrizer(
                p_structure, defaults.symmetry_length_tolerance,
                defaults.symmetry_angle_tolerance).point_group

            if defect.in_atom:
                add_atom_to_structure(structure, defect.in_atom, coords)
                add_atom_to_structure(p_structure, defect.in_atom, coords)

            return (to_istructure(structure),
                    tuple(coords), site.site_symmetry,
                    to_istructure(p_structure), p_sites, p_site_symmetry)
        else:
            if defect.in_atom:
                add_atom_to_structure(structure, defect.in_atom, coords)
            return (to_istructure(structure), tuple(coords),
                    site.site_symmetry, None, None, None)
Exemple #6
0
def make_defect_entry(name: str, charge: int, perfect_structure: IStructure,
                      defect_structure: IStructure):

    analyzer = DefectStructureComparator(perfect_structure, defect_structure)

    species = []
    frac_coords = []
    for d, p in enumerate(analyzer.p_to_d):
        if p is None:
            site = defect_structure[d]
        else:
            site = perfect_structure[p]
        species.append(site.specie)
        frac_coords.append(site.frac_coords)

    initial_structure = IStructure(perfect_structure.lattice, species,
                                   frac_coords)
    symmetrizer = StructureSymmetrizer(initial_structure)

    return DefectEntry(name=name,
                       charge=charge,
                       structure=initial_structure,
                       site_symmetry=symmetrizer.point_group,
                       defect_center=tuple(analyzer.defect_center_coord))
Exemple #7
0
def append_interstitial(supercell_info: SupercellInfo,
                        unitcell_structure: Union[Structure, IStructure],
                        frac_coords: List[Union[List[float], Coords]],
                        infos: List[str]
                        ) -> SupercellInfo:
    """
    inv_trans_mat must be multiplied with coords from the right as the
    trans_mat is multiplied to the unitcell lattice vector from the left.
    see __mul__ of IStructure in pymatgen.
    x_u, x_s means the frac coordinates in unitcell and supercell,
    while a, b, c are the unitcell lattice vector.
    (a_u, b_u, c_u) . (a, b, c) = (a_s, b_s, c_s) . trans_mat . (a, b, c)
    (a_u, b_u, c_u) = (a_s, b_s, c_s) . trans_mat
    so, (a_s, b_s, c_s) = (a_u, b_u, c_u) . inv_trans_ma
    """
    if supercell_info.unitcell_structure and \
            supercell_info.unitcell_structure != unitcell_structure:
        raise NotPrimitiveError

    if isinstance(frac_coords[0], float):
        frac_coords = [frac_coords]

    for fcoord, info in zip(frac_coords, infos):
        us = Structure.from_dict(unitcell_structure.as_dict())
        us.append(species=Element.H, coords=fcoord)
        symmetrizer = StructureSymmetrizer(us)
        site_symm = symmetrizer.spglib_sym_data["site_symmetry_symbols"][-1]

        inv_matrix = inv(np.array(supercell_info.transformation_matrix))
        new_coords = np.dot(fcoord, inv_matrix).tolist()

        supercell_info.interstitials.append(
            Interstitial(frac_coords=new_coords,
                         site_symmetry=site_symm,
                         info=info))
    return supercell_info
def test_():
    structure = Structure.from_str(""" Na2 Cu2 O4
1.0
1.8088488050 -5.4059198794 0.0000000000
1.8088488050 5.4059198794 0.0000000000
0.0000000000 0.0000000000 5.3190514901
Na Cu O
2 2 4
direct
0.7123738820 0.2876261180 0.2500000000 Na
0.2876261180 0.7123738820 0.7500000000 Na
0.9970663194 0.0029336806 0.2500000000 Cu
0.0029336806 0.9970663194 0.7500000000 Cu
0.1138815169 0.8861184831 0.4939795157 O
0.8861184831 0.1138815169 0.5060204843 O
0.1138815169 0.8861184831 0.0060204843 O
0.8861184831 0.1138815169 0.9939795157 O 
""", fmt="POSCAR")
    symmetrizer = StructureSymmetrizer(structure)
    print(symmetrizer.primitive)
    sstructure = Structure.from_str(""" Na24 Cu24 O48
1.0
10.853093 0.000000 0.000000
0.000000 10.811840 0.000000
0.000000 0.000000 10.638103
Na Cu O
24 24 48
direct
0.166667 -0.212374 0.125000 Na
0.166667 -0.212374 0.625000 Na
0.500000 -0.212374 0.125000 Na
0.500000 -0.212374 0.625000 Na
0.833333 -0.212374 0.125000 Na
0.833333 -0.212374 0.625000 Na
0.333333 0.287626 0.125000 Na
0.333333 0.287626 0.625000 Na
0.666667 0.287626 0.125000 Na
0.666667 0.287626 0.625000 Na
1.000000 0.287626 0.125000 Na
1.000000 0.287626 0.625000 Na
0.166667 0.212374 0.375000 Na
0.166667 0.212374 0.875000 Na
0.500000 0.212374 0.375000 Na
0.500000 0.212374 0.875000 Na
0.833333 0.212374 0.375000 Na
0.833333 0.212374 0.875000 Na
0.333333 0.712374 0.375000 Na
0.333333 0.712374 0.875000 Na
0.666667 0.712374 0.375000 Na
0.666667 0.712374 0.875000 Na
1.000000 0.712374 0.375000 Na
1.000000 0.712374 0.875000 Na
0.166667 -0.497066 0.125000 Cu
0.166667 -0.497066 0.625000 Cu
0.500000 -0.497066 0.125000 Cu
0.500000 -0.497066 0.625000 Cu
0.833333 -0.497066 0.125000 Cu
0.833333 -0.497066 0.625000 Cu
0.333333 0.002934 0.125000 Cu
0.333333 0.002934 0.625000 Cu
0.666667 0.002934 0.125000 Cu
0.666667 0.002934 0.625000 Cu
1.000000 0.002934 0.125000 Cu
1.000000 0.002934 0.625000 Cu
0.166667 0.497066 0.375000 Cu
0.166667 0.497066 0.875000 Cu
0.500000 0.497066 0.375000 Cu
0.500000 0.497066 0.875000 Cu
0.833333 0.497066 0.375000 Cu
0.833333 0.497066 0.875000 Cu
0.333333 0.997066 0.375000 Cu
0.333333 0.997066 0.875000 Cu
0.666667 0.997066 0.375000 Cu
0.666667 0.997066 0.875000 Cu
1.000000 0.997066 0.375000 Cu
1.000000 0.997066 0.875000 Cu
0.166667 0.386118 0.246990 O
0.166667 0.386118 0.746990 O
0.500000 0.386118 0.246990 O
0.500000 0.386118 0.746990 O
0.833333 0.386118 0.246990 O
0.833333 0.386118 0.746990 O
0.333333 0.886118 0.246990 O
0.333333 0.886118 0.746990 O
0.666667 0.886118 0.246990 O
0.666667 0.886118 0.746990 O
1.000000 0.886118 0.246990 O
1.000000 0.886118 0.746990 O
0.166667 -0.386118 0.253010 O
0.166667 -0.386118 0.753010 O
0.500000 -0.386118 0.253010 O
0.500000 -0.386118 0.753010 O
0.833333 -0.386118 0.253010 O
0.833333 -0.386118 0.753010 O
0.333333 0.113882 0.253010 O
0.333333 0.113882 0.753010 O
0.666667 0.113882 0.253010 O
0.666667 0.113882 0.753010 O
1.000000 0.113882 0.253010 O
1.000000 0.113882 0.753010 O
0.166667 0.386118 0.003010 O
0.166667 0.386118 0.503010 O
0.500000 0.386118 0.003010 O
0.500000 0.386118 0.503010 O
0.833333 0.386118 0.003010 O
0.833333 0.386118 0.503010 O
0.333333 0.886118 0.003010 O
0.333333 0.886118 0.503010 O
0.666667 0.886118 0.003010 O
0.666667 0.886118 0.503010 O
1.000000 0.886118 0.003010 O
1.000000 0.886118 0.503010 O
0.166667 -0.386118 0.496990 O
0.166667 -0.386118 0.996990 O
0.500000 -0.386118 0.496990 O
0.500000 -0.386118 0.996990 O
0.833333 -0.386118 0.496990 O
0.833333 -0.386118 0.996990 O
0.333333 0.113882 0.496990 O
0.333333 0.113882 0.996990 O
0.666667 0.113882 0.496990 O
0.666667 0.113882 0.996990 O
1.000000 0.113882 0.496990 O
1.000000 0.113882 0.996990 O""", fmt="POSCAR")
    symmetrizer = StructureSymmetrizer(sstructure)
    print(symmetrizer.primitive)
Exemple #9
0
def test_symmetrize_defect_structure_2():
    structure = Structure.from_str(fmt="POSCAR", input_string="""Mg48 N31
   1.00000000000000
    10.00    0.00    0.00
     0.00   10.00    0.00
     0.00    0.00   10.00
  N
    31
Direct
  0.9998735951099533  0.9999339271342436  0.9998810782738516
  0.4998325344890802  0.0000864604371742  0.0001093145892668
  0.9999579188430090  0.5001853666498661  0.0001277381372233
  0.2491639910909313  0.2182663238872422  0.4987861655656971
  0.2808293379596023  0.4991743721150215  0.7498359204125151
  0.5007987323114946  0.2498921962049820  0.2191539974347521
  0.2186260754052398  0.4998463318536253  0.2504951842089369
  0.5003683092799207  0.7505911171114192  0.2814698995089699
  0.7491029691281099  0.2824156531954642  0.4998653178588484
  0.2496769296641759  0.2810133141130393  0.0008972384265746
  0.2179934993920654  0.0013328906653882  0.7491830895564036
  0.9985995146190305  0.2494223137356002  0.2817274775328684
  0.2819549960242611  0.0002510594995684  0.2492863143591961
  0.9999066837513126  0.7494408251560003  0.2182162389686653
  0.7503446162775589  0.2186089947761758  0.0001821657373426
  0.5000178504783079  0.5000386610406409  0.9999895875233165
  0.4999380720704565  0.5002342427150381  0.5000689317878368
  0.0000976472392296  0.5000243131273407  0.5000777225283457
  0.5001616481443207  0.0002089601314523  0.4998675396277079
  0.7502599885437249  0.7191435719333086  0.9992528941462950
  0.7820064323950149  0.9990033992670391  0.2509026823008185
  0.0012722293791043  0.7506950871201497  0.7182763220765622
  0.7176368346430237  0.9998582962107960  0.7509680009789932
  0.0000228430868177  0.2509182464808006  0.7821761073165092
  0.2495215811710665  0.7814963684974714  0.9998566240987685
  0.7508300518084354  0.7818602560717594  0.5013867902350881
  0.7190618878688895  0.5010405127949369  0.2502514755283229
  0.4989978969018409  0.7502977850544852  0.7809492219327865
  0.7814464623477875  0.5003886730650109  0.7494947707104060
  0.4996606931909255  0.2496508616713697  0.7186036919929819
  0.2506716727065808  0.7181216545822622  0.5001902272634595""")
    structure_symmetrizer = StructureSymmetrizer(
        structure,
        defaults.symmetry_length_tolerance,
        defaults.symmetry_angle_tolerance)
    actual = symmetrize_defect_structure(structure_symmetrizer,
                                         anchor_atom_idx=15,
                                         anchor_atom_coord=np.array([0.5, 0.5, 0.0]))

    expected = Structure.from_str(fmt="POSCAR", input_string="""Mg4 O3
1.00000000000000
10 0 0
0 10 0
0 0 10
N
31
Direct
    0         0         0
    0.5       0         0
    0         0.5       0
    0.249164  0.218235  0.498835
    0.280829  0.499143  0.749885
    0.500857  0.249885  0.219171
    0.218626  0.499815  0.250544
    0.500185  0.750544  0.281374
    0.749103  0.282384  0.499914
    0.249885  0.280829  0.000857
    0.218235  0.001165  0.749164
    0.998835  0.249164  0.281765
    0.282384  8.6e-05   0.249103
    0.999914  0.749103  0.217616
    0.750544  0.218626  0.000185
    0.5       0.5       0
    0.5       0.5       0.5
    0         0.5       0.5
    0.5       1         0.5
    0.750115  0.719171  0.999143
    0.781765  0.998835  0.250836
    0.001165  0.750836  0.718235
    0.717616  0.999914  0.750897
    8.6e-05   0.250897  0.782384
    0.249456  0.781374  0.999815
    0.750836  0.781765  0.501165
    0.719171  0.500857  0.250115
    0.499143  0.750115  0.780829
    0.781374  0.500185  0.749456
    0.499815  0.249456  0.718626
    0.250897  0.717616  0.500086""")
    assert actual == expected
Exemple #10
0
def test_f_centering(bcc):
    s = StructureSymmetrizer(bcc)
    primitive = s.primitive
    to_conventional = primitive * Centering.I.primitive_to_conv
    assert to_conventional == s.conventional
    assert Centering.I.conv_multiplicity == 2
Exemple #11
0
def symmetrizer_bcc():
    lattice = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
    coords = [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]
    structure = Structure(lattice=lattice, species=["H", "H"], coords=coords)
    symmetrizer = StructureSymmetrizer(structure)
    return symmetrizer
Exemple #12
0
def test_a_centering(a_centered_orthorhombic):
    s = StructureSymmetrizer(a_centered_orthorhombic)
    primitive = s.primitive
    to_conventional = primitive * Centering.A.primitive_to_conv
    assert to_conventional.lattice == s.conventional.lattice
    assert Centering.A.conv_multiplicity == 2
Exemple #13
0
def group_by_non_equiv_sites(structure: Structure):
    symmetrizer = StructureSymmetrizer(structure)
    return symmetrizer.grouped_atom_indices()
Exemple #14
0
def test_grouped_atom_indices(complex_monoclinic_structure):
    symmetrizer = StructureSymmetrizer(complex_monoclinic_structure)
    actual = symmetrizer.grouped_atom_indices()
    assert actual == {'H1_a': [0], 'He1_m': [1, 2], 'He2_m': [3, 4]}
Exemple #15
0
def test_c_centering(c_centered_monoclinic):
    s = StructureSymmetrizer(c_centered_monoclinic)
    primitive = s.primitive
    to_conventional = primitive * Centering.C.primitive_to_conv
    assert to_conventional == s.conventional
    assert Centering.C.conv_multiplicity == 2
Exemple #16
0
def symmetrizer_mc():
    lattice = [[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [-2.0, 0.0, 10.0]]
    coords = [[0.0, 0.0, 0.0], [0.5, 0.5, 0.0]]
    structure = Structure(lattice=lattice, species=["H"] * 2, coords=coords)
    symmetrizer = StructureSymmetrizer(structure)
    return symmetrizer
Exemple #17
0
def test_r_centering(rhombohedral):
    s = StructureSymmetrizer(rhombohedral)
    rhombohedral = s.primitive
    to_conventional = rhombohedral * Centering.R.primitive_to_conv
    assert to_conventional == s.conventional
Exemple #18
0
 def _unique_point_group(self, structure):
     symmetrizer = StructureSymmetrizer(structure, self.symprec)
     return unique_point_group(symmetrizer.point_group)
Exemple #19
0
def mc_structure_conv(mc_structure):
    symmetrizer = StructureSymmetrizer(mc_structure)
    return symmetrizer.conventional