def write_structure(structure, filename): """ Write a structure to a file based on file extension. For example, anything ending in a "cif" is assumed to be a Crystallographic Information Format file. Supported formats include CIF, POSCAR, CSSR and pymatgen's JSON serialized structures. Args: structure (Structure/IStructure): Structure to write filename (str): A filename to write to. """ fname = os.path.basename(filename) if fnmatch(fname, "*.cif*"): writer = CifWriter(structure) elif fnmatch(fname, "POSCAR*") or fnmatch(fname, "CONTCAR*"): writer = Poscar(structure) elif fnmatch(fname.lower(), "*.cssr*"): writer = Cssr(structure) elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"): with zopen(filename, "wt") as f: f.write(str2unicode(json.dumps(structure, cls=MontyEncoder))) return else: raise ValueError("Unrecognized file extension!") writer.write_file(filename)
def cif(src='POSCAR'): """ cifファイルを作成 """ srcpos = Poscar.from_file(src) finder = SpacegroupAnalyzer(srcpos.structure) std_str = finder.get_conventional_standard_structure() cif_obj = CifWriter(std_str, symprec=0.1) cif_obj.write_file('poscar.cif')
def cif(src): """ cifファイルを作成 """ srcpos = Poscar.from_file(src) finder = SpacegroupAnalyzer(srcpos.structure) std_str = finder.get_conventional_standard_structure() std_cif = CifWriter(std_str, symprec=0.1) std_cif.write_file("poscar.cif")
def prim_cif(self, dst): """ primitive cellでのcifフォーマットをgetする """ finder = SpacegroupAnalyzer(self.structure) structure = finder.get_primitive_standard_structure() structure = finder.get_conventional_standard_structure() cif = CifWriter(structure, symprec=0.1) cif.write_file(dst)
def batch_write_vasp_input(transformed_structures, vasp_input_set=MPRelaxSet, output_dir=".", create_directory=True, subfolder=None, include_cif=False, **kwargs): """ Batch write vasp input for a sequence of transformed structures to output_dir, following the format output_dir/{group}/{formula}_{number}. Args: transformed_structures: Sequence of TransformedStructures. vasp_input_set: pymatgen.io.vaspio_set.VaspInputSet to creates vasp input files from structures. output_dir: Directory to output files create_directory (bool): Create the directory if not present. Defaults to True. subfolder: Function to create subdirectory name from transformed_structure. e.g., lambda x: x.other_parameters["tags"][0] to use the first tag. include_cif (bool): Boolean indication whether to output a CIF as well. CIF files are generally better supported in visualization programs. """ for i, s in enumerate(transformed_structures): formula = re.sub(r"\s+", "", s.final_structure.formula) if subfolder is not None: subdir = subfolder(s) dirname = os.path.join(output_dir, subdir, "{}_{}".format(formula, i)) else: dirname = os.path.join(output_dir, "{}_{}".format(formula, i)) s.write_vasp_input(vasp_input_set, dirname, create_directory=create_directory, **kwargs) if include_cif: from pymatgen.io.cif import CifWriter writer = CifWriter(s.final_structure) writer.write_file(os.path.join(dirname, "{}.cif".format(formula)))
def test_disordered(self): si = Element("Si") n = Element("N") coords = list() coords.append(np.array([0, 0, 0])) coords.append(np.array([0.75, 0.5, 0.75])) lattice = Lattice( np.array([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]])) struct = Structure(lattice, [si, {si: 0.5, n: 0.5}], coords) writer = CifWriter(struct) ans = """# generated using pymatgen data_Si1.5N0.5 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 3.84019793 _cell_length_b 3.84019899 _cell_length_c 3.84019793 _cell_angle_alpha 119.99999086 _cell_angle_beta 90.00000000 _cell_angle_gamma 60.00000914 _symmetry_Int_Tables_number 1 _chemical_formula_structural Si1.5N0.5 _chemical_formula_sum 'Si1.5 N0.5' _cell_volume 40.04479464 _cell_formula_units_Z 1 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Si Si1 1 0.000000 0.000000 0.000000 1 Si Si2 1 0.750000 0.500000 0.750000 0.5 N N3 1 0.750000 0.500000 0.750000 0.5 """ for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): self.assertEqual(l1.strip(), l2.strip())
def test_CifWriter(self): filepath = os.path.join(test_dir, 'POSCAR') poscar = Poscar.from_file(filepath) writer = CifWriter(poscar.structure, symprec=0.01) ans = """# generated using pymatgen data_FePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 10.41176687 _cell_length_b 6.06717188 _cell_length_c 4.75948954 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 62 _chemical_formula_structural FePO4 _chemical_formula_sum 'Fe4 P4 O16' _cell_volume 300.65685512 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 '-x+1/2, -y, z+1/2' 4 'x+1/2, y, -z+1/2' 5 'x+1/2, -y+1/2, -z+1/2' 6 '-x+1/2, y+1/2, z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Fe Fe1 4 0.218728 0.250000 0.525133 1 P P2 4 0.094613 0.750000 0.581757 1 O O3 8 0.165710 0.546072 0.714616 1 O O4 4 0.043372 0.250000 0.292862 1 O O5 4 0.096642 0.750000 0.258680 1""" for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): self.assertEqual(l1.strip(), l2.strip())
def test_CifWriter(self): filepath = self.TEST_FILES_DIR / 'POSCAR' poscar = Poscar.from_file(filepath) writer = CifWriter(poscar.structure, symprec=0.01) ans = """# generated using pymatgen data_FePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 10.41176687 _cell_length_b 6.06717188 _cell_length_c 4.75948954 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 62 _chemical_formula_structural FePO4 _chemical_formula_sum 'Fe4 P4 O16' _cell_volume 300.65685512 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 '-x+1/2, -y, z+1/2' 4 'x+1/2, y, -z+1/2' 5 'x+1/2, -y+1/2, -z+1/2' 6 '-x+1/2, y+1/2, z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Fe Fe0 4 0.21872822 0.75000000 0.47486711 1 P P1 4 0.09461309 0.25000000 0.41824327 1 O O2 8 0.16570974 0.04607233 0.28538394 1 O O3 4 0.04337231 0.75000000 0.70713767 1 O O4 4 0.09664244 0.25000000 0.74132035 1""" for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): self.assertEqual(l1.strip(), l2.strip())
def get(self, sid): """Retrieve structure for contribution in CIF format. --- operationId: get_cif parameters: - name: sid in: path type: string pattern: '^[a-f0-9]{24}$' required: true description: Structure ID (ObjectId) responses: 200: description: structure in CIF format schema: type: string """ entry = Structures.objects.no_dereference().get(id=sid) structure = Structure.from_dict(entry.to_mongo()) return CifWriter(structure, symprec=1e-10).__str__()
def get_cif_string(self, temp=300, symprec=None): """ Return string with structure and anisotropic U tensor in CIF format at temperature `temp` in Kelvin Args: symprec (float): If not none, finds the symmetry of the structure and writes the cif with symmetry information. Passes symprec to the SpacegroupAnalyzer """ # Get string with structure in CIF format. # Don't use symprec because it changes the order of the sites # and we must be consistent with site_labels when writing aniso_U terms! from pymatgen.io.cif import CifWriter cif = CifWriter(self.structure, symprec=symprec) aniso_u = """loop_ _atom_site_aniso_label _atom_site_aniso_U_11 _atom_site_aniso_U_22 _atom_site_aniso_U_33 _atom_site_aniso_U_23 _atom_site_aniso_U_13 _atom_site_aniso_U_12""".splitlines() # Compute U tensor in CIF format (reduced coords) natom = len(self.structure) msq = self.get_msq_tmesh([float(temp)], what_list="displ") ucart = getattr(msq, "displ") ucart = np.reshape(ucart, (natom, 3, 3)) ucif = self.convert_ucart(ucart, fmt="cif") # Add matrix elements. Use 0 based index for iatom, site in enumerate(self.structure): site_label = "%s%d" % (site.specie.symbol, iatom) m = ucif[iatom] aniso_u.append("%s %10.5f %10.5f %10.5f %10.5f %10.5f %10.5f" % (site_label, m[0, 0], m[1, 1], m[2, 2], m[1, 2], m[0, 2], m[0, 1])) return str(cif) + "\n".join(aniso_u)
def get_random_structure(elem, num_atom, sg, dim, thickness=0): max_try = 100 factor = 1.0 i = 0 while i < max_try: random.seed(time.time() * 1e8) if sg == 0: sg = get_random_spg(dim) symbol, sg = get_symbol_and_number(sg, dim) if dim == 3: rand_crystal = random_crystal(sg, elem, num_atom, factor) elif dim == 2: rand_crystal = random_crystal_2D(sg, elem, num_atom, thickness, factor) elif dim == 1: rand_crystal = random_crystal_1D(sg, elem, num_atom, thickness, factor) if dim == 0: rand_crystal = random_cluster(sg, elem, num_atom, factor) if rand_crystal.valid: comp = str(rand_crystal.struct.composition) comp = comp.replace(" ", "") if dim > 0: outpath = comp + '.cif' CifWriter(rand_crystal.struct, symprec=0.1).write_file(filename=outpath) ans = get_symmetry_dataset(rand_crystal.spg_struct, symprec=1e-1)['international'] print('Symmetry requested: {:d}({:s}), generated: {:s}'.format( sg, symbol, ans)) return True else: outpath = comp + '.xyz' rand_crystal.to_file(filename=outpath, fmt='xyz') ans = PointGroupAnalyzer(rand_crystal.molecule).sch_symbol print('Symmetry requested: {:d}({:s}), generated: {:s}'.format( sg, symbol, ans)) return True i += 1
def quick_view(structure: Structure, *args, conventional: bool = False, supercell: list = [1, 1, 1], symprec: float = 0.01, angle_tolerance: float = 5.0) -> JsmolView: """A function to visualize pymatgen Structure objects in jupyter notebook using jupyter_jsmol package. Args: structure: pymatgen Structure object. *args: Extra arguments for JSmol's load command. Eg. "{2 2 2}", "packed" conventional: use conventional cell. Defaults to False. supercell: can be used to make supercells with pymatgen.Structure.make_supercell method. symprec: If not none, finds the symmetry of the structure and writes the cif with symmetry information. Passes symprec to the SpacegroupAnalyzer. angle_tolerance: Angle tolerance for symmetry finding. Passes angle_tolerance to the SpacegroupAnalyzer. Used only if symprec is not None. Returns: A jupyter widget object. """ s = structure.copy() if conventional: spga = SpacegroupAnalyzer(s, symprec=symprec, angle_tolerance=angle_tolerance) s = spga.get_conventional_standard_structure() cif = CifWriter(s, symprec=symprec, angle_tolerance=angle_tolerance, refine_struct=False) supercell_str = "{" + " ".join(map(str, supercell)) + "}" return JsmolView.from_str(str(cif), supercell_str, *args)
def get_string(self) -> str: cw = CifWriter(self.structure) return cw.__str__()
def test_write(self): cw_ref_string = """# generated using pymatgen data_GdB4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 7.13160000 _cell_length_b 7.13160000 _cell_length_c 4.05050000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural GdB4 _chemical_formula_sum 'Gd4 B16' _cell_volume 206.00729003 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd Gd0 1 0.317460 0.817460 0.000000 1.0 Gd Gd1 1 0.182540 0.317460 0.000000 1.0 Gd Gd2 1 0.817460 0.682540 0.000000 1.0 Gd Gd3 1 0.682540 0.182540 0.000000 1.0 B B4 1 0.000000 0.000000 0.202900 1.0 B B5 1 0.500000 0.500000 0.797100 1.0 B B6 1 0.000000 0.000000 0.797100 1.0 B B7 1 0.500000 0.500000 0.202900 1.0 B B8 1 0.175900 0.038000 0.500000 1.0 B B9 1 0.962000 0.175900 0.500000 1.0 B B10 1 0.038000 0.824100 0.500000 1.0 B B11 1 0.675900 0.462000 0.500000 1.0 B B12 1 0.324100 0.538000 0.500000 1.0 B B13 1 0.824100 0.962000 0.500000 1.0 B B14 1 0.538000 0.675900 0.500000 1.0 B B15 1 0.462000 0.324100 0.500000 1.0 B B16 1 0.086700 0.586700 0.500000 1.0 B B17 1 0.413300 0.086700 0.500000 1.0 B B18 1 0.586700 0.913300 0.500000 1.0 B B19 1 0.913300 0.413300 0.500000 1.0 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z Gd0 5.05000 5.05000 0.00000 Gd1 -5.05000 5.05000 0.00000 Gd2 5.05000 -5.05000 0.00000 Gd3 -5.05000 -5.05000 0.00000 """ s_ncl = self.mcif_ncl.get_structures(primitive=False)[0] cw = CifWriter(s_ncl, write_magmoms=True) self.assertEqual(cw.__str__(), cw_ref_string) # from list-type magmoms list_magmoms = [list(m) for m in s_ncl.site_properties['magmom']] # float magmoms (magnitude only) float_magmoms = [float(m) for m in s_ncl.site_properties['magmom']] s_ncl.add_site_property('magmom', list_magmoms) cw = CifWriter(s_ncl, write_magmoms=True) self.assertEqual(cw.__str__(), cw_ref_string) s_ncl.add_site_property('magmom', float_magmoms) cw = CifWriter(s_ncl, write_magmoms=True) cw_ref_string_magnitudes = """# generated using pymatgen data_GdB4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 7.13160000 _cell_length_b 7.13160000 _cell_length_c 4.05050000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural GdB4 _chemical_formula_sum 'Gd4 B16' _cell_volume 206.00729003 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd Gd0 1 0.317460 0.817460 0.000000 1.0 Gd Gd1 1 0.182540 0.317460 0.000000 1.0 Gd Gd2 1 0.817460 0.682540 0.000000 1.0 Gd Gd3 1 0.682540 0.182540 0.000000 1.0 B B4 1 0.000000 0.000000 0.202900 1.0 B B5 1 0.500000 0.500000 0.797100 1.0 B B6 1 0.000000 0.000000 0.797100 1.0 B B7 1 0.500000 0.500000 0.202900 1.0 B B8 1 0.175900 0.038000 0.500000 1.0 B B9 1 0.962000 0.175900 0.500000 1.0 B B10 1 0.038000 0.824100 0.500000 1.0 B B11 1 0.675900 0.462000 0.500000 1.0 B B12 1 0.324100 0.538000 0.500000 1.0 B B13 1 0.824100 0.962000 0.500000 1.0 B B14 1 0.538000 0.675900 0.500000 1.0 B B15 1 0.462000 0.324100 0.500000 1.0 B B16 1 0.086700 0.586700 0.500000 1.0 B B17 1 0.413300 0.086700 0.500000 1.0 B B18 1 0.586700 0.913300 0.500000 1.0 B B19 1 0.913300 0.413300 0.500000 1.0 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z Gd0 0.00000 0.00000 7.14178 Gd1 0.00000 0.00000 7.14178 Gd2 0.00000 0.00000 -7.14178 Gd3 0.00000 0.00000 -7.14178 """ self.assertEqual(cw.__str__(), cw_ref_string_magnitudes) # test we're getting correct magmoms in ncl case s_ncl2 = self.mcif_ncl2.get_structures()[0] list_magmoms = [list(m) for m in s_ncl2.site_properties['magmom']] self.assertEqual(list_magmoms[0][0], 0.0) self.assertAlmostEqual(list_magmoms[0][1], 5.9160793408726366) self.assertAlmostEqual(list_magmoms[1][0], -5.1234749999999991) self.assertAlmostEqual(list_magmoms[1][1], 2.9580396704363183) # test creating an structure without oxidation state doesn't raise errors s_manual = Structure(Lattice.cubic(4.2), ["Cs", "Cl"],[[0, 0, 0], [0.5, 0.5, 0.5]]) s_manual.add_spin_by_site([1, -1]) cw = CifWriter(s_manual, write_magmoms=True) # check oxidation state cw_manual_oxi_string = """# generated using pymatgen data_CsCl _symmetry_space_group_name_H-M 'P 1' _cell_length_a 4.20000000 _cell_length_b 4.20000000 _cell_length_c 4.20000000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural CsCl _chemical_formula_sum 'Cs1 Cl1' _cell_volume 74.08800000 _cell_formula_units_Z 1 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_type_symbol _atom_type_oxidation_number Cs+ 1.0 Cl+ 1.0 loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Cs+ Cs0 1 0.000000 0.000000 0.000000 1 Cl+ Cl1 1 0.500000 0.500000 0.500000 1 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z """ s_manual.add_oxidation_state_by_site([1,1]) cw = CifWriter(s_manual, write_magmoms=True) self.assertEqual(cw.__str__(), cw_manual_oxi_string)
#!/usr/bin/python3 from pymatgen import Structure from pymatgen.transformations.standard_transformations import OrderDisorderedStructureTransformation from pymatgen.transformations.advanced_transformations import EnumerateStructureTransformation from pymatgen.io.cif import CifWriter import sys try: cif_filename = sys.argv[1] except ValueError: print("please give the cif file name as the 1st argument!") s = Structure.from_file(cif_filename) prim = s.get_primitive_structure() # Merge sites that are less than 1A apart. prim.merge_sites(1) prim = prim.get_sorted_structure() t = EnumerateStructureTransformation() ordered = t.apply_transformation(prim, 5) print(len(ordered)) for i in range(len(ordered)): c = CifWriter(ordered[i]['structure'], symprec=0.01) c.write_file("LLZO_ordered-" + str(i) + ".cif")
os.chdir(prev_dir) with open("../data.pickle", "rb") as fr: data = pickle.load(fr) x_train = data["x_train"] y_train = data["y_train"] x_val = data["x_val"] y_val = data["y_val"] x_test = data["x_test"] y_test = data["y_test"] train_mpids = data["train_mpids"] val_mpids = data["val_mpids"] test_mpids = data["test_mpids"] all_x = np.concatenate((x_train, x_val, x_test), axis=0) all_y = np.concatenate((y_train, y_val, y_test), axis=0) all_mpids = np.concatenate((train_mpids, val_mpids, test_mpids), axis=0) id_prop = [] with alive_bar(len(all_x)) as bar: for x, y, mp in zip(all_x, all_y, all_mpids): if x.state == [[600]]: id_prop.append([f"mp-{mp}", y]) cw = CifWriter(x, symprec=0.001) cw.write_file(f"structures/mp-{mp}.cif") bar() np.savetxt("structures/id_prop.csv", id_prop, delimiter=",", fmt="%s")
def test_symmetrized(self): filepath = os.path.join(test_dir, 'POSCAR') poscar = Poscar.from_file(filepath) writer = CifWriter(poscar.structure, symprec=0.1) ans = """# generated using pymatgen data_FePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 10.41176687 _cell_length_b 6.06717188 _cell_length_c 4.75948954 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 62 _chemical_formula_structural FePO4 _chemical_formula_sum 'Fe4 P4 O16' _cell_volume 300.65685512 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 '-x+1/2, -y, z+1/2' 4 'x+1/2, y, -z+1/2' 5 'x+1/2, -y+1/2, -z+1/2' 6 '-x+1/2, y+1/2, z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Fe Fe1 4 0.218728 0.750000 0.474867 1 P P2 4 0.094613 0.250000 0.418243 1 O O3 8 0.165710 0.046072 0.285384 1 O O4 4 0.043372 0.750000 0.707138 1 O O5 4 0.096642 0.250000 0.741320 1""" for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): self.assertEqual(l1.strip(), l2.strip()) ans = """# generated using pymatgen data_LiFePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 4.74480000 _cell_length_b 6.06577000 _cell_length_c 10.41037000 _cell_angle_alpha 90.50179000 _cell_angle_beta 90.00019000 _cell_angle_gamma 90.00362000 _symmetry_Int_Tables_number 62 _chemical_formula_structural LiFePO4 _chemical_formula_sum 'Li4 Fe4 P4 O16' _cell_volume 299.607967711 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 'x+1/2, -y, -z+1/2' 4 '-x+1/2, y, z+1/2' 5 '-x+1/2, -y+1/2, z+1/2' 6 'x+1/2, y+1/2, -z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Li Li1 4 0.000010 0.500000 0.999990 1.0 Fe Fe2 4 0.025030 0.746540 0.281160 1.0 P P3 4 0.082060 0.248260 0.405570 1.0 O O4 8 0.213420 0.043980 0.334230 1.0 O O5 4 0.208430 0.251100 0.543180 1.0 O O6 4 0.241480 0.750450 0.596220 1.0 """ s = Structure.from_file(os.path.join(test_dir, 'LiFePO4.cif')) writer = CifWriter(s, symprec=0.1) self.assertEqual(writer.__str__().strip(), ans.strip())
def upload_file(): stamp = "" if request.method == 'POST': #request.environ['REMOTE_ADDR'] if request.environ.get('HTTP_X_FORWARDED_FOR') is None: ip = request.environ['REMOTE_ADDR'] else: ip = request.environ['HTTP_X_FORWARDED_FOR'] # if behind a proxy #substrate information# f1 = request.files['POSCAR_sub'] stamp = time.strftime("%Y%m%d-%H%M%S") + '-' + ip poscar_sub = stamp + '-' + f1.filename f1.save(upload_dir + os.sep + secure_filename(poscar_sub)) h_sub = int(request.form["h_sub"]) k_sub = int(request.form["k_sub"]) l_sub = int(request.form["l_sub"]) nlayers_substrate = int(request.form["nlayers_substrate"]) min_thick_sub = float(request.form["min_thick_sub"]) min_vac_sub = float(request.form["min_vac_sub"]) #is_primitive = request.form.get["is_primitive"] hkl_sub = [h_sub, k_sub, l_sub] #2d information# f2 = request.files['POSCAR_2d'] poscar_2d = stamp + '-' + f2.filename f2.save(upload_dir + os.sep + secure_filename(poscar_2d)) h_2d = int(request.form["h_2d"]) k_2d = int(request.form["k_2d"]) l_2d = int(request.form["l_2d"]) nlayers_2d = int(request.form["nlayers_2d"]) hkl_2d = [h_2d, k_2d, l_2d] #General information# separation = float(request.form["separation"]) max_area = float(request.form["max_area"]) max_mismatch = float(request.form["max_mismatch"]) max_angle_diff = float(request.form["max_angle_diff"]) #Matching# try: substrate_bulk = pymatgen.Structure.from_file(upload_dir + os.sep + poscar_sub) sa_sub = pymatgen.symmetry.analyzer.SpacegroupAnalyzer( substrate_bulk) substrate_bulk = sa_sub.get_conventional_standard_structure() substrate_slab = Interface(substrate_bulk, hkl=hkl_sub, min_thick=min_thick_sub, min_vac=min_vac_sub, primitive=False, from_ase=True) mat2d_slab = utils.slab_from_file(hkl_2d, upload_dir + os.sep + poscar_2d) operation_dir = "static" + os.sep + "operations" + os.sep + stamp if not os.path.exists(operation_dir): os.makedirs(operation_dir) mat2d_slab.to(fmt="poscar", filename=operation_dir + "POSCAR_mat2d_slab.vasp") sd_flags = CalibrateSlab.set_sd_flags(interface=substrate_slab, n_layers=nlayers_substrate, top=True, bottom=False) poscar = pymatgen.io.vasp.inputs.Poscar( substrate_slab, selective_dynamics=sd_flags) poscar.write_file(filename=operation_dir + os.sep + "POSCAR_substrate_slab.vasp") substrate_slab_aligned, mat2d_slab_aligned, mismatch = transformations.get_aligned_lattices( substrate_slab, mat2d_slab, max_area=max_area, max_mismatch=max_mismatch, max_angle_diff=max_angle_diff, r1r2_tol=0.01) substrate_slab_aligned.to(fmt="poscar", filename=operation_dir + os.sep + "POSCAR_substrate_aligned.vasp") mat2d_slab_aligned.to(fmt="poscar", filename=operation_dir + os.sep + "POSCAR_mat2d_aligned.vasp") hetero_interfaces = transformations.generate_all_configs( mat2d_slab_aligned, substrate_slab_aligned, nlayers_2d, nlayers_substrate, separation) for i, iface in enumerate(hetero_interfaces): sd_flags = CalibrateSlab.set_sd_flags(interface=iface, n_layers=nlayers_2d + nlayers_substrate, top=True, bottom=False) poscar = pymatgen.io.vasp.inputs.Poscar( iface, selective_dynamics=sd_flags) poscar.write_file(filename=operation_dir + os.sep + 'POSCAR_final_{}.vasp'.format(i)) p = Poscar.from_file(operation_dir + os.sep + 'POSCAR_final_{}.vasp'.format(i)) w = CifWriter(p.structure) w.write_file(operation_dir + os.sep + 'POSCAR_final_{}.cif'.format(i)) # st = pychemia.code.vasp.read_poscar(operation_dir+os.sep+'POSCAR_final_{}.vasp'.format(i)) #rf = open("testing") #rf.write("reading succesful") #rf.close() # pychemia.io.cif.save(structure=st,filename=operation_dir+os.sep+'POSCAR_final_{}.xyz'.format(i)) except: #redirect(url_for("error",_id="matching",stamp=stamp)) return ("Error") return redirect(url_for('result', stamp=stamp)) return render_template("matching.html", _id="matching", test_var="test", stamp=stamp)
def test_write(self): cw_ref_string = """# generated using pymatgen data_GdB4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 7.13160000 _cell_length_b 7.13160000 _cell_length_c 4.05050000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural GdB4 _chemical_formula_sum 'Gd4 B16' _cell_volume 206.00729003 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd Gd1 1 0.317460 0.817460 0.000000 1.0 Gd Gd2 1 0.182540 0.317460 0.000000 1.0 Gd Gd3 1 0.817460 0.682540 0.000000 1.0 Gd Gd4 1 0.682540 0.182540 0.000000 1.0 B B5 1 0.000000 0.000000 0.202900 1.0 B B6 1 0.500000 0.500000 0.797100 1.0 B B7 1 0.000000 0.000000 0.797100 1.0 B B8 1 0.500000 0.500000 0.202900 1.0 B B9 1 0.175900 0.038000 0.500000 1.0 B B10 1 0.962000 0.175900 0.500000 1.0 B B11 1 0.038000 0.824100 0.500000 1.0 B B12 1 0.675900 0.462000 0.500000 1.0 B B13 1 0.324100 0.538000 0.500000 1.0 B B14 1 0.824100 0.962000 0.500000 1.0 B B15 1 0.538000 0.675900 0.500000 1.0 B B16 1 0.462000 0.324100 0.500000 1.0 B B17 1 0.086700 0.586700 0.500000 1.0 B B18 1 0.413300 0.086700 0.500000 1.0 B B19 1 0.586700 0.913300 0.500000 1.0 B B20 1 0.913300 0.413300 0.500000 1.0 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z Gd1 5.05000 5.05000 0.00000 Gd2 -5.05000 5.05000 0.00000 Gd3 5.05000 -5.05000 0.00000 Gd4 -5.05000 -5.05000 0.00000 """ s_ncl = self.mcif_ncl.get_structures(primitive=False)[0] cw = CifWriter(s_ncl, write_magmoms=True) self.assertEqual(cw.__str__(), cw_ref_string) # from list-type magmoms list_magmoms = [list(m) for m in s_ncl.site_properties['magmom']] # float magmoms (magnitude only) float_magmoms = [float(m) for m in s_ncl.site_properties['magmom']] s_ncl.add_site_property('magmom', list_magmoms) cw = CifWriter(s_ncl, write_magmoms=True) self.assertEqual(cw.__str__(), cw_ref_string) s_ncl.add_site_property('magmom', float_magmoms) cw = CifWriter(s_ncl, write_magmoms=True) cw_ref_string_magnitudes = """# generated using pymatgen data_GdB4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 7.13160000 _cell_length_b 7.13160000 _cell_length_c 4.05050000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural GdB4 _chemical_formula_sum 'Gd4 B16' _cell_volume 206.00729003 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd Gd1 1 0.317460 0.817460 0.000000 1.0 Gd Gd2 1 0.182540 0.317460 0.000000 1.0 Gd Gd3 1 0.817460 0.682540 0.000000 1.0 Gd Gd4 1 0.682540 0.182540 0.000000 1.0 B B5 1 0.000000 0.000000 0.202900 1.0 B B6 1 0.500000 0.500000 0.797100 1.0 B B7 1 0.000000 0.000000 0.797100 1.0 B B8 1 0.500000 0.500000 0.202900 1.0 B B9 1 0.175900 0.038000 0.500000 1.0 B B10 1 0.962000 0.175900 0.500000 1.0 B B11 1 0.038000 0.824100 0.500000 1.0 B B12 1 0.675900 0.462000 0.500000 1.0 B B13 1 0.324100 0.538000 0.500000 1.0 B B14 1 0.824100 0.962000 0.500000 1.0 B B15 1 0.538000 0.675900 0.500000 1.0 B B16 1 0.462000 0.324100 0.500000 1.0 B B17 1 0.086700 0.586700 0.500000 1.0 B B18 1 0.413300 0.086700 0.500000 1.0 B B19 1 0.586700 0.913300 0.500000 1.0 B B20 1 0.913300 0.413300 0.500000 1.0 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z Gd1 0.00000 0.00000 7.14178 Gd2 0.00000 0.00000 7.14178 Gd3 0.00000 0.00000 -7.14178 Gd4 0.00000 0.00000 -7.14178 """ self.assertEqual(cw.__str__(), cw_ref_string_magnitudes) # test we're getting correct magmoms in ncl case s_ncl2 = self.mcif_ncl2.get_structures()[0] list_magmoms = [list(m) for m in s_ncl2.site_properties['magmom']] self.assertEqual(list_magmoms[0][0], 0.0) self.assertAlmostEqual(list_magmoms[0][1], 5.9160793408726366) self.assertAlmostEqual(list_magmoms[1][0], -5.1234749999999991) self.assertAlmostEqual(list_magmoms[1][1], 2.9580396704363183)
a=sys.argv[2].split(',') b=sys.argv[3].split(',') c=sys.argv[4].split(',') sp =[a,b,c] l=sys.argv[2].replace(',','') m=sys.argv[3].replace(',','') n=sys.argv[4].replace(',','') size=l+"x"+m+"x"+n else: print("Check input formatting") ## compatbility with QE input/output #if filname.endswith(".in"): # with open("fil.xsf","w") as outfile: # subprocess.check_call(["pwi2xsf",filname],stdout=outfile) # filname="fil.xsf" #elif filname.endswith(".out"): # subprocess.check_call(["pwo2xsf",filname," > fil.xsf"]) # filname="fil.xsf" # Read structure from PWscf file, xsf format structure = Structure.from_file(filname) # make supercell structure.make_supercell(sp,to_unit_cell=True) # output to cif w = CifWriter(structure) w.write_file("super-"+size+"-"+outname[0]+".cif")
def write_cif(path, structure): writer = CifWriter(structure) writer.write_file(path)
def test_symmetrized(self): filepath = os.path.join(test_dir, 'POSCAR') poscar = Poscar.from_file(filepath, check_for_POTCAR=False) writer = CifWriter(poscar.structure, symprec=0.1) ans = """# generated using pymatgen data_FePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 10.41176687 _cell_length_b 6.06717188 _cell_length_c 4.75948954 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 62 _chemical_formula_structural FePO4 _chemical_formula_sum 'Fe4 P4 O16' _cell_volume 300.65685512 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 '-x+1/2, -y, z+1/2' 4 'x+1/2, y, -z+1/2' 5 'x+1/2, -y+1/2, -z+1/2' 6 '-x+1/2, y+1/2, z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Fe Fe1 4 0.218728 0.250000 0.525133 1 P P2 4 0.094613 0.750000 0.581757 1 O O3 8 0.165710 0.546072 0.714616 1 O O4 4 0.043372 0.250000 0.292862 1 O O5 4 0.096642 0.750000 0.258680 1""" for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): self.assertEqual(l1.strip(), l2.strip()) ans = """# generated using pymatgen data_LiFePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 10.41037000 _cell_length_b 6.06577000 _cell_length_c 4.74480000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 62 _chemical_formula_structural LiFePO4 _chemical_formula_sum 'Li4 Fe4 P4 O16' _cell_volume 299.619458734 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 '-x+1/2, -y, z+1/2' 4 'x+1/2, y, -z+1/2' 5 'x+1/2, -y+1/2, -z+1/2' 6 '-x+1/2, y+1/2, z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Li Li1 4 0.000000 0.000000 0.000000 1.0 Fe Fe2 4 0.218845 0.750000 0.474910 1.0 P P3 4 0.094445 0.250000 0.417920 1.0 O O4 8 0.165815 0.044060 0.286540 1.0 O O5 4 0.043155 0.750000 0.708460 1.0 O O6 4 0.096215 0.250000 0.741480 1.0 """ s = Structure.from_file(os.path.join(test_dir, 'LiFePO4.cif')) writer = CifWriter(s, symprec=0.1) s2 = CifParser.from_string(str(writer)).get_structures()[0] m = StructureMatcher() self.assertTrue(m.fit(s, s2)) s = self.get_structure("Li2O") writer = CifWriter(s, symprec=0.1) ans = """# generated using pymatgen data_Li2O _symmetry_space_group_name_H-M Fm-3m _cell_length_a 4.65884171 _cell_length_b 4.65884171 _cell_length_c 4.65884171 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 225 _chemical_formula_structural Li2O _chemical_formula_sum 'Li8 O4' _cell_volume 101.11925577 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 'z, y, -x' 4 '-z, -y, x' 5 '-x, y, -z' 6 'x, -y, z' 7 '-z, y, x' 8 'z, -y, -x' 9 'x, -y, -z' 10 '-x, y, z' 11 'z, -y, x' 12 '-z, y, -x' 13 '-x, -y, z' 14 'x, y, -z' 15 '-z, -y, -x' 16 'z, y, x' 17 'y, -z, -x' 18 '-y, z, x' 19 'y, x, -z' 20 '-y, -x, z' 21 'y, z, x' 22 '-y, -z, -x' 23 'y, -x, z' 24 '-y, x, -z' 25 '-y, z, -x' 26 'y, -z, x' 27 '-y, -x, -z' 28 'y, x, z' 29 '-y, -z, x' 30 'y, z, -x' 31 '-y, x, z' 32 'y, -x, -z' 33 '-z, x, -y' 34 'z, -x, y' 35 'x, z, -y' 36 '-x, -z, y' 37 'z, -x, -y' 38 '-z, x, y' 39 '-x, -z, -y' 40 'x, z, y' 41 'z, x, y' 42 '-z, -x, -y' 43 '-x, z, y' 44 'x, -z, -y' 45 '-z, -x, y' 46 'z, x, -y' 47 'x, -z, y' 48 '-x, z, -y' 49 'x+1/2, y+1/2, z' 50 '-x+1/2, -y+1/2, -z' 51 'z+1/2, y+1/2, -x' 52 '-z+1/2, -y+1/2, x' 53 '-x+1/2, y+1/2, -z' 54 'x+1/2, -y+1/2, z' 55 '-z+1/2, y+1/2, x' 56 'z+1/2, -y+1/2, -x' 57 'x+1/2, -y+1/2, -z' 58 '-x+1/2, y+1/2, z' 59 'z+1/2, -y+1/2, x' 60 '-z+1/2, y+1/2, -x' 61 '-x+1/2, -y+1/2, z' 62 'x+1/2, y+1/2, -z' 63 '-z+1/2, -y+1/2, -x' 64 'z+1/2, y+1/2, x' 65 'y+1/2, -z+1/2, -x' 66 '-y+1/2, z+1/2, x' 67 'y+1/2, x+1/2, -z' 68 '-y+1/2, -x+1/2, z' 69 'y+1/2, z+1/2, x' 70 '-y+1/2, -z+1/2, -x' 71 'y+1/2, -x+1/2, z' 72 '-y+1/2, x+1/2, -z' 73 '-y+1/2, z+1/2, -x' 74 'y+1/2, -z+1/2, x' 75 '-y+1/2, -x+1/2, -z' 76 'y+1/2, x+1/2, z' 77 '-y+1/2, -z+1/2, x' 78 'y+1/2, z+1/2, -x' 79 '-y+1/2, x+1/2, z' 80 'y+1/2, -x+1/2, -z' 81 '-z+1/2, x+1/2, -y' 82 'z+1/2, -x+1/2, y' 83 'x+1/2, z+1/2, -y' 84 '-x+1/2, -z+1/2, y' 85 'z+1/2, -x+1/2, -y' 86 '-z+1/2, x+1/2, y' 87 '-x+1/2, -z+1/2, -y' 88 'x+1/2, z+1/2, y' 89 'z+1/2, x+1/2, y' 90 '-z+1/2, -x+1/2, -y' 91 '-x+1/2, z+1/2, y' 92 'x+1/2, -z+1/2, -y' 93 '-z+1/2, -x+1/2, y' 94 'z+1/2, x+1/2, -y' 95 'x+1/2, -z+1/2, y' 96 '-x+1/2, z+1/2, -y' 97 'x+1/2, y, z+1/2' 98 '-x+1/2, -y, -z+1/2' 99 'z+1/2, y, -x+1/2' 100 '-z+1/2, -y, x+1/2' 101 '-x+1/2, y, -z+1/2' 102 'x+1/2, -y, z+1/2' 103 '-z+1/2, y, x+1/2' 104 'z+1/2, -y, -x+1/2' 105 'x+1/2, -y, -z+1/2' 106 '-x+1/2, y, z+1/2' 107 'z+1/2, -y, x+1/2' 108 '-z+1/2, y, -x+1/2' 109 '-x+1/2, -y, z+1/2' 110 'x+1/2, y, -z+1/2' 111 '-z+1/2, -y, -x+1/2' 112 'z+1/2, y, x+1/2' 113 'y+1/2, -z, -x+1/2' 114 '-y+1/2, z, x+1/2' 115 'y+1/2, x, -z+1/2' 116 '-y+1/2, -x, z+1/2' 117 'y+1/2, z, x+1/2' 118 '-y+1/2, -z, -x+1/2' 119 'y+1/2, -x, z+1/2' 120 '-y+1/2, x, -z+1/2' 121 '-y+1/2, z, -x+1/2' 122 'y+1/2, -z, x+1/2' 123 '-y+1/2, -x, -z+1/2' 124 'y+1/2, x, z+1/2' 125 '-y+1/2, -z, x+1/2' 126 'y+1/2, z, -x+1/2' 127 '-y+1/2, x, z+1/2' 128 'y+1/2, -x, -z+1/2' 129 '-z+1/2, x, -y+1/2' 130 'z+1/2, -x, y+1/2' 131 'x+1/2, z, -y+1/2' 132 '-x+1/2, -z, y+1/2' 133 'z+1/2, -x, -y+1/2' 134 '-z+1/2, x, y+1/2' 135 '-x+1/2, -z, -y+1/2' 136 'x+1/2, z, y+1/2' 137 'z+1/2, x, y+1/2' 138 '-z+1/2, -x, -y+1/2' 139 '-x+1/2, z, y+1/2' 140 'x+1/2, -z, -y+1/2' 141 '-z+1/2, -x, y+1/2' 142 'z+1/2, x, -y+1/2' 143 'x+1/2, -z, y+1/2' 144 '-x+1/2, z, -y+1/2' 145 'x, y+1/2, z+1/2' 146 '-x, -y+1/2, -z+1/2' 147 'z, y+1/2, -x+1/2' 148 '-z, -y+1/2, x+1/2' 149 '-x, y+1/2, -z+1/2' 150 'x, -y+1/2, z+1/2' 151 '-z, y+1/2, x+1/2' 152 'z, -y+1/2, -x+1/2' 153 'x, -y+1/2, -z+1/2' 154 '-x, y+1/2, z+1/2' 155 'z, -y+1/2, x+1/2' 156 '-z, y+1/2, -x+1/2' 157 '-x, -y+1/2, z+1/2' 158 'x, y+1/2, -z+1/2' 159 '-z, -y+1/2, -x+1/2' 160 'z, y+1/2, x+1/2' 161 'y, -z+1/2, -x+1/2' 162 '-y, z+1/2, x+1/2' 163 'y, x+1/2, -z+1/2' 164 '-y, -x+1/2, z+1/2' 165 'y, z+1/2, x+1/2' 166 '-y, -z+1/2, -x+1/2' 167 'y, -x+1/2, z+1/2' 168 '-y, x+1/2, -z+1/2' 169 '-y, z+1/2, -x+1/2' 170 'y, -z+1/2, x+1/2' 171 '-y, -x+1/2, -z+1/2' 172 'y, x+1/2, z+1/2' 173 '-y, -z+1/2, x+1/2' 174 'y, z+1/2, -x+1/2' 175 '-y, x+1/2, z+1/2' 176 'y, -x+1/2, -z+1/2' 177 '-z, x+1/2, -y+1/2' 178 'z, -x+1/2, y+1/2' 179 'x, z+1/2, -y+1/2' 180 '-x, -z+1/2, y+1/2' 181 'z, -x+1/2, -y+1/2' 182 '-z, x+1/2, y+1/2' 183 '-x, -z+1/2, -y+1/2' 184 'x, z+1/2, y+1/2' 185 'z, x+1/2, y+1/2' 186 '-z, -x+1/2, -y+1/2' 187 '-x, z+1/2, y+1/2' 188 'x, -z+1/2, -y+1/2' 189 '-z, -x+1/2, y+1/2' 190 'z, x+1/2, -y+1/2' 191 'x, -z+1/2, y+1/2' 192 '-x, z+1/2, -y+1/2' loop_ _atom_type_symbol _atom_type_oxidation_number Li+ 1.0 O2- -2.0 loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Li+ Li1 8 0.250000 0.250000 0.250000 1 O2- O2 4 0.000000 0.000000 0.000000 1""" for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): self.assertEqual(l1.strip(), l2.strip())
#!/usr/bin/env python # encoding: utf-8 ''' $Author: Qiang Zhu $ Export cif file from POSCAR ''' from optparse import OptionParser from pymatgen.io.cif import CifWriter from pymatgen.io.vasp import Poscar from pymatgen.symmetry.analyzer import SpacegroupAnalyzer # ------------------------------------------------------------------ # -------------------------------- Options ------------------------- parser = OptionParser() parser.add_option('-i', '--input', help='input POSCAR file') parser.add_option('-o', '--output', help='output cif file') parser.add_option('-t', '--tolerance', type=float, default=0.001, help='') (options, args) = parser.parse_args() tol = options.tolerance p = Poscar.from_file(options.input) finder = SpacegroupAnalyzer(p.structure, symprec=tol, angle_tolerance=5) print('Space group:', finder.get_space_group_symbol(), 'tolerance:', tol) print(finder.get_symmetrized_structure()) CifWriter(p.structure, symprec=tol).write_file(options.output)
def output_as_cif(self, symprec=None): print(CifWriter(self.to_pymatgen_structure(), symprec))
def cif_lib_build(self, crystal_system, size_limit=None): ''' function to build cif and pdf library based on space group symbol Parameters ---------- crystal_system: str name of crystal system. It capitalized, like CUBIC. space group symbol will be generated by get_symbol_list method size_list : int optional. Uppder limit of data pulled out per symbol ''' self.crystal_system = crystal_system space_group_symbol = self.get_symbol_list(crystal_system) if isinstance(space_group_symbol, list): space_group_symbol_set = space_group_symbol else: space_group_symbol_set = list(spac_group_symbol) ## changing dir data_dir = os.path.join(self.working_dir, crystal_system) self.data_dir = data_dir self._makedirs(data_dir) os.chdir(data_dir) if os.getcwd() == data_dir: print('Library will be built at %s' % data_dir) else: e = 'Werid, return' raise RuntimeError(e) # summary lists missed_list = [] # reference m_id_list = [] # reference for searchs have been done in the past time_info = time.strftime('%Y-%m-%d') # create dirs, cif and calculated dir cif_dir = os.path.join(data_dir, 'cif_data') self._makedirs(cif_dir) self.cif_dir = cif_dir # looping for space_group_symbol in space_group_symbol_set: print('Building library with space_group symbol: {}'.format(space_group_symbol)) ## search query m = MPRester(self.API_key) search = m.query(criteria = {"spacegroup.symbol": space_group_symbol}, properties = ["material_id"]) if search: ## crazy looping if size_limit: dim = 400 # 400 data sets per symbol else: dim = len(search) print('Pull out %s data sets' % dim) print('Now, starts to save cif and compute pdf...') for i in range(dim): # part 1: grab cif files from data base m_id = search[i]['material_id'] m_id_list.append(m_id) m_struc = m.get_structure_by_material_id(m_id) m_formula = m_struc.formula m_name = m_formula.replace(' ', '') # material name cif_w = CifWriter(m_struc) cif_name = '{}_{}.cif'.format(space_group_symbol, m_name) cif_w_name = os.path.join(cif_dir, cif_name) if os.path.isfile(cif_w_name): print('already have {}, skip'.format(cif_name)) pass # skip files already exist else: cif_w.write_file(cif_w_name) print('{} has been saved'.format(cif_name)) else: print('Hmm, no reasult. Something wrong') missed_list.append(space_group_symbol) pass m_id_list_name = '{}_{}_material_id.txt'.format(crystal_system, time_info) m_id_list_w_name = os.path.join(data_dir, m_id_list_name) np.savetxt(m_id_list_w_name, m_id_list) print('''SUMMARY: for {} cystsal sytem, Symbols {} can't be found from data base'''.format(crystal_system, missed_list)) return cif_dir
def get_cif(filename, tolerance=0.1): struc = Structure.from_file(filename) cif = CifWriter(struc, symprec=tolerance) cif.write_file(filename + '.cif')
# import structure into pymatgen strucbin = "/home/wwwennie/[email protected]/bin/pos_tmp/" #filname = strucbin+"tet.in" #bivo4 = struct_import(ubin,filname) # #filname = strucbin+"pseudotet.in" # volume expansion, not quite hydrostatic #bivo4comp = struct_import(filname) filname = strucbin + "Ov-s15v20.in" bivo4surf = struct_import(filname) ########### polaron bias ######### struct = bias_polaron(bivo4surf, 121, 1.9, bias=1.05) w = CifWriter(struct) w.write_file("bias.cif") ########### surface structure histogram ####### #title="Bond length distribution" #legend=["Bi-O","V-O"] #len_BiO,surfBiatoms = bonds.surf_spec_bond_len(bivo4surf,2.8,'Bi','O',n=2) #len_VO,surfVatoms = bonds.surf_spec_bond_len(bivo4surf,2.8,'V','O',n=2) #plot.hist_plot([len_BiO,len_VO], title,legend,xlim=[1.6,2.65]) # #title="Bond angle distribtion" #legend=["O-Bi-O","O-V-O"] #ang_BiO = bonds.surf_spec_bond_angle(bivo4,2.8,'Bi','O',n=2) #ang_VO = bonds.surf_spec_bond_angle(bivo4,2.8,'V','O',n=2) #plot.hist_plot([ang_BiO,ang_VO], title,legend,xlim=[65,165]) #
def generate_ewald_orderings(path, choose_file, oxidation_states, num_structures): """ DESCRIPTION: Given a disordered CIF structure with at least one crystallographic site that is shared by more than one element, all permutations will have their electrostatic energy calculated via an Ewald summation, given that all ion charges are specified. Ordered CIF structures will be generated, postpended with a number that indicates the stability ranking of the structure. For example, if a CIF file called "Na2Mn2Fe(VO4)3.cif" is inputted with num_structures=3, then the function will generate 3 ordered output files, "Na2Mn2Fe(VO4)3-ewald-1", "Na2Mn2Fe(VO4)3-ewald-2", and "Na2Mn2Fe(VO4)3-ewald-3", with "Na2Mn2Fe(VO4)3-ewald-1" being the most stable and "Na2Mn2Fe(VO4)3-ewald-3" being the least stable. Note that this function does not take into account the symmetry of the crystal, and thus it may give several structures which are symmetrically identical under a space group. Use "find_unique_structures" to isolate unique orderings. PARAMETERS: path: string The file path to the CIF file. The CIF file must be a disordered structure, or else an error will occur. A disordered structure will have one site that is occupied by more than one element, with occupancies less than 1: i.e. Fe at 0,0,0.5 with an occupancy of 0.75, and Mn at the same site 0,0,0.5 with an occupancy of 0.25. This function cannot handle multivalent elements, for example it cannot handle a structure that has Mn in both the 2+ and 3+ redox state. choose_file: boolean Setting this parameter to True brings up the file explorer dialog for the user to manually select the CIF file oxidation_states: dictionary A dictionary that maps each element in the structure to a particular oxidation state. E.g. {"Fe": 3, "Mn": 2, "O": -2, "V": 5, "Na": 1, "Al":3} Make sure that all elements in the structure is assigned an oxidation state. It is ok to add more elements than needed. num_structures: int The number of strcutures to be outputted by the function. There can be hundreds or thousands of candidate structures, however in practice only the first few (or even only the first, most stable) structures are needed. RETURNS: None """ # open file dialog if file is to be manually chosen if choose_file: root = tk.Tk() root.withdraw() path = filedialog.askopenfilename() #Read cif file cryst = Structure.from_file(path) analyzer = SpacegroupAnalyzer(cryst) space_group = analyzer.get_space_group_symbol() print(space_group) symm_struct = analyzer.get_symmetrized_structure() cryst = TransformedStructure(symm_struct) #Create Oxidation State Transform oxidation_transform = OxidationStateDecorationTransformation( oxidation_states) #Create Ewald Ordering Transform object which will be passed into the transmuter ordering_transform = OrderDisorderedStructureTransformation( symmetrized_structures=True) # apply the order-disorder transform on the structure for any site that has fractional occupancies transmuter = StandardTransmuter([cryst], [oxidation_transform, ordering_transform], extend_collection=num_structures) print("Ewald optimization successful!") num_structures = len(transmuter.transformed_structures) for i in range(num_structures): newCryst = transmuter.transformed_structures[i].final_structure #Save to CIF structure_name = os.path.splitext(os.path.basename(path))[0] save_directory = structure_name if not os.path.isdir(save_directory): os.mkdir(save_directory) filename = structure_name + '/' + structure_name + '-ewald' + '-%i' % ( i + 1) w = CifWriter(newCryst) w.write_file(filename + '.cif') print("Cif file saved to {}.cif".format(filename)) #Save to POSCAR poscar = Poscar(newCryst) poscar.write_file(filename) print("POSCAR file saved to {}".format(filename))
def test_write(self): s_ncl = self.mcif_ncl.get_structures(primitive=False)[0] cw = CifWriter(s_ncl, write_magmoms=True) cw_ref_string = """# generated using pymatgen data_GdB4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 7.13160000 _cell_length_b 7.13160000 _cell_length_c 4.05050000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural GdB4 _chemical_formula_sum 'Gd4 B16' _cell_volume 206.007290027 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd Gd1 1 0.317460 0.817460 0.000000 1.0 Gd Gd2 1 0.182540 0.317460 0.000000 1.0 Gd Gd3 1 0.817460 0.682540 0.000000 1.0 Gd Gd4 1 0.682540 0.182540 0.000000 1.0 B B5 1 0.000000 0.000000 0.202900 1.0 B B6 1 0.500000 0.500000 0.797100 1.0 B B7 1 0.000000 0.000000 0.797100 1.0 B B8 1 0.500000 0.500000 0.202900 1.0 B B9 1 0.175900 0.038000 0.500000 1.0 B B10 1 0.962000 0.175900 0.500000 1.0 B B11 1 0.038000 0.824100 0.500000 1.0 B B12 1 0.675900 0.462000 0.500000 1.0 B B13 1 0.324100 0.538000 0.500000 1.0 B B14 1 0.824100 0.962000 0.500000 1.0 B B15 1 0.538000 0.675900 0.500000 1.0 B B16 1 0.462000 0.324100 0.500000 1.0 B B17 1 0.086700 0.586700 0.500000 1.0 B B18 1 0.413300 0.086700 0.500000 1.0 B B19 1 0.586700 0.913300 0.500000 1.0 B B20 1 0.913300 0.413300 0.500000 1.0 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z Gd1 5.05 5.05 0.0 Gd2 -5.05 5.05 0.0 Gd3 5.05 -5.05 0.0 Gd4 -5.05 -5.05 0.0 """ self.assertEqual(cw.__str__(), cw_ref_string)
for i in data: row = [] material_id = i['material_id'] row.append(material_id) row.append(i['pretty_formula']) row.append(i['nelements']) row.append(i['nsites']) row.append(i['is_hubbard']) row.append(i['is_compatible']) row.append(i['volume']) row.append(i['density']) row.append(i['energy_per_atom']) row.append(i['formation_energy_per_atom']) # save cif and csv files c = CifWriter(i['structure']) # add G_Voigt_Reuss_Hill, K_Voigt_Reuss_Hill, elastic_anisotropy, poisson_ratio if search_key == 'elasticity': elasticity = i['elasticity'] row.append(elasticity['G_Voigt_Reuss_Hill']) row.append(elasticity['K_Voigt_Reuss_Hill']) row.append(elasticity['elastic_anisotropy']) row.append(elasticity['poisson_ratio']) cif_file = './training/elasticity/data/' + material_id + '.cif' c.write_file(cif_file) csv_writer_warnings.writerow(row) if elasticity['warnings']: continue else: csv_writer.writerow(row)
def find_unique_structures(base_crystal_path, directory): """ DESCRIPTION: Given a base crystal structure along with a directory containing CIF structures, determine how many unique configurations are in the directory, and assign a configuration ID number to each CIF structure in the directory. Results can be seen in the outputted unique.csv file. The function uses the base crystal structure provided to find the space group and associated symmetry operations, which are then used to see whether the CIF structures in the directory are equivalent. PARAMETERS: base_crystal_path: string The path to the base crystal CIF structure. Note that this structure should contain the space group that you want to check all other structures to. If the symmetry of this structure is incorrect, you will get unexpected results. directory: string The path to the directory containing the CIF structures to compare. Note that this function assumes that the CIF names are all prefixed by a dash and followed by an interger, ie "LiCoO2-1", "LiCoO2-2", "LiCoO2-3"..., ect. RETURNS: None """ # convert all files (they should all be cif files) in the directory into Structures and place them into a list cif_file_names = [ os.path.splitext(os.path.basename(path))[0] for path in os.listdir(directory) if path.endswith('.cif') ] cif_files = [ directory + path for path in os.listdir(directory) if path.endswith('.cif') ] cif_files = sorted(cif_files, key=lambda x: int(x.split("-")[-1].replace(".cif", ""))) cif_file_names = sorted(cif_file_names, key=lambda x: int(x.split("-")[-1])) structures = [IStructure.from_file(path) for path in cif_files] print(cif_file_names) # Get the base crystal structure base_crystal = IStructure.from_file(base_crystal_path) # Get the space group of the base crystal analyzer = SpacegroupAnalyzer(base_crystal) spacegroup = analyzer.get_space_group_operations() print(spacegroup) id = 1 num_structures = len(structures) config_dict = {} unique_structs = [] for i in range(num_structures): config1 = structures[i] unique_cif_name = cif_file_names[i] if not unique_cif_name in config_dict: config_dict[unique_cif_name] = id print("%s Unique Structures Found..." % (id)) unique_structs.append(config1) id += 1 for j in range(num_structures): cif_name = cif_file_names[j] config2 = structures[j] if not cif_name in config_dict: isEquivalent = spacegroup.are_symmetrically_equivalent( config1, config2) if isEquivalent: config_dict[cif_name] = config_dict[unique_cif_name] print("----------------------------------------------") print("%s Total Unique Structures Found" % (id - 1)) print("----------------------------------------------") with open('unique.csv', 'w') as f: for key in config_dict.keys(): f.write("%s,%s\n" % (key, config_dict[key])) crystal_name = os.path.splitext(os.path.basename(base_crystal_path))[0] directory_path = "{}-unique".format(crystal_name) if not os.path.isdir(directory_path): os.mkdir(directory_path) num_unique_structures = len(unique_structs) for i in range(num_unique_structures): config = unique_structs[i] #Save to CIF filename = crystal_name + '_ewald' + '_{}'.format(i + 1) w = CifWriter(config) w.write_file(directory_path + '/' + filename + '.cif') # print("Cif file saved to {}.cif".format(filename)) #Save to POSCAR poscar = Poscar(config) poscar.write_file(directory_path + '/' + filename)
# coding: utf-8 # In[5]: from pymatgen import Structure from pymatgen import symmetry from pymatgen.ext.matproj import MPRester from pymatgen.io.cif import CifWriter from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from pymatgen.core.operations import SymmOp from IPython.display import Image with MPRester("izD7mJmnjhUOKyWGtZ") as m: # Structure for material id structure = m.get_structure_by_material_id("mp-27869") w = CifWriter(structure) w.write_file('mp-27869.cif') sGP = SpacegroupAnalyzer(structure) print("2ème élément de symétrie (Ci:0 0 0):") Op1 = SymmOp.from_xyz_string("-x, -y, -z") print("Effet sur P1 #2:") Eff1 = Op1.operate((0, 0, 1 / 2)) print(Eff1) display(Image(filename='sym1.jpg')) print("4ème élément de symétrie (3-bar axis:y,-x+y,-z):") Op2 = SymmOp.from_xyz_string("y,-x+y,-z") print("Effet sur BaO1 #4:") Eff2 = Op2.operate((0, 0, 0.24)) print(Eff2) display(Image(filename='sym2.jpg')) print("5ème élément de symétrie (3-bar axis:-x+y,-x,z):")
def get_string(self): from pymatgen import Structure lines, scope = [], [] table_start = mp_level01_titles[1] + '_' for key, value in self.document.iterate(): if isinstance(value, Table): header = any([ bool(isinstance(col, unicode) or isinstance(col, str)) for col in value ]) if isinstance(value.index, MultiIndex): value.reset_index(inplace=True) csv_string = value.to_csv(index=False, header=header, float_format='%g', encoding='utf-8')[:-1] lines += csv_string.decode('utf-8').split('\n') elif isinstance(value, Structure): from pymatgen.io.cif import CifWriter cif = CifWriter(value, symprec=symprec).__str__() lines.append( make_pair(''.join([replacements.get(c, c) for c in key]), cif + ':end')) else: level, key = key key = key if isinstance(key, unicode) else key.decode('utf-8') # truncate scope level_reduction = bool(level < len(scope)) if level_reduction: del scope[level:] # append scope and set delimiters if value is None: is_table = key.startswith(table_start) if is_table: # account for 'data_' prefix key = key[len(table_start):] start, end = '\n[+', ']' else: start, end = '\n{', '}' scope.append(''.join([replacements.get(c, c) for c in key])) # correct scope to omit internal 'general' section scope_corr = scope if scope[0] == mp_level01_titles[0]: scope_corr = scope[1:] # insert scope line if (value is None and scope_corr)or \ (value is not None and level_reduction): lines.append(start + '.'.join(scope_corr) + end) # insert key-value line if value is not None: val = unicode(value) if not isinstance(value, str) else value value_lines = [val] if val.startswith('http') \ else textwrap.wrap(val) if len(value_lines) > 1: value_lines = [''] + value_lines + [':end'] lines.append( make_pair( ''.join([replacements.get(c, c) for c in key]), '\n'.join(value_lines))) return '\n'.join(lines) + '\n'
from pymatgen.io.cif import CifWriter def get_struc(infile, cid): with open(infile, 'rb') as f: struc_dict = pickle.load(f) return struc_dict[cid] if __name__ == '__main__': ''' extract a structure from init_struc_data.pkl or opt_struc_data.pkl and output cif file ''' # ---------- argparse parser = argparse.ArgumentParser() parser.add_argument('-s', '--symmetrized', help='flag for symmetrized structure', action='store_true') parser.add_argument('infile', help='input file') parser.add_argument('cid', help='structure ID', type=int) args = parser.parse_args() # ---------- get structure struc = get_struc(args.infile, args.cid) # ---------- write cif if args.symmetrized: cw = CifWriter(struc, symprec=0.1) else: cw = CifWriter(struc, symprec=None) cw.write_file('{}.cif'.format(args.cid))
# initialize a list to store all the structures struct_lst = [] with mg.MPRester(api_key) as m: for formula, spacegroup_number in zip(mp_query_df.formula, mp_query_df.spacegroup_number): try: # query structures based on the pretty formula and spacegroup number struct = m.query(criteria={"pretty_formula": formula, "spacegroup.number": spacegroup_number}, properties=["structure"])[0]["structure"] except IndexError: # if there isn't an exact, get the pretty formula struct = formula struct_lst.append(struct) # %% examine the query result # check which compounds don't have an exact match in Materials Project unmatched_struct = [structure for structure in struct_lst if isinstance(structure, str)] print("Number of unmatched structures: {}\n {}".format(len(unmatched_struct), unmatched_struct)) # there are 15 out of 90 unmatched structures # get the compound structures with a match matched_struct = [structure for structure in struct_lst if isinstance(structure, mg.Structure)] # write the structures as CIF files for structure in matched_struct: pretty_formula = structure.composition.reduced_formula cif = CifWriter(structure) cif.write_file(STRUCT_PATH + pretty_formula + ".cif")
def test_write(self): cw_ref_string = """# generated using pymatgen data_GdB4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 7.13160000 _cell_length_b 7.13160000 _cell_length_c 4.05050000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural GdB4 _chemical_formula_sum 'Gd4 B16' _cell_volume 206.00729003 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd Gd0 1 0.31746000 0.81746000 0.00000000 1.0 Gd Gd1 1 0.18254000 0.31746000 0.00000000 1.0 Gd Gd2 1 0.81746000 0.68254000 0.00000000 1.0 Gd Gd3 1 0.68254000 0.18254000 0.00000000 1.0 B B4 1 0.00000000 0.00000000 0.20290000 1.0 B B5 1 0.50000000 0.50000000 0.79710000 1.0 B B6 1 0.00000000 0.00000000 0.79710000 1.0 B B7 1 0.50000000 0.50000000 0.20290000 1.0 B B8 1 0.17590000 0.03800000 0.50000000 1.0 B B9 1 0.96200000 0.17590000 0.50000000 1.0 B B10 1 0.03800000 0.82410000 0.50000000 1.0 B B11 1 0.67590000 0.46200000 0.50000000 1.0 B B12 1 0.32410000 0.53800000 0.50000000 1.0 B B13 1 0.82410000 0.96200000 0.50000000 1.0 B B14 1 0.53800000 0.67590000 0.50000000 1.0 B B15 1 0.46200000 0.32410000 0.50000000 1.0 B B16 1 0.08670000 0.58670000 0.50000000 1.0 B B17 1 0.41330000 0.08670000 0.50000000 1.0 B B18 1 0.58670000 0.91330000 0.50000000 1.0 B B19 1 0.91330000 0.41330000 0.50000000 1.0 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z Gd0 5.05000000 5.05000000 0.00000000 Gd1 -5.05000000 5.05000000 0.00000000 Gd2 5.05000000 -5.05000000 0.00000000 Gd3 -5.05000000 -5.05000000 0.00000000 """ s_ncl = self.mcif_ncl.get_structures(primitive=False)[0] cw = CifWriter(s_ncl, write_magmoms=True) self.assertEqual(cw.__str__(), cw_ref_string) # from list-type magmoms list_magmoms = [list(m) for m in s_ncl.site_properties['magmom']] # float magmoms (magnitude only) float_magmoms = [float(m) for m in s_ncl.site_properties['magmom']] s_ncl.add_site_property('magmom', list_magmoms) cw = CifWriter(s_ncl, write_magmoms=True) self.assertEqual(cw.__str__(), cw_ref_string) s_ncl.add_site_property('magmom', float_magmoms) cw = CifWriter(s_ncl, write_magmoms=True) cw_ref_string_magnitudes = """# generated using pymatgen data_GdB4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 7.13160000 _cell_length_b 7.13160000 _cell_length_c 4.05050000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural GdB4 _chemical_formula_sum 'Gd4 B16' _cell_volume 206.00729003 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd Gd0 1 0.31746000 0.81746000 0.00000000 1.0 Gd Gd1 1 0.18254000 0.31746000 0.00000000 1.0 Gd Gd2 1 0.81746000 0.68254000 0.00000000 1.0 Gd Gd3 1 0.68254000 0.18254000 0.00000000 1.0 B B4 1 0.00000000 0.00000000 0.20290000 1.0 B B5 1 0.50000000 0.50000000 0.79710000 1.0 B B6 1 0.00000000 0.00000000 0.79710000 1.0 B B7 1 0.50000000 0.50000000 0.20290000 1.0 B B8 1 0.17590000 0.03800000 0.50000000 1.0 B B9 1 0.96200000 0.17590000 0.50000000 1.0 B B10 1 0.03800000 0.82410000 0.50000000 1.0 B B11 1 0.67590000 0.46200000 0.50000000 1.0 B B12 1 0.32410000 0.53800000 0.50000000 1.0 B B13 1 0.82410000 0.96200000 0.50000000 1.0 B B14 1 0.53800000 0.67590000 0.50000000 1.0 B B15 1 0.46200000 0.32410000 0.50000000 1.0 B B16 1 0.08670000 0.58670000 0.50000000 1.0 B B17 1 0.41330000 0.08670000 0.50000000 1.0 B B18 1 0.58670000 0.91330000 0.50000000 1.0 B B19 1 0.91330000 0.41330000 0.50000000 1.0 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z Gd0 0.00000000 0.00000000 7.14177849 Gd1 0.00000000 0.00000000 7.14177849 Gd2 0.00000000 0.00000000 -7.14177849 Gd3 0.00000000 0.00000000 -7.14177849 """ self.assertEqual(cw.__str__().strip(), cw_ref_string_magnitudes.strip()) # test we're getting correct magmoms in ncl case s_ncl2 = self.mcif_ncl2.get_structures()[0] list_magmoms = [list(m) for m in s_ncl2.site_properties['magmom']] self.assertEqual(list_magmoms[0][0], 0.0) self.assertAlmostEqual(list_magmoms[0][1], 5.9160793408726366) self.assertAlmostEqual(list_magmoms[1][0], -5.1234749999999991) self.assertAlmostEqual(list_magmoms[1][1], 2.9580396704363183) # test creating an structure without oxidation state doesn't raise errors s_manual = Structure(Lattice.cubic(4.2), ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]]) s_manual.add_spin_by_site([1, -1]) cw = CifWriter(s_manual, write_magmoms=True) # check oxidation state cw_manual_oxi_string = """# generated using pymatgen data_CsCl _symmetry_space_group_name_H-M 'P 1' _cell_length_a 4.20000000 _cell_length_b 4.20000000 _cell_length_c 4.20000000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 1 _chemical_formula_structural CsCl _chemical_formula_sum 'Cs1 Cl1' _cell_volume 74.08800000 _cell_formula_units_Z 1 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' loop_ _atom_type_symbol _atom_type_oxidation_number Cs+ 1.0 Cl+ 1.0 loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Cs+ Cs0 1 0.00000000 0.00000000 0.00000000 1 Cl+ Cl1 1 0.50000000 0.50000000 0.50000000 1 loop_ _atom_site_moment_label _atom_site_moment_crystalaxis_x _atom_site_moment_crystalaxis_y _atom_site_moment_crystalaxis_z """ s_manual.add_oxidation_state_by_site([1, 1]) cw = CifWriter(s_manual, write_magmoms=True) self.assertEqual(cw.__str__(), cw_manual_oxi_string)
def test_symmetrized(self): filepath = self.TEST_FILES_DIR / 'POSCAR' poscar = Poscar.from_file(filepath, check_for_POTCAR=False) writer = CifWriter(poscar.structure, symprec=0.1) ans = """# generated using pymatgen data_FePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 10.41176687 _cell_length_b 6.06717188 _cell_length_c 4.75948954 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 62 _chemical_formula_structural FePO4 _chemical_formula_sum 'Fe4 P4 O16' _cell_volume 300.65685512 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 '-x+1/2, -y, z+1/2' 4 'x+1/2, y, -z+1/2' 5 'x+1/2, -y+1/2, -z+1/2' 6 '-x+1/2, y+1/2, z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Fe Fe1 4 0.218728 0.250000 0.525133 1 P P2 4 0.094613 0.750000 0.581757 1 O O3 8 0.165710 0.546072 0.714616 1 O O4 4 0.043372 0.250000 0.292862 1 O O5 4 0.096642 0.750000 0.258680 1""" cif = CifParser.from_string(str(writer)) m = StructureMatcher() self.assertTrue(m.fit(cif.get_structures()[0], poscar.structure)) # for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): # self.assertEqual(l1.strip(), l2.strip()) ans = """# generated using pymatgen data_LiFePO4 _symmetry_space_group_name_H-M Pnma _cell_length_a 10.41037000 _cell_length_b 6.06577000 _cell_length_c 4.74480000 _cell_angle_alpha 90.00000000 _cell_angle_beta 90.00000000 _cell_angle_gamma 90.00000000 _symmetry_Int_Tables_number 62 _chemical_formula_structural LiFePO4 _chemical_formula_sum 'Li4 Fe4 P4 O16' _cell_volume 299.619458734 _cell_formula_units_Z 4 loop_ _symmetry_equiv_pos_site_id _symmetry_equiv_pos_as_xyz 1 'x, y, z' 2 '-x, -y, -z' 3 '-x+1/2, -y, z+1/2' 4 'x+1/2, y, -z+1/2' 5 'x+1/2, -y+1/2, -z+1/2' 6 '-x+1/2, y+1/2, z+1/2' 7 '-x, y+1/2, -z' 8 'x, -y+1/2, z' loop_ _atom_site_type_symbol _atom_site_label _atom_site_symmetry_multiplicity _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Li Li1 4 0.000000 0.000000 0.000000 1.0 Fe Fe2 4 0.218845 0.750000 0.474910 1.0 P P3 4 0.094445 0.250000 0.417920 1.0 O O4 8 0.165815 0.044060 0.286540 1.0 O O5 4 0.043155 0.750000 0.708460 1.0 O O6 4 0.096215 0.250000 0.741480 1.0 """ s = Structure.from_file(self.TEST_FILES_DIR / 'LiFePO4.cif') writer = CifWriter(s, symprec=0.1) s2 = CifParser.from_string(str(writer)).get_structures()[0] self.assertTrue(m.fit(s, s2)) s = self.get_structure("Li2O") writer = CifWriter(s, symprec=0.1) s2 = CifParser.from_string(str(writer)).get_structures()[0] self.assertTrue(m.fit(s, s2)) # test angle tolerance. s = Structure.from_file(self.TEST_FILES_DIR / 'LiFePO4.cif') writer = CifWriter(s, symprec=0.1, angle_tolerance=0) d = list(writer.ciffile.data.values())[0] self.assertEqual(d["_symmetry_Int_Tables_number"], 14) s = Structure.from_file(self.TEST_FILES_DIR / 'LiFePO4.cif') writer = CifWriter(s, symprec=0.1, angle_tolerance=2) d = list(writer.ciffile.data.values())[0] self.assertEqual(d["_symmetry_Int_Tables_number"], 62)
species = [] atoms = False for line in fp: if "end" in line: atoms = False if atoms == True: curr_line = line.split() specie = curr_line[0] xyz = [float(curr_line[1]),float(curr_line[2]),float(curr_line[3])] species.append(specie) coords.append(xyz) if "PBC " in line: curr_line = line.split() abc = [float(curr_line[1]),float(curr_line[2]),float(curr_line[3])] angles = [float(curr_line[4]),float(curr_line[5]),float(curr_line[6])] atoms = True lattice = Lattice.from_lengths_and_angles(abc,angles) structure = Structure(lattice, species, coords, coords_are_cartesian=True) return structure # Usage: # $python car_reader.py FILENAME.car # Writes FILENAME.cif # First Argument given to python script is filename filename = sys.argv[1] # reads file structure = read_car_file(filename) # Writes .cif file of converted structure CifWriter(structure.get_sorted_structure()).write_file(Path(filename).with_suffix('.cif'))