def test_no_symmops(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") f = os.path.join(test_dir, "nosymm.cif") p = CifParser(f) s = p.get_structures()[0] self.assertEqual(s.formula, "H96 C60 O8")
def test_one_line_symm(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") f = os.path.join(test_dir, "OneLineSymmP1.cif") p = CifParser(f) s = p.get_structures()[0] self.assertEqual(s.formula, "Ga4 Pb2 O8")
def test_jahn_teller_structure_analysis(self): parser = CifParser(os.path.join(test_dir, 'LiFePO4.cif')) LiFePO4 = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'Fe3O4.cif')) Fe3O4 = parser.get_structures()[0] self.assertTrue(self.jt.is_jahn_teller_active(LiFePO4)) self.assertTrue(self.jt.is_jahn_teller_active(Fe3O4)) LiFePO4_analysis = { 'active': True, 'strength': 'weak', 'sites': [ { 'ligand': 'O2-', 'ligand_bond_length_spread': 0.2111, 'ligand_bond_lengths': [2.1382, 2.0840, 2.0863, 2.2383, 2.2951, 2.2215], 'strength': 'weak', 'motif': 'oct', 'motif_order_parameter': 0.1441, 'site_indices': [4, 5, 6, 7], 'species': 'Fe2+', 'spin_state': 'unknown' } ] } self.assertDictEqual(LiFePO4_analysis, self.jt.get_analysis(LiFePO4))
def test_bad_cif(self): f = os.path.join(test_dir, "bad_occu.cif") p = CifParser(f) self.assertRaises(ValueError, p.get_structures) p = CifParser(f, occupancy_tolerance=2) s = p.get_structures()[0] self.assertAlmostEqual(s[0].species_and_occu["Al3+"], 0.5)
def test_no_symmops(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") f = self.TEST_FILES_DIR / "nosymm.cif" p = CifParser(f) s = p.get_structures()[0] self.assertEqual(s.formula, "H96 C60 O8")
def test_implicit_hydrogen(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") parser = CifParser(os.path.join(test_dir, 'Senegalite_implicit_hydrogen.cif')) for s in parser.get_structures(): self.assertEqual(s.formula, "Al8 P4 O32") self.assertEqual(sum(s.site_properties['implicit_hydrogens']), 20)
def test_one_line_symm(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") f = self.TEST_FILES_DIR / "OneLineSymmP1.cif" p = CifParser(f) s = p.get_structures()[0] self.assertEqual(s.formula, "Ga4 Pb2 O8")
def setUp(self): warnings.filterwarnings("ignore") self.mcif = CifParser(self.TEST_FILES_DIR / "magnetic.example.NiO.mcif") self.mcif_ncl = CifParser(self.TEST_FILES_DIR / "magnetic.ncl.example.GdB4.mcif") self.mcif_incom = CifParser(self.TEST_FILES_DIR / "magnetic.incommensurate.example.Cr.mcif") self.mcif_disord = CifParser(self.TEST_FILES_DIR / "magnetic.disordered.example.CuMnO2.mcif") self.mcif_ncl2 = CifParser(self.TEST_FILES_DIR / "Mn3Ge_IR2.mcif")
def test_replacing_finite_precision_frac_coords(self): f = self.TEST_FILES_DIR / "cif_finite_precision_frac_coord_error.cif" with warnings.catch_warnings(): p = CifParser(f) s = p.get_structures()[0] self.assertEqual(str(s.composition), "N5+24") self.assertIn("Some fractional co-ordinates rounded to ideal values to " "avoid finite precision errors.", p.errors)
def setUp(self): """ Setup Fe3O4 structure for testing multiple oxidation states """ cif_ob = CifParser(os.path.join(test_dir, "Fe3O4.cif")) self._struct = cif_ob.get_structures()[0] self._valrad_evaluator = ValenceIonicRadiusEvaluator(self._struct) self._length = len(self._struct.sites)
def test_missing_atom_site_type_with_oxistates(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") parser = CifParser(self.TEST_FILES_DIR / 'P24Ru4H252C296S24N16.cif') c = Composition({'S0+': 24, 'Ru0+': 4, 'H0+': 252, 'C0+': 296, 'N0+': 16, 'P0+': 24}) for s in parser.get_structures(False): self.assertEqual(s.composition, c)
def test_bad_cif(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") f = self.TEST_FILES_DIR / "bad_occu.cif" p = CifParser(f) self.assertRaises(ValueError, p.get_structures) p = CifParser(f, occupancy_tolerance=2) s = p.get_structures()[0] self.assertAlmostEqual(s[0].species["Al3+"], 0.5)
def test_bad_cif(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") f = os.path.join(test_dir, "bad_occu.cif") p = CifParser(f) self.assertRaises(ValueError, p.get_structures) p = CifParser(f, occupancy_tolerance=2) s = p.get_structures()[0] self.assertAlmostEqual(s[0].species_and_occu["Al3+"], 0.5)
def test_cluster_from_file(self): r = CifParser(os.path.join(test_dir, "CoO19128.cif")) structure = r.get_structures()[0] atoms = Atoms(structure, "O", 10.0) atoms.write_file("ATOMS_test") mol_1 = Atoms.cluster_from_file("ATOMS_test") mol_2 = Atoms.cluster_from_file(os.path.join(test_dir, "ATOMS")) self.assertEqual(mol_1.formula, mol_2.formula) self.assertEqual(len(mol_1), len(mol_2)) os.remove("ATOMS_test")
def setUp(self): self.mcif = CifParser(os.path.join(test_dir, "magnetic.example.NiO.mcif")) self.mcif_ncl = CifParser(os.path.join(test_dir, "magnetic.ncl.example.GdB4.mcif")) self.mcif_incom = CifParser(os.path.join(test_dir, "magnetic.incommensurate.example.Cr.mcif")) self.mcif_disord = CifParser(os.path.join(test_dir, "magnetic.disordered.example.CuMnO2.mcif")) self.mcif_ncl2 = CifParser(os.path.join(test_dir, "Mn3Ge_IR2.mcif"))
def handle_insufficientpowderdata(cif_string): """ Handles CIF parsing errors arising from too few or too many values in data loop for diffraction data. :param cif_string: (str) cif file :return: corrected cif string """ smlineno = 0 looplineno = 0 cif_lines = json.loads(json.dumps(cif_string)).splitlines() powderdataline = False loopdataline = False cif_string_new = '' for lineno, line in enumerate(cif_lines): if '_sm_powderpattern_remark' in line: powderdataline = True smlineno = lineno + 1 break else: cif_string_new += line + '\n' if powderdataline: for line in cif_lines[smlineno:]: line_list = line.split() if len(line_list) > 10: cif_string_new += line + '\n' elif 1 < len(line_list) < 11: cif_string_new += '#' + line + '\n' try: print CifParser.from_string(cif_string_new).get_structures()[0].as_dict() return cif_string_new except: print 'UNSUCCESSFUL 1st attempt (uncommenting lines with insufficient or too many values for powder pattern)' cif_string_new = '' for lineno, line in enumerate(cif_lines): if 'loop_' in line: if '_sm_powderpattern' in cif_lines[lineno + 1]: cif_string_new += '#' + line + '\n' loopdataline = True looplineno = lineno + 1 break else: cif_string_new += line + '\n' else: cif_string_new += line + '\n' if loopdataline: for line in cif_lines[looplineno:]: cif_string_new += '#' + line + '\n' try: print CifParser.from_string(cif_string_new).get_structures()[0].as_dict() return cif_string_new except: print 'UNSUCCESSFUL 2nd attempt (uncommenting all powder diffraction lines)' return cif_string_new
def setUp(self): filepath1 = os.path.join(test_dir, 'Li2O.cif') p = CifParser(filepath1).get_structures(False)[0] bv = BVAnalyzer() valences = bv.get_valences(p) el = [site.species_string for site in p.sites] val_dict = dict(zip(el, valences)) self._radii = {} for k, v in val_dict.items(): k1 = re.sub('[1-9,+,\-]', '', k) self._radii[k1] = float(Specie(k1, v).ionic_radius) p.remove(0) self._vac_struct = p
def test_implicit_hydrogen(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") parser = CifParser(self.TEST_FILES_DIR / 'Senegalite_implicit_hydrogen.cif') for s in parser.get_structures(): self.assertEqual(s.formula, "Al8 P4 O32") self.assertEqual(sum(s.site_properties['implicit_hydrogens']), 20) self.assertIn("Structure has implicit hydrogens defined, " "parsed structure unlikely to be suitable for use " "in calculations unless hydrogens added.", parser.errors) parser = CifParser(self.TEST_FILES_DIR / 'cif_implicit_hydrogens_cod_1011130.cif') s = parser.get_structures()[0] self.assertIn("Structure has implicit hydrogens defined, " "parsed structure unlikely to be suitable for use " "in calculations unless hydrogens added.", parser.errors)
def test_find_primitive(self): """ F m -3 m Li2O testing of converting to primitive cell """ parser = CifParser(os.path.join(test_dir, 'Li2O.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure) primitive_structure = s.find_primitive() self.assertEqual(primitive_structure.formula, "Li2 O1") # This isn't what is expected. All the angles should be 60 self.assertAlmostEqual(primitive_structure.lattice.alpha, 60) self.assertAlmostEqual(primitive_structure.lattice.beta, 60) self.assertAlmostEqual(primitive_structure.lattice.gamma, 60) self.assertAlmostEqual(primitive_structure.lattice.volume, structure.lattice.volume / 4.0)
def from_cif_file(cif_file, source='', comment=''): """ Static method to create Header object from cif_file Args: cif_file: cif_file path and name source: User supplied identifier, i.e. for Materials Project this would be the material ID number comment: User comment that goes in header Returns: Header Object """ r = CifParser(cif_file) structure = r.get_structures()[0] return Header(structure, source, comment)
def handle_unparsablespecies(cif_string): """ Handles CIF parsing errors arising from unrecognizable species :param cif_string: (str) cif file :return: pymatgen structure object with appended unparsable species """ cif_string_new = '' symbols = [] coords = [] occupancies = [] cif = CifFile.from_string(cif_string).data for block in cif: if 'standardized' in block: cif_stdblock = cif[block] break for i, sym in enumerate(cif_stdblock['_atom_site_type_symbol']): if 'OH' in sym: symbols.append(sym) coords.append([float(cif_stdblock['_atom_site_fract_x'][i]), float(cif_stdblock['_atom_site_fract_y'][i]), float(cif_stdblock['_atom_site_fract_z'][i])]) occupancies.append(float(cif_stdblock['_atom_site_occupancy'][i])) for key in cif: cif_string_new += str(cif[key]) + '\n' cif_string_new += '\n' new_struct = CifParser.from_string(cif_string_new).get_structures()[0] for specie_no in range(len(symbols)): new_struct.append({DummySpecie('X'): occupancies[specie_no]}, coords[specie_no], properties={"molecule": [symbols[specie_no]]}) return new_struct
def test_CifParserCod(self): """ Parsing problematic cif files from the COD database """ with warnings.catch_warnings(): warnings.simplefilter("ignore") # Symbol in capital letters parser = CifParser(self.TEST_FILES_DIR / 'Cod_2100513.cif') for s in parser.get_structures(True): self.assertEqual(s.formula, "Ca4 Nb2.0 Al2 O12") # Label in capital letters parser = CifParser(self.TEST_FILES_DIR / 'Cod_4115344.cif') for s in parser.get_structures(True): self.assertEqual(s.formula, "Mo4 P2 H60 C60 I4 O4")
def cif2geom_sym2(cif): parser=CifParser.from_string(cif) struct=parser.get_structures()[0] sg = SpacegroupAnalyzer(struct) struct = sg.get_conventional_standard_structure() sg = SpacegroupAnalyzer(struct) geomlines=["CRYSTAL"] geomlines += ["0 0 1"] geomlines += [str(sg.get_spacegroup_number())] cry_sys = sg.get_crystal_system() lattice = struct.lattice if cry_sys == 'trigonal' or cry_sys == 'hexagonal' or cry_sys == 'tetragonal': geomlines += ["%s %s" %(lattice.a,lattice.c)] elif cry_sys == 'cubic': geomlines += ["%s" %(lattice.a)] elif cry_sys == 'triclinic': geomlines += ["%s %s %s %s %s %s" %(lattice.a,lattice.b,lattice.c,lattice.alpha,lattice.beta,lattice.gamma)] elif cry_sys == 'monoclinic': geomlines += ["%s %s %s %s" %(lattice.a,lattice.b,lattice.c,lattice.beta)] elif cry_sys == 'orthorhombic': geomlines += ["%s %s %s" %(lattice.a,lattice.b,lattice.c)] else: print('Error printing symmetrized structure.') quit() ds = sg.get_symmetry_dataset() eq_sites = np.unique(ds['equivalent_atoms']) geomlines += [str(len(eq_sites))] for eq_site in eq_sites: site = struct.sites[eq_site] geomlines += ["%s %s %s %s" %(site.specie.Z+200,site.a,site.b,site.c)] return geomlines,struct
def extract_struct(cifstr): parser = CifParser.from_string(cifstr)\ .get_structures()[0]\ .as_dict() lat_a = parser['lattice']['a'] lat_b = parser['lattice']['b'] lat_c = parser['lattice']['c'] poss = [ tuple(site['abc']) for site in parser['sites'] ] ions = [ site['species'][0]['element'] for site in parser['sites'] ] positions = {} for iidx,ion in enumerate(ions): if ion in positions.keys(): positions[ion].append(poss[iidx]) else: positions[ion] = [poss[iidx]] for key in positions.keys(): positions[key] = np.array(positions[key]) return pd.Series( [lat_a,lat_b,lat_c,positions], ['a','b','c','positions'] )
def test_get_lattice_from_lattice_type(self): cif_structure = """#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 _chemical_formula_structural FePO4 _chemical_formula_sum 'Fe4 P4 O16' _cell_volume 300.65685512 _cell_formula_units_Z 4 _symmetry_cell_setting Orthorhombic 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 Fe Fe1 1 0.218728 0.750000 0.474867 1 Fe Fe2 1 0.281272 0.250000 0.974867 1 Fe Fe3 1 0.718728 0.750000 0.025133 1 Fe Fe4 1 0.781272 0.250000 0.525133 1 P P5 1 0.094613 0.250000 0.418243 1 P P6 1 0.405387 0.750000 0.918243 1 P P7 1 0.594613 0.250000 0.081757 1 P P8 1 0.905387 0.750000 0.581757 1 O O9 1 0.043372 0.750000 0.707138 1 O O10 1 0.096642 0.250000 0.741320 1 O O11 1 0.165710 0.046072 0.285384 1 O O12 1 0.165710 0.453928 0.285384 1 O O13 1 0.334290 0.546072 0.785384 1 O O14 1 0.334290 0.953928 0.785384 1 O O15 1 0.403358 0.750000 0.241320 1 O O16 1 0.456628 0.250000 0.207138 1 O O17 1 0.543372 0.750000 0.792862 1 O O18 1 0.596642 0.250000 0.758680 1 O O19 1 0.665710 0.046072 0.214616 1 O O20 1 0.665710 0.453928 0.214616 1 O O21 1 0.834290 0.546072 0.714616 1 O O22 1 0.834290 0.953928 0.714616 1 O O23 1 0.903358 0.750000 0.258680 1 O O24 1 0.956628 0.250000 0.292862 1 """ cp = CifParser.from_string(cif_structure) s_test = cp.get_structures(False)[0] filepath = self.TEST_FILES_DIR / 'POSCAR' poscar = Poscar.from_file(filepath) s_ref = poscar.structure sm = StructureMatcher(stol=0.05, ltol=0.01, angle_tol=0.1) self.assertTrue(sm.fit(s_ref, s_test))
def _parse_structure(self, structure_schema): data = structure_schema['data'] format = structure_schema['format'] if format == 'cif': # cif lattice can be weird non standard shape structure = (CifParser.from_string(data)).get_structures()[0] lattice = pmg.Lattice.from_parameters(*structure.lattice.abc, *structure.lattice.angles) structure = pmg.Structure(lattice, structure.species, structure.frac_coords, coords_are_cartesian=False) elif format == 'POSCAR': structure = (Poscar.from_string(data)).structure return structure
def main(): parser = argparse.ArgumentParser(description=''' Example script to generate FEFF input files from a cif file Author: Alan Dozier Version: 1.0 Last updated: August, 2012''') parser.add_argument('cif_file', metavar='cif_file', type=str, nargs=1, help='cif_file to use') parser.add_argument('central_atom', metavar='central_atom', type=str, nargs=1, help='symbol of absorbing atom') parser.add_argument('calc_type', metavar='calc_type', type=str, nargs=1, help='type of calc, currently XANES or EXAFS') args = parser.parse_args() cif_file = args.cif_file[0] central_atom = args.central_atom[0] calc_type = args.calc_type[0] r = CifParser(cif_file) structure = r.get_structures()[0] x = MPXANESSet("MaterialsProject") source = os.path.basename(cif_file) comment = 'From cif file' header = MPXANESSet.get_header(x, structure, source, comment) print("\n\nHEADER\n") print(header) tags = MPXANESSet.get_feff_tags(x, calc_type) print("\n\nPARAMETERS\n") print(tags) POT = MPXANESSet.get_feff_pot(x, structure, central_atom) print("\n\nPOTENTIALS\n") print(POT) ATOMS = MPXANESSet.get_feff_atoms(x, structure, central_atom) print("\n\nATOMS\n") print(ATOMS)
def setUp(self): parser = CifParser(os.path.join(test_dir, 'Fe.cif')) self.Fe = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'LiFePO4.cif')) self.LiFePO4 = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'Fe3O4.cif')) self.Fe3O4 = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'magnetic.ncl.example.GdB4.mcif')) self.GdB4 = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'magnetic.example.NiO.mcif')) self.NiO_expt = parser.get_structures()[0] latt = Lattice.cubic(4.17) species = ["Ni", "O"] coords = [[0, 0, 0], [0.5, 0.5, 0.5]] self.NiO = Structure.from_spacegroup(225, latt, species, coords) latt = Lattice([[2.085, 2.085, 0.0], [0.0, -2.085, -2.085], [-2.085, 2.085, -4.17]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0, 0.5], [0, 0, 0], [0.25, 0.5, 0.25], [0.75, 0.5, 0.75]] self.NiO_AFM_111 = Structure(latt, species, coords, site_properties={'magmom': [-5, 5, 0, 0]}) latt = Lattice([[2.085, 2.085, 0], [0, 0, -4.17], [-2.085, 2.085, 0]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0.5, 0.5], [0, 0, 0], [0, 0.5, 0], [0.5, 0, 0.5]] self.NiO_AFM_001 = Structure(latt, species, coords, site_properties={'magmom': [-5, 5, 0, 0]})
def read_structure(filename, primitive=True, sort=False): """ Reads a structure 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/CONTCAR, CHGCAR, LOCPOT, vasprun.xml, CSSR and pymatgen's JSON serialized structures. Args: filename (str): A filename to read from. primitive (bool): Whether to convert to a primitive cell for cifs. Defaults to True. sort (bool): Whether to sort sites. Default to False. Returns: A Structure object. """ fname = os.path.basename(filename) if fnmatch(fname.lower(), "*.cif*"): parser = CifParser(filename) s = parser.get_structures(primitive=primitive)[0] elif fnmatch(fname, "POSCAR*") or fnmatch(fname, "CONTCAR*"): s = Poscar.from_file(filename, False).structure elif fnmatch(fname, "CHGCAR*") or fnmatch(fname, "LOCPOT*"): s = Chgcar.from_file(filename).structure elif fnmatch(fname, "vasprun*.xml*"): s = Vasprun(filename).final_structure elif fnmatch(fname.lower(), "*.cssr*"): cssr = Cssr.from_file(filename) s = cssr.structure elif fnmatch(fname, "*.json*") or fnmatch(fname, "*.mson*"): with zopen(filename) as f: s = json.load(f, cls=MontyDecoder) if type(s) != Structure: raise IOError("File does not contain a valid serialized " "structure") else: raise ValueError("Unrecognized file extension!") if sort: s = s.get_sorted_structure() return s
def setUp(self): latt = Lattice.cubic(4.17) species = ["Ni", "O"] coords = [[0, 0, 0], [0.5, 0.5, 0.5]] self.NiO = Structure.from_spacegroup(225, latt, species, coords) latt = Lattice([[2.085, 2.085, 0.0], [0.0, -2.085, -2.085], [-2.085, 2.085, -4.17]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0, 0.5], [0, 0, 0], [0.25, 0.5, 0.25], [0.75, 0.5, 0.75]] self.NiO_AFM_111 = Structure(latt, species, coords) self.NiO_AFM_111.add_spin_by_site([-5, 5, 0, 0]) latt = Lattice([[2.085, 2.085, 0], [0, 0, -4.17], [-2.085, 2.085, 0]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0.5, 0.5], [0, 0, 0], [0, 0.5, 0], [0.5, 0, 0.5]] self.NiO_AFM_001 = Structure(latt, species, coords) self.NiO_AFM_001.add_spin_by_site([-5, 5, 0, 0]) parser = CifParser(os.path.join(test_dir, 'Fe3O4.cif')) self.Fe3O4 = parser.get_structures()[0] trans = AutoOxiStateDecorationTransformation() self.Fe3O4_oxi = trans.apply_transformation(self.Fe3O4) parser = CifParser(os.path.join(test_dir, 'Li8Fe2NiCoO8.cif')) self.Li8Fe2NiCoO8 = parser.get_structures()[0] self.Li8Fe2NiCoO8.remove_oxidation_states() warnings.simplefilter("ignore")
def get_primitive(datapath, writepath): s = CifParser(datapath, occupancy_tolerance=1).get_structures()[0] sprim = s.get_primitive_structure() sprim.to('cif', writepath)
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)
class MagCifTest(unittest.TestCase): def setUp(self): self.mcif = CifParser( os.path.join(test_dir, "magnetic.example.NiO.mcif")) self.mcif_ncl = CifParser( os.path.join(test_dir, "magnetic.ncl.example.GdB4.mcif")) self.mcif_incom = CifParser( os.path.join(test_dir, "magnetic.incommensurate.example.Cr.mcif")) self.mcif_disord = CifParser( os.path.join(test_dir, "magnetic.disordered.example.CuMnO2.mcif")) def test_mcif_detection(self): self.assertTrue(self.mcif.feature_flags["magcif"]) self.assertTrue(self.mcif_ncl.feature_flags["magcif"]) self.assertTrue(self.mcif_incom.feature_flags["magcif"]) self.assertTrue(self.mcif_disord.feature_flags["magcif"]) self.assertFalse(self.mcif.feature_flags["magcif_incommensurate"]) self.assertFalse(self.mcif_ncl.feature_flags["magcif_incommensurate"]) self.assertTrue(self.mcif_incom.feature_flags["magcif_incommensurate"]) self.assertFalse( self.mcif_disord.feature_flags["magcif_incommensurate"]) def test_get_structures(self): # incommensurate structures not currently supported self.assertRaises(NotImplementedError, self.mcif_incom.get_structures) # disordered magnetic structures not currently supported self.assertRaises(NotImplementedError, self.mcif_disord.get_structures) # taken from self.mcif_ncl, removing explicit magnetic symmops # so that MagneticSymmetryGroup() has to be invoked magcifstr = """ data_5yOhtAoR _space_group.magn_name_BNS "P 4/m' b' m' " _cell_length_a 7.1316 _cell_length_b 7.1316 _cell_length_c 4.0505 _cell_angle_alpha 90.00 _cell_angle_beta 90.00 _cell_angle_gamma 90.00 loop_ _atom_site_label _atom_site_type_symbol _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd1 Gd 0.31746 0.81746 0.00000 1 B1 B 0.00000 0.00000 0.20290 1 B2 B 0.17590 0.03800 0.50000 1 B3 B 0.08670 0.58670 0.50000 1 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""" s = self.mcif.get_structures(primitive=False)[0] self.assertEqual(s.formula, "Ni32 O32") self.assertTrue(Magmom.are_collinear(s.site_properties['magmom'])) # example with non-collinear spin s_ncl = self.mcif_ncl.get_structures(primitive=False)[0] s_ncl_from_msg = CifParser.from_string(magcifstr).get_structures( primitive=False)[0] self.assertEqual(s_ncl.formula, "Gd4 B16") self.assertFalse(Magmom.are_collinear(s_ncl.site_properties['magmom'])) self.assertTrue(s_ncl.matches(s_ncl_from_msg)) 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.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 """ 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.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 0.0 0.0 7.14177848998 Gd2 0.0 0.0 7.14177848998 Gd3 0.0 0.0 -7.14177848998 Gd4 0.0 0.0 -7.14177848998 """ self.assertEqual(cw.__str__(), cw_ref_string_magnitudes) def test_bibtex(self): ref_bibtex_string = """@article{Blanco:2006, author = {Blanco, J.A.}, title = {?}, journal = {PHYSICAL REVIEW B}, year = {2006}, volume = {73}, number = {?}, pages = {?--?}, doi = {10.1103/PhysRevB.73.212411} }""" self.assertEqual(self.mcif_ncl.get_bibtex_strings()[0], ref_bibtex_string)
class MagCifTest(PymatgenTest): def setUp(self): warnings.filterwarnings("ignore") self.mcif = CifParser(self.TEST_FILES_DIR / "magnetic.example.NiO.mcif") self.mcif_ncl = CifParser(self.TEST_FILES_DIR / "magnetic.ncl.example.GdB4.mcif") self.mcif_incom = CifParser(self.TEST_FILES_DIR / "magnetic.incommensurate.example.Cr.mcif") self.mcif_disord = CifParser(self.TEST_FILES_DIR / "magnetic.disordered.example.CuMnO2.mcif") self.mcif_ncl2 = CifParser(self.TEST_FILES_DIR / "Mn3Ge_IR2.mcif") def tearDown(self): warnings.simplefilter("default") def test_mcif_detection(self): self.assertTrue(self.mcif.feature_flags["magcif"]) self.assertTrue(self.mcif_ncl.feature_flags["magcif"]) self.assertTrue(self.mcif_incom.feature_flags["magcif"]) self.assertTrue(self.mcif_disord.feature_flags["magcif"]) self.assertFalse(self.mcif.feature_flags["magcif_incommensurate"]) self.assertFalse(self.mcif_ncl.feature_flags["magcif_incommensurate"]) self.assertTrue(self.mcif_incom.feature_flags["magcif_incommensurate"]) self.assertFalse( self.mcif_disord.feature_flags["magcif_incommensurate"]) def test_get_structures(self): # incommensurate structures not currently supported self.assertRaises(NotImplementedError, self.mcif_incom.get_structures) # disordered magnetic structures not currently supported self.assertRaises(NotImplementedError, self.mcif_disord.get_structures) # taken from self.mcif_ncl, removing explicit magnetic symmops # so that MagneticSymmetryGroup() has to be invoked magcifstr = """ data_5yOhtAoR _space_group.magn_name_BNS "P 4/m' b' m' " _cell_length_a 7.1316 _cell_length_b 7.1316 _cell_length_c 4.0505 _cell_angle_alpha 90.00 _cell_angle_beta 90.00 _cell_angle_gamma 90.00 loop_ _atom_site_label _atom_site_type_symbol _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy Gd1 Gd 0.31746 0.81746 0.00000 1 B1 B 0.00000 0.00000 0.20290 1 B2 B 0.17590 0.03800 0.50000 1 B3 B 0.08670 0.58670 0.50000 1 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""" s = self.mcif.get_structures(primitive=False)[0] self.assertEqual(s.formula, "Ni32 O32") self.assertTrue(Magmom.are_collinear(s.site_properties["magmom"])) # example with non-collinear spin s_ncl = self.mcif_ncl.get_structures(primitive=False)[0] s_ncl_from_msg = CifParser.from_string(magcifstr).get_structures( primitive=False)[0] self.assertEqual(s_ncl.formula, "Gd4 B16") self.assertFalse(Magmom.are_collinear(s_ncl.site_properties["magmom"])) self.assertTrue(s_ncl.matches(s_ncl_from_msg)) 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) @unittest.skipIf(pybtex is None, "pybtex not present") def test_bibtex(self): ref_bibtex_string = """@article{cifref0, author = "Blanco, J.A.", journal = "PHYSICAL REVIEW B", volume = "73", year = "2006", pages = "?--?" } """ self.assertEqual(self.mcif_ncl.get_bibtex_string(), ref_bibtex_string)
def test_CifParser(self): parser = CifParser(self.TEST_FILES_DIR / "LiFePO4.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Li4 Fe4 P4 O16", "Incorrectly parsed cif.") parser = CifParser(self.TEST_FILES_DIR / "V2O3.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "V4 O6") bibtex_str = """ @article{cifref0, author = "Andersson, G.", title = "Studies on vanadium oxides. I. Phase analysis", journal = "Acta Chemica Scandinavica (1-27,1973-42,1988)", volume = "8", year = "1954", pages = "1599--1606" } """ self.assertEqual(parser.get_bibtex_string().strip(), bibtex_str.strip()) parser = CifParser(self.TEST_FILES_DIR / "Li2O.cif") prim = parser.get_structures(True)[0] self.assertEqual(prim.formula, "Li2 O1") conv = parser.get_structures(False)[0] self.assertEqual(conv.formula, "Li8 O4") # test for disordered structures parser = CifParser(self.TEST_FILES_DIR / "Li10GeP2S12.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Li20.2 Ge2.06 P3.94 S24", "Incorrectly parsed cif.") cif_str = """#\#CIF1.1 ########################################################################## # Crystallographic Information Format file # Produced by PyCifRW module # # This is a CIF file. CIF has been adopted by the International # Union of Crystallography as the standard for data archiving and # transmission. # # For information on this file format, follow the CIF links at # http://www.iucr.org ########################################################################## data_FePO4 _symmetry_space_group_name_H-M 'P 1' _cell_length_a 10.4117668699 _cell_length_b 6.06717187997 _cell_length_c 4.75948953998 loop_ # sometimes this is in a loop (incorrectly) _cell_angle_alpha 91.0 _cell_angle_beta 92.0 _cell_angle_gamma 93.0 _chemical_name_systematic 'Generated by pymatgen' _symmetry_Int_Tables_number 1 _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' 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_attached_hydrogens _atom_site_B_iso_or_equiv _atom_site_occupancy Fe Fe1 1 0.218728 0.750000 0.474867 0 . 1 Fe JJ2 1 0.281272 0.250000 0.974867 0 . 1 # there's a typo here, parser should read the symbol from the # _atom_site_type_symbol Fe Fe3 1 0.718728 0.750000 0.025133 0 . 1 Fe Fe4 1 0.781272 0.250000 0.525133 0 . 1 P P5 1 0.094613 0.250000 0.418243 0 . 1 P P6 1 0.405387 0.750000 0.918243 0 . 1 P P7 1 0.594613 0.250000 0.081757 0 . 1 P P8 1 0.905387 0.750000 0.581757 0 . 1 O O9 1 0.043372 0.750000 0.707138 0 . 1 O O10 1 0.096642 0.250000 0.741320 0 . 1 O O11 1 0.165710 0.046072 0.285384 0 . 1 O O12 1 0.165710 0.453928 0.285384 0 . 1 O O13 1 0.334290 0.546072 0.785384 0 . 1 O O14 1 0.334290 0.953928 0.785384 0 . 1 O O15 1 0.403358 0.750000 0.241320 0 . 1 O O16 1 0.456628 0.250000 0.207138 0 . 1 O O17 1 0.543372 0.750000 0.792862 0 . 1 O O18 1 0.596642 0.250000 0.758680 0 . 1 O O19 1 0.665710 0.046072 0.214616 0 . 1 O O20 1 0.665710 0.453928 0.214616 0 . 1 O O21 1 0.834290 0.546072 0.714616 0 . 1 O O22 1 0.834290 0.953928 0.714616 0 . 1 O O23 1 0.903358 0.750000 0.258680 0 . 1 O O24 1 0.956628 0.250000 0.292862 0 . 1 """ parser = CifParser.from_string(cif_str) struct = parser.get_structures(primitive=False)[0] self.assertEqual(struct.formula, "Fe4 P4 O16") self.assertAlmostEqual(struct.lattice.a, 10.4117668699) self.assertAlmostEqual(struct.lattice.b, 6.06717187997) self.assertAlmostEqual(struct.lattice.c, 4.75948953998) self.assertAlmostEqual(struct.lattice.alpha, 91) self.assertAlmostEqual(struct.lattice.beta, 92) self.assertAlmostEqual(struct.lattice.gamma, 93) with warnings.catch_warnings(): warnings.simplefilter("ignore") parser = CifParser(self.TEST_FILES_DIR / "srycoo.cif") self.assertEqual(parser.get_structures()[0].formula, "Sr5.6 Y2.4 Co8 O21") # Test with a decimal Xyz. This should parse as two atoms in # conventional cell if it is correct, one if not. parser = CifParser(self.TEST_FILES_DIR / "Fe.cif") self.assertEqual(len(parser.get_structures(primitive=False)[0]), 2) self.assertFalse(parser.has_errors)
def from_string(data): # use archieml-python parse to import data rdct = RecursiveDict(archieml.loads(data)) rdct.rec_update() # post-process internal representation of file contents for key in list(rdct.keys()): is_general, root_key = normalize_root_level(key) if is_general: # make part of shared (meta-)data, i.e. nest under `general` at # the beginning of the MPFile if mp_level01_titles[0] not in rdct: rdct[mp_level01_titles[0]] = RecursiveDict() rdct.move_to_end(mp_level01_titles[0], last=False) # normalize identifier key (pop & insert) # using rec_update since we're looping over all entries # also: support data in bare tables (marked-up only by # root-level identifier) by nesting under 'data' value = rdct.pop(key) keys = [mp_level01_titles[0]] if is_general else [] keys.append(root_key) if isinstance(value, list): keys.append('table') rdct.rec_update(nest_dict(value, keys)) # reference to section to iterate or parse as CIF section = rdct[mp_level01_titles[0]][root_key] \ if is_general else rdct[root_key] # iterate to find CSV sections to parse # also parse propnet quantities if isinstance(section, dict): scope = [] for k, v in section.iterate(): level, key = k key = ''.join([replacements.get(c, c) for c in key]) level_reduction = bool(level < len(scope)) if level_reduction: del scope[level:] if v is None: scope.append(key) elif isinstance(v, list) and isinstance(v[0], dict): table = '' for row_dct in v: table = '\n'.join([table, row_dct['value']]) pd_obj = read_csv(table) d = nest_dict(pd_obj.to_dict(), scope + [key]) section.rec_update(d, overwrite=True) if not is_general and level == 0: section.insert_default_plot_options(pd_obj, key) elif Quantity is not None and isinstance(v, six.string_types) and ' ' in v: quantity = Quantity.from_key_value(key, v) d = nest_dict(quantity.as_dict(), scope + [key]) # TODO quantity.symbol.name section.rec_update(d, overwrite=True) # convert CIF strings into pymatgen structures if mp_level01_titles[3] in section: from pymatgen.io.cif import CifParser for name in section[mp_level01_titles[3]].keys(): cif = section[mp_level01_titles[3]].pop(name) parser = CifParser.from_string(cif) structure = parser.get_structures(primitive=False)[0] section[mp_level01_titles[3]].rec_update(nest_dict( structure.as_dict(), [name] )) return MPFile.from_dict(rdct)
def test_get_primitive_standard_structure(self): parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) prim = s.get_primitive_standard_structure() self.assertAlmostEqual(prim.lattice.alpha, 109.47122063400001) self.assertAlmostEqual(prim.lattice.beta, 109.47122063400001) self.assertAlmostEqual(prim.lattice.gamma, 109.47122063400001) self.assertAlmostEqual(prim.lattice.a, 7.9657251015812145) self.assertAlmostEqual(prim.lattice.b, 7.9657251015812145) self.assertAlmostEqual(prim.lattice.c, 7.9657251015812145) parser = CifParser(os.path.join(test_dir, 'btet_1915.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) prim = s.get_primitive_standard_structure() self.assertAlmostEqual(prim.lattice.alpha, 105.015053349) self.assertAlmostEqual(prim.lattice.beta, 105.015053349) self.assertAlmostEqual(prim.lattice.gamma, 118.80658411899999) self.assertAlmostEqual(prim.lattice.a, 4.1579321075608791) self.assertAlmostEqual(prim.lattice.b, 4.1579321075608791) self.assertAlmostEqual(prim.lattice.c, 4.1579321075608791) parser = CifParser(os.path.join(test_dir, 'orci_1010.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) prim = s.get_primitive_standard_structure() self.assertAlmostEqual(prim.lattice.alpha, 134.78923546600001) self.assertAlmostEqual(prim.lattice.beta, 105.856239333) self.assertAlmostEqual(prim.lattice.gamma, 91.276341676000001) self.assertAlmostEqual(prim.lattice.a, 3.8428217771014852) self.assertAlmostEqual(prim.lattice.b, 3.8428217771014852) self.assertAlmostEqual(prim.lattice.c, 3.8428217771014852) parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) prim = s.get_primitive_standard_structure() self.assertAlmostEqual(prim.lattice.alpha, 90) self.assertAlmostEqual(prim.lattice.beta, 90) self.assertAlmostEqual(prim.lattice.gamma, 164.985257335) self.assertAlmostEqual(prim.lattice.a, 15.854897098324196) self.assertAlmostEqual(prim.lattice.b, 15.854897098324196) self.assertAlmostEqual(prim.lattice.c, 3.99648651) parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) prim = s.get_primitive_standard_structure() self.assertAlmostEqual(prim.lattice.alpha, 63.579155761999999) self.assertAlmostEqual(prim.lattice.beta, 116.42084423747779) self.assertAlmostEqual(prim.lattice.gamma, 148.47965136208569) self.assertAlmostEqual(prim.lattice.a, 7.2908007159612325) self.assertAlmostEqual(prim.lattice.b, 7.2908007159612325) self.assertAlmostEqual(prim.lattice.c, 6.8743926325200002) parser = CifParser(os.path.join(test_dir, 'hex_1170.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) prim = s.get_primitive_standard_structure() self.assertAlmostEqual(prim.lattice.alpha, 90) self.assertAlmostEqual(prim.lattice.beta, 90) self.assertAlmostEqual(prim.lattice.gamma, 120) self.assertAlmostEqual(prim.lattice.a, 3.699919902005897) self.assertAlmostEqual(prim.lattice.b, 3.699919902005897) self.assertAlmostEqual(prim.lattice.c, 6.9779585500000003) parser = CifParser(os.path.join(test_dir, 'rhomb_3478_conv.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) prim = s.get_primitive_standard_structure() self.assertAlmostEqual(prim.lattice.alpha, 28.049186140546812) self.assertAlmostEqual(prim.lattice.beta, 28.049186140546812) self.assertAlmostEqual(prim.lattice.gamma, 28.049186140546812) self.assertAlmostEqual(prim.lattice.a, 5.9352627428399982) self.assertAlmostEqual(prim.lattice.b, 5.9352627428399982) self.assertAlmostEqual(prim.lattice.c, 5.9352627428399982)
fws = [] connections = {} # add the root FW (GGA+U) spec = _snl_to_spec(snl, enforce_gga=False) tasks = [VaspWriterTask(), get_custodian_task(spec)] fws.append(Firework(tasks, spec, fw_id=1)) # add GGA insertion to DB spec = {'task_type': 'VASP db insertion', '_priority': 2, '_category': 'VASP', '_queueadapter': QA_VASP} fws.append(Firework([VaspToDBTask()], spec, fw_id=2)) connections[1] = 2 mpvis = MPVaspInputSet() spec['vaspinputset_name'] = mpvis.__class__.__name__ return Workflow(fws, connections, name=Composition(snl.structure.composition.reduced_formula).alphabetical_formula) """ if __name__ == '__main__': s1 = CifParser('test_wfs/Si.cif').get_structures()[0] s2 = CifParser('test_wfs/FeO.cif').get_structures()[0] snl1 = StructureNL(s1, "Anubhav Jain <*****@*****.**>") snl2 = StructureNL(s2, "Anubhav Jain <*****@*****.**>") snl_to_wf(snl1).to_file('test_wfs/wf_si_dupes.json', indent=4) snl_to_wf(snl2).to_file('test_wfs/wf_feo_dupes.json', indent=4)
def __init__(self): self.CIFDIR = "cifdir/" self.key = input.APIKEY # Import API key from input self.MaterialID = input.MATERIALID # Set class variable MaterialID from input self.seedname = str( input.SEEDNAME) # set class variable SEEDNAME from input file self.Ecut = input.ECUT #Class variable; in Ryberg, transfer from input file self.kpts = input.KMESH ### KPTS from input file for a generator, class variable self.SEEDDIR = "OUTPUT/" + 'VSP-' + self.seedname + '/' #set the seed directory self.pseudodir = "ABINIT/ABINITPP/ATOMICDATA/" # Set the directory for pseudopotentials self.EMAIL = input.EMAIL #Class variable; set email for SLURM from input file self.NCORE = input.ncore #Class Variable; number of cores, taken from input file self.SOC = input.SOC self.NBND = input.NUMBANDS # MAKE DIRECTORIES if not os.path.exists(self.SEEDDIR): os.makedirs(self.SEEDDIR) if not os.path.exists(self.SEEDDIR + "PP"): os.makedirs(self.SEEDDIR + "PP") if not os.path.exists(self.SEEDDIR + "WT"): os.makedirs(self.SEEDDIR + "WT") if not os.path.exists(self.SEEDDIR + 'PBE'): os.makedirs(self.SEEDDIR + "PBE") if not os.path.exists(self.SEEDDIR + "HSE06"): os.makedirs(self.SEEDDIR + "HSE06") if not os.path.exists(self.SEEDDIR + "W90"): os.makedirs(self.SEEDDIR + "W90") #import structure from PYMATGEN with matproj.MPRester(self.key) as m: struct = m.get_structure_by_material_id( self.MaterialID, final=True, conventional_unit_cell=False ) # GET STRUCT FROM MATERIALS PROJECT self.struct = m.get_structure_by_material_id( self.MaterialID, final=True, conventional_unit_cell=False ) # GET STRUCT FROM MATERIALS PROJECT C = Composition(str(struct.formula)) ########## MAKE A CIF FILE ### cif = CifWriter(struct) # Start generator cif.write_file(self.CIFDIR + self.seedname + ".cif") #write cif file to directory ciffile = self.CIFDIR + self.seedname + ".cif" # define ciffile cif = open(ciffile) # open cif file parser = CifParser(ciffile) #Start Parser ####### PARSE VARIABLES FROM CIF ########## chk_a = "_cell_length_a" chk_b = "_cell_length_b" chk_c = "_cell_length_c" chk_alpha = "_cell_angle_alpha" chk_beta = "_cell_angle_beta" chk_gamma = "_cell_angle_gamma" chk_name = "_chemical_formula_structural" for x in cif: if chk_a in x: self.a = x.replace(chk_a, '').replace('\n', '') if chk_b in x: self.b = x.replace(chk_b, '').replace('\n', '') if chk_c in x: self.c = x.replace(chk_c, '').replace('\n', '') if chk_alpha in x: self.alpha = x.replace(chk_alpha, '').replace('\n', '') if chk_beta in x: self.beta = x.replace(chk_beta, '').replace('\n', '') if chk_gamma in x: self.gamma = x.replace(chk_gamma, '').replace('\n', '') #if chk_name in x: # seedname = x.replace(chk_name, '') # seedname = seedname.replace('\n', '').translate( # {ord(i): None for i in ' '}) self.UNIQUE_ATOMS = np.unique(struct.species) self.cord = struct.frac_coords self.ntypat = np.unique(struct.atomic_numbers).size self.natom = np.array(struct.atomic_numbers).size self.atomnum = np.unique(struct.atomic_numbers)[::1] self.typat = "" for x in struct.atomic_numbers: for at in self.atomnum: if at == x: self.typat += ''.join( map(str, np.where(self.atomnum == at)[0] + 1)) + " " # SOC CASE # SOC CASE self.SOC = input.SOC self.noncolin = '.FALSE.' self.lspinorb = '.FALSE.' if input.SOC: self.noncolin = '.TRUE.' self.lspinorb = '.TRUE.' num_bands = input.NUMBANDS num_wann = num_bands - (num_bands % 2) # FORCE EVEN self.wan = num_wann if self.SOC: self.WTwan = self.wan / 2 num_bands = 0 for x in struct.species: PP = gb.glob(self.pseudodir + str(x) + ".*") readpp = minidom.parse(''.join(map(str, PP))) items = readpp.getElementsByTagName('atom') num_bands += float(items[0].attributes['valence'].value) num_wann = num_bands - (num_bands % 2) # FORCE EVEN
def test_CifParserSpringerPauling(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") # Below are 10 tests for CIFs from the Springer Materials/Pauling file DBs. # Partial occupancy on sites, incorrect label, previously unparsable parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1928405.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Er1 Mn3.888 Fe2.112 Sn6") self.assertTrue(parser.has_errors) # Partial occupancy on sites, previously parsed as an ordered structure parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1011081.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Zr0.2 Nb0.8") self.assertTrue(parser.has_errors) # Partial occupancy on sites, incorrect label, previously unparsable parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1615854.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Na2 Al2 Si6 O16") self.assertTrue(parser.has_errors) # Partial occupancy on sites, incorrect label, previously unparsable parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1622133.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Ca0.184 Mg13.016 Fe2.8 Si16 O48") self.assertTrue(parser.has_errors) # Partial occupancy on sites, previously parsed as an ordered structure parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1908491.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Mn0.48 Zn0.52 Ga2 Se4") self.assertTrue(parser.has_errors) # Partial occupancy on sites, incorrect label, previously unparsable parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1811457.cif") for s in parser.get_structures(True): self.assertEqual(s.formula, "Ba2 Mg0.6 Zr0.2 Ta1.2 O6") self.assertTrue(parser.has_errors) # Incomplete powder diffraction data, previously unparsable # This CIF file contains the molecular species "NH3" which is # parsed as "N" because the label is "N{x}" (x = 1,2,..) and the # corresponding symbol is "NH3". Since, the label and symbol are switched # in CIFs from Springer Materials/Pauling file DBs, CifParser parses the # element as "Nh" (Nihonium). parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1002871.cif") self.assertEqual( parser.get_structures(True)[0].formula, "Cu1 Br2 Nh6") self.assertEqual( parser.get_structures(True)[1].formula, "Cu1 Br4 Nh6") self.assertTrue(parser.has_errors) # Incomplete powder diffraction data, previously unparsable parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1704003.cif") for s in parser.get_structures(): self.assertEqual(s.formula, "Rb4 Mn2 F12") self.assertTrue(parser.has_errors) # Unparsable species 'OH/OH2', previously parsed as "O" parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1500382.cif") for s in parser.get_structures(): self.assertEqual(s.formula, "Mg6 B2 O6 F1.764") self.assertTrue(parser.has_errors) # Unparsable species 'OH/OH2', previously parsed as "O" parser = CifParser(self.TEST_FILES_DIR / "PF_sd_1601634.cif") for s in parser.get_structures(): self.assertEqual(s.formula, "Zn1.29 Fe0.69 As2 Pb1.02 O8")
def test_dot_positions(self): f = self.TEST_FILES_DIR / "ICSD59959.cif" p = CifParser(f) s = p.get_structures()[0] self.assertEqual(s.formula, "K1 Mn1 F3")
def test_site_symbol_preference(self): parser = CifParser(self.TEST_FILES_DIR / "site_type_symbol_test.cif") self.assertEqual(parser.get_structures()[0].formula, "Ge0.4 Sb0.4 Te1")
def test_supercells(self): from pymatgen.io.cif import CifParser import numpy as np from supercellor.supercell import make_supercell EPS = 1e-6 def get_shortest_distance(system): nat = len(system.sites) shortest_distance = np.inf for i in range(nat): for j in range(i + 1, nat): d = system.get_distance(i, j) shortest_distance = min((d, shortest_distance)) return shortest_distance filenames = ('data/Al-fcc.cif', ) for fname in filenames: parser = CifParser(fname) structure = parser.get_structures()[0] shortestd_unit = get_shortest_distance(2 * structure) for method in ( 'bec', 'hnf', ): for wrap in (False, True): for standardize in (False, True): for do_niggli in (False, True): for D in np.arange(5.0, 15.1, 5.0): for implementation in ('fort', 'pyth'): if D >= 10 and implementation == 'pyth': continue S1, sm = make_supercell( structure, distance=D, method=method, verbosity=0, implementation='fort', wrap=wrap, standardize=standardize, do_niggli_first=do_niggli) S2 = structure * sm shortestd_super = get_shortest_distance(S1) # print method, wrap, standardize, do_niggli, D, implementation, shortestd_super, shortestd_unit # Checking that atoms are not moved closer together, for any reasons self.assertTrue( abs(shortestd_super - shortestd_unit) < EPS) if not standardize: angl1 = np.array(S1._lattice.angles) angl2 = np.array(S2._lattice.angles) angl1.sort() # sort in place angl2.sort() # checking angles are the same self.assertTrue( np.sum((angl1 - angl2)**2) < EPS) if not (standardize or do_niggli): # check consistency between scaling matrix and lattice vecs: self.assertTrue( np.sum(( S1._lattice.matrix - S2._lattice.matrix)**2) < 1e-6)
def cif_structure(self, file_name): parser = CifParser(file_name) structure = parser.get_structures()[0] # parse.close() return structure
def test_get_conventional_standard_structure(self): parser = CifParser(os.path.join(test_dir, 'bcc_1927.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 9.1980270633769461) self.assertAlmostEqual(conv.lattice.b, 9.1980270633769461) self.assertAlmostEqual(conv.lattice.c, 9.1980270633769461) parser = CifParser(os.path.join(test_dir, 'btet_1915.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 5.0615106678044235) self.assertAlmostEqual(conv.lattice.b, 5.0615106678044235) self.assertAlmostEqual(conv.lattice.c, 4.2327080177761687) parser = CifParser(os.path.join(test_dir, 'orci_1010.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 2.9542233922299999) self.assertAlmostEqual(conv.lattice.b, 4.6330325651443296) self.assertAlmostEqual(conv.lattice.c, 5.373703587040775) parser = CifParser(os.path.join(test_dir, 'orcc_1003.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 4.1430033493799998) self.assertAlmostEqual(conv.lattice.b, 31.437979757624728) self.assertAlmostEqual(conv.lattice.c, 3.99648651) parser = CifParser(os.path.join(test_dir, 'monoc_1028.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 117.53832420192903) self.assertAlmostEqual(conv.lattice.gamma, 90) self.assertAlmostEqual(conv.lattice.a, 14.033435583000625) self.assertAlmostEqual(conv.lattice.b, 3.96052850731) self.assertAlmostEqual(conv.lattice.c, 6.8743926325200002) parser = CifParser(os.path.join(test_dir, 'hex_1170.cif')) structure = parser.get_structures(False)[0] s = SpacegroupAnalyzer(structure, symprec=1e-2) conv = s.get_conventional_standard_structure() self.assertAlmostEqual(conv.lattice.alpha, 90) self.assertAlmostEqual(conv.lattice.beta, 90) self.assertAlmostEqual(conv.lattice.gamma, 120) self.assertAlmostEqual(conv.lattice.a, 3.699919902005897) self.assertAlmostEqual(conv.lattice.b, 3.699919902005897) self.assertAlmostEqual(conv.lattice.c, 6.9779585500000003)
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.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.61000000 _cell_length_b 4.61000000 _cell_length_c 4.61000000 _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 97.972181 _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.0 O2- O2 4 0.000000 0.000000 0.000000 1.0""" for l1, l2 in zip(str(writer).split("\n"), ans.split("\n")): self.assertEqual(l1.strip(), l2.strip())
def get_kpts(screener,cif_file,level): """ Obtain the number of kpoints Args: screener (class): pymofscreen.screener class cif_file (string): name of CIF file level (string): accuracy level Returns: kpts (list of ints): kpoint grid gamma (bool): True for gamma-centered """ niggli = screener.niggli mofpath = screener.mofpath kpts_path = screener.kpts_path kppas = screener.kppas kpts = None if not mofpath: mofpath = '' if kpts_path == 'Auto' and has_pm: if level == 'low': kppa = kppas[0] elif level == 'high': kppa = kppas[1] else: raise ValueError('kpoints accuracy level not defined') filepath = os.path.join(mofpath,cif_file) if '.cif' in cif_file: parser = CifParser(filepath) pm_mof = parser.get_structures(primitive=niggli)[0] elif 'OUTCAR' in cif_file: mof_temp = read(filepath) write('pm_temp.cif',mof_temp) parser = CifParser('pm_temp.cif') pm_mof = parser.get_structures(primitive=niggli)[0] os.remove('pm_temp.cif') else: pm_mof = pm.Structure.from_file(filepath,primitive=niggli) pm_kpts = Kpoints.automatic_density(pm_mof,kppa) kpts = pm_kpts.kpts[0] if pm_kpts.style.name == 'Gamma': gamma = True else: gamma = False elif kpts_path == 'Auto' and not has_pm: raise ValueError('Pymatgen not installed. Please provide a kpts file.') elif niggli and not has_pm: raise ValueError('Pymatgen not installed: set niggli=False') else: old_cif_name = cif_file.split('.cif')[0].split('_')[0] infile = open(kpts_path,'r') lines = infile.read().splitlines() infile.close() for i in range(len(lines)): if old_cif_name in lines[i]: if level == 'low': kpts = lines[i+1] gamma = lines[i+2] elif level == 'high': kpts = lines[i+3] gamma = lines[i+4] else: raise ValueError('Incompatible KPPA with prior runs') break kpts = np.squeeze(np.asarray(np.matrix(kpts))).tolist() if not kpts or len(kpts) != 3: raise ValueError('Error parsing k-points for '+cif_file) if gamma == 'True': gamma = True elif gamma == 'False': gamma = False else: raise ValueError('Error parsing gamma for '+cif_file) return kpts, gamma
class RecalculateHSEFileWriter(FileWriter): """ recalculate with HSE """ def generate_structure(self, primitive=True): return self.struc def write_vasp_files(self): mpset = MPHSERelaxSet(self.out_struc, user_incar_settings={'EDIFF': 1e-5, 'EDIFFG': -0.01, 'ALGO': 'F', 'ISMEAR': 0}, \ user_kpoints_settings={'reciprocal_density': 250}) mpset.write_input(self.wd) if __name__ == '__main__': # poscar_input = "/Users/yao/Google Drive/data/lattice_energy_testset/mp-22862_NaCl/POSCAR" # wd = "/Users/yao/Google Drive/data/lattice_energy_testset/mp-22862_NaCl_recal" # poscar_input = "/Users/yao/Google Drive/data/lattice_energy_testset/mp-22865_CsCl/POSCAR" # wd = "/Users/yao/Google Drive/data/lattice_energy_testset/mp-22865_CsCl_recal" # poscar_input = "/Users/yao/Google Drive/data/phonopy/NaCl/NaCl-vasp-dfpt-exercise/POSCAR" # wd = "/Users/yao/Google Drive/data/phonopy/NaCl/NaCl-vasp-dfpt-exercise" # struc = Poscar.from_file(poscar_input).structure cif_input = "/Users/yao/Google Drive/data/2116/solidsolution/structures_exp_guess/inorganic/EntryWithCollCode30657_Cs2AgCl3.cif" wd = "/Users/yao/Google Drive/data/2116/solidsolution/structures_exp_guess/inorganic/Cs2AgCl3" struc = CifParser(cif_input).get_structures()[0] filewriter = RecalculateMPFileWriter(struc, wd) filewriter.write_vasp_files()
def sol(self, EB_K_2, miller_index_2, min_slab_size_2=8.0, min_vacuum_size_2=15): from pymatgen.analysis.adsorption import AdsorbateSiteFinder, plot_slab, reorient_z from pymatgen.core.surface import Slab, SlabGenerator, generate_all_slabs, Structure, Lattice, ReconstructionGenerator from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from pymatgen.core.structure import Structure from pymatgen.io.cif import CifParser from matplotlib import pyplot as plt from pymatgen.io.vasp.inputs import Poscar from pymatgen.io.vasp.sets import MVLSlabSet import shutil import os ##mpr = MPRester()#密钥#密钥 ass = self.cif_route print(ass) # os.chdir(r"E:\VASP practical\Input") # print (os.getcwd()) # Note that you must provide your own API Key, which can # be accessed via the Dashboard at materialsproject.org #mpr = MPRester()#密钥 struct = CifParser(ass) structure = struct.get_structures()[0] print(structure) os.chdir(r"E:\VASP practical\Input") print(os.getcwd()) structure = SpacegroupAnalyzer( structure).get_conventional_standard_structure() #空间群分析 need_miller_index = miller_index_2 #通过米勒指数,确定要切的晶面 slab = SlabGenerator(struct, miller_index=need_miller_index, min_slab_size=min_slab_size_2,\ min_vacuum_size=min_vacuum_size_2, center_slab=True) #晶面生成器参数 for n, slabs in enumerate(slab.get_slabs()): slabs_bak = slabs.copy() #可能的晶面 slabs.make_supercell(self.supercell) #晶胞扩充 A = Poscar(slabs) #将切面转换为Poscar relax = A.structure #将Poscar 转换为结构信息 custom_settings = {"NPAR": 4} # 用户的INCAR 设置 relax = MVLSlabSet(relax, user_incar_settings=custom_settings) #Vasp输入文件生成器 fig = plt.figure() #绘图--确立画布 ax = fig.add_subplot(111) #绘图--确立位置 plot_slab(slabs, ax, adsorption_sites=False) #绘图 dire = str(ass) + "---" + "sol" + str(EB_K_2) + str( need_miller_index) + '----' + str(n) #设置一个用作存储输入文件的名称 plt.savefig(dire) #将该名称用于保存图片 relax.write_input(dire) #将生成的VASP输入文件写入存储 os.chdir("./" + dire) #定义一个更改当前目录的变量 dire2 = './vaspstd_sub' #确立脚本名称 shutil.copy(r"C:\Users\41958\.spyder-py3\vaspstd_sub", dire2) #将脚本写入VASP输入文件所在文件夹 eb = str(EB_K_2) ls = str('TURE') with open('INCAR', 'a') as file_object: file_object.write('LSOL = ' + ls + '\n' + 'EB_K = ' + eb) # os.chdir("../") #将当前目录改为默认目录 os.chdir(r"D:\Desktop\VASP practical\workdir") print(os.getcwd()) print('finished')
] d = '/home/kenneth/proj/pro-min/minerals' bv_elem = [] bv_sum = [] bv_type = [] bvs = [] bv_name = [] bv_geo = [] for m in mins: print(m) mn, num = m.split('_') fi = os.path.join(d, mn + '_' + str(num) + '.cif') # print(fi) # exit() parser = CifParser(fi) structure = parser.get_structures(primitive=True)[0] els = [Element(el.symbol) for el in structure.composition.elements] if not set(els).issubset(set(BV_PARAMS.keys())): raise ValueError( "Structure contains elements not in set of BV parameters!") bv = pma.BVAnalyzer() # Perform symmetry determination and get sites grouped by symmetry. if bv.symm_tol: finder = SpacegroupAnalyzer(structure, bv.symm_tol) symm_structure = finder.get_symmetrized_structure() equi_sites = symm_structure.equivalent_sites else:
def absorbed(self, millerindex_1, absorbate_1, absorba, judge='', appendage=""): from pymatgen import Structure, Lattice, MPRester, Molecule import pymatgen.core.structure import pymatgen.core.sites from pymatgen.analysis.adsorption import AdsorbateSiteFinder, reorient_z, plot_slab from pymatgen.core.surface import generate_all_slabs from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from matplotlib import pyplot as plt from pymatgen.io.cif import CifParser from pymatgen.io.vasp.inputs import Poscar from pymatgen.io.vasp.sets import MVLSlabSet from pymatgen.io.cif import CifWriter import os import shutil ass = self.cif_route print(ass) # os.chdir(r"E:\VASP practical\Input") # print (os.getcwd()) # Note that you must provide your own API Key, which can # be accessed via the Dashboard at materialsproject.org #mpr = MPRester()#密钥 struct = CifParser(ass) structure = struct.get_structures()[0] print(structure) os.chdir(r"E:\VASP practical\Input") print(os.getcwd()) # fcc_ni = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.5), ["Ni", "Ni"], # [[0, 0, 0], [0.5, 0.5, 0.5]]) slabs = generate_all_slabs(structure, max_index=1, min_slab_size=8.0, min_vacuum_size=10.0) millerindex = millerindex_1 struct_111 = [ slab for slab in slabs if slab.miller_index == millerindex_1 ][0] asf_ni_111 = AdsorbateSiteFinder(struct_111) ads_sites = asf_ni_111.find_adsorption_sites() # print(ads_sites) assert len(ads_sites) == 4 fig = plt.figure() ax = fig.add_subplot(111) plot_slab(struct_111, ax, adsorption_sites=True) fig = plt.figure() ax = fig.add_subplot(111) adsorbate = Molecule(absorbate_1, absorba) ads_structs = asf_ni_111.generate_adsorption_structures( adsorbate, repeat=[1, 1, 1]) A = Poscar(reorient_z(ads_structs[0])) #将切面转换为Poscar open('POSCAR', 'w').write(str(A)) p = Poscar.from_file('POSCAR') # w = CifWriter(A.struct) # w.write_file('mystructure.cif') path = r'E:\VASP practical\Input\POSCAR' # 文件路径 if os.path.exists(path): # 如果文件存在 # 删除文件,可使用以下两种方法。 os.remove(path) #os.unlink(path) else: print('no such file:%s' % my_file) # 则返回文件不存在 # w = CifWriter(A.struct) # w.write_file('mystructure.cif') relax = p.structure #将Poscar 转换为结构信息 custom_settings = {"NPAR": 4} # 用户的INCAR 设置 relaxs = MVLSlabSet(relax, user_incar_settings=custom_settings) # Vasp输入文件生成器 dire = str(ass) + "---" + str(absorbate_1) + str(millerindex_1) # print (relax) relaxs.write_input(dire) os.chdir("./" + dire) print(os.getcwd()) #定义一个更改当前目录的变量 dire2 = './vaspstd_sub' #确立脚本名称 shutil.copy(r"C:\Users\41958\.spyder-py3\vaspstd_sub", dire2) eb = appendage #添加其他INCAR参数 with open('INCAR', 'r') as f1: lines = f1.readlines() with open('INCAR', 'w') as f2: for line in lines: if judge in line: continue f2.write(line) with open('INCAR', 'a') as f3: f3.write(eb) plot_slab(ads_structs[0], ax, adsorption_sites=False, decay=0.09) # open('POSCAR001', 'w').write(str(Poscar(reorient_z(ads_structs[0])))) os.chdir(r"D:\Desktop\VASP practical\workdir") print(os.getcwd()) print('finished') # my_lattace = Lattace('mp-698074')#半水石膏 # # my_lattace.phase_out()#生成晶胞优化的输入文件 # go = my_lattace.phase_sol(66,judge='LWAVE', appendage= '\nLWAVE = Ture') # print('yoo')
def setUp(self): parser = CifParser(os.path.join(test_dir, 'Fe.cif')) self.Fe = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'LiFePO4.cif')) self.LiFePO4 = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'Fe3O4.cif')) self.Fe3O4 = parser.get_structures()[0] parser = CifParser( os.path.join(test_dir, 'magnetic.ncl.example.GdB4.mcif')) self.GdB4 = parser.get_structures()[0] parser = CifParser(os.path.join(test_dir, 'magnetic.example.NiO.mcif')) self.NiO_expt = parser.get_structures()[0] latt = Lattice.cubic(4.17) species = ["Ni", "O"] coords = [[0, 0, 0], [0.5, 0.5, 0.5]] self.NiO = Structure.from_spacegroup(225, latt, species, coords) latt = Lattice([[2.085, 2.085, 0.0], [0.0, -2.085, -2.085], [-2.085, 2.085, -4.17]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0, 0.5], [0, 0, 0], [0.25, 0.5, 0.25], [0.75, 0.5, 0.75]] self.NiO_AFM_111 = Structure(latt, species, coords, site_properties={'magmom': [-5, 5, 0, 0]}) latt = Lattice([[2.085, 2.085, 0], [0, 0, -4.17], [-2.085, 2.085, 0]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0.5, 0.5], [0, 0, 0], [0, 0.5, 0], [0.5, 0, 0.5]] self.NiO_AFM_001 = Structure(latt, species, coords, site_properties={'magmom': [-5, 5, 0, 0]}) latt = Lattice([[2.085, 2.085, 0], [0, 0, -4.17], [-2.085, 2.085, 0]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0.5, 0.5], [0, 0, 0], [0, 0.5, 0], [0.5, 0, 0.5]] self.NiO_AFM_001_opposite = Structure( latt, species, coords, site_properties={'magmom': [5, -5, 0, 0]}) latt = Lattice([[2.085, 2.085, 0], [0, 0, -4.17], [-2.085, 2.085, 0]]) species = ["Ni", "Ni", "O", "O"] coords = [[0.5, 0.5, 0.5], [0, 0, 0], [0, 0.5, 0], [0.5, 0, 0.5]] self.NiO_unphysical = Structure( latt, species, coords, site_properties={'magmom': [-3, 0, 0, 0]}) warnings.simplefilter("ignore")
def test_dot_positions(self): f = os.path.join(test_dir, "ICSD59959.cif") p = CifParser(f) s = p.get_structures()[0] self.assertEqual(s.formula, "K1 Mn1 F3")
def test_parse_symbol(self): """ Test the _parse_symbol function with several potentially problematic examples of symbols and labels. """ test_cases = { "MgT": "Mg", "MgT1": "Mg", "H(46A)": "H", "O(M)": "O", "N(Am)": "N", "H1N2a": "H", "CO(1)": "Co", "Wat1": "O", "MgM2A": "Mg", "CaX": "Ca", "X1": "X", "X": "X", "OA1": "O", "NaA2": "Na", "O-H2": "O", "OD2": "O", "OW": "O", "SiT": "Si", "SiTet": "Si", "Na-Int": "Na", "CaD1": "Ca", "KAm": "K", "D+1": "D", "D": "D", "D1-": "D", "D4": "D", "D0": "D", "NH": "Nh", "NH2": "Nh", "NH3": "Nh", "SH": "S", } for e in Element: name = e.name test_cases[name] = name if len(name) == 2: test_cases[name.upper()] = name test_cases[name.upper() + str(1)] = name test_cases[name.upper() + "A"] = name test_cases[name + str(1)] = name test_cases[name + str(2)] = name test_cases[name + str(3)] = name test_cases[name + str(1) + "A"] = name special = { "Hw": "H", "Ow": "O", "Wat": "O", "wat": "O", "OH": "", "OH2": "" } test_cases.update(special) with warnings.catch_warnings(): warnings.simplefilter("ignore") parser = CifParser(self.TEST_FILES_DIR / "LiFePO4.cif") for sym, expected_symbol in test_cases.items(): self.assertEqual(parser._parse_symbol(sym), expected_symbol)
def test_site_symbol_preference(self): parser = CifParser(os.path.join(test_dir, 'site_type_symbol_test.cif')) self.assertEqual(parser.get_structures()[0].formula, "Ge0.4 Sb0.4 Te1")
db = client[DB] group = Group.get_from_string('%s_cif_raw' % COLLECTION) logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.DEBUG, filename='%s.log' % COLLECTION) logging.info('Creating collection %s', COLLECTION) collection = db[COLLECTION] documents = [] for cif in group.nodes: path, structures, source, structure, document = [None] * 5 path = cif.get_file_abs_path() try: structures = CifParser(path).get_structures(primitive=False) except Exception as exception: logging.error('%s', str(exception)) else: source = cif.get_attr('source') for structure in structures: document = { 'source': source, 'structure': structure.as_dict() } documents.append(document) if not (len(documents) % (N / 10)): logging.info('%d documents collected', len(documents)) if len(documents) == N: logging.info('Inserting %d documents into %s', len(documents), COLLECTION)
def test_empty_deque(self): s = """data_1526655 _journal_name_full _space_group_IT_number 227 _symmetry_space_group_name_Hall 'F 4d 2 3 -1d' _symmetry_space_group_name_H-M 'F d -3 m :1' _cell_angle_alpha 90 _cell_angle_beta 90 _cell_angle_gamma 90 _cell_formula_units_Z 8 _cell_length_a 5.381 _cell_length_b 5.381 _cell_length_c 5.381 _cell_volume 155.808 loop_ _atom_site_label _atom_site_type_symbol _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy _atom_site_U_iso_or_equiv Si1 Si 0 0 0 1 0.0 _iucr_refine_fcf_details ; data_symmetries loop_ _space_group_symop_id _space_group_symop_operation_xyz 1 x,y,z 2 -x+1/2,y+1/2,-z+1/2 3 -x,-y,-z 4 x-1/2,-y-1/2,z-1/2 ;""" p = CifParser.from_string(s) self.assertEqual(p.get_structures()[0].formula, "Si1") cif = """ data_1526655 _journal_name_full _space_group_IT_number 227 _symmetry_space_group_name_Hall 'F 4d 2 3 -1d' _symmetry_space_group_name_H-M 'F d -3 m :1' _cell_angle_alpha 90 _cell_angle_beta 90 _cell_angle_gamma 90 _cell_formula_units_Z 8 _cell_length_a 5.381 _cell_length_b 5.381 _cell_length_c 5.381 _cell_volume 155.808 _iucr_refine_fcf_details ; data_symmetries Some arbitrary multiline string ; loop_ _atom_site_label _atom_site_type_symbol _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z _atom_site_occupancy _atom_site_U_iso_or_equiv Si1 Si 0 0 0 1 0.0 """ p = CifParser.from_string(cif) self.assertRaises(ValueError, p.get_structures)
def compute_environments(chemenv_configuration): string_sources = { 'cif': { 'string': 'a Cif file', 'regexp': r'.*\.cif$' }, 'mp': { 'string': 'the Materials Project database', 'regexp': r'mp-[0-9]+$' } } questions = {'c': 'cif'} questions['m'] = 'mp' lgf = LocalGeometryFinder() lgf.setup_parameters() allcg = AllCoordinationGeometries() strategy_class = strategies_class_lookup[ chemenv_configuration.package_options['default_strategy']['strategy']] # TODO: Add the possibility to change the parameters and save them in the chemenv_configuration default_strategy = strategy_class() default_strategy.setup_options( chemenv_configuration.package_options['default_strategy'] ['strategy_options']) max_dist_factor = chemenv_configuration.package_options[ 'default_max_distance_factor'] firsttime = True while True: if len(questions) > 1: found = False print( 'Enter the source from which the structure is coming or <q> to quit :' ) for key_character, qq in questions.items(): print(' - <{}> for a structure from {}'.format( key_character, string_sources[qq]['string'])) test = input(' ... ') if test == 'q': break if test not in list(questions.keys()): for key_character, qq in questions.items(): if re.match(string_sources[qq]['regexp'], str(test)) is not None: found = True source_type = qq if not found: print('Wrong key, try again ...') continue else: source_type = questions[test] else: found = False source_type = list(questions.values())[0] if found and len(questions) > 1: input_source = test if source_type == 'cif': if not found: input_source = input('Enter path to cif file : ') cp = CifParser(input_source) structure = cp.get_structures()[0] elif source_type == 'mp': if not found: input_source = input( 'Enter materials project id (e.g. "mp-1902") : ') a = MPRester() structure = a.get_structure_by_material_id(input_source) lgf.setup_structure(structure) print('Computing environments for {} ... '.format( structure.composition.reduced_formula)) se = lgf.compute_structure_environments( maximum_distance_factor=max_dist_factor) print('Computing environments finished') while True: test = input( 'See list of environments determined for each (unequivalent) site ? ' '("y" or "n", "d" with details, "g" to see the grid) : ') strategy = default_strategy if test in ['y', 'd', 'g']: strategy.set_structure_environments(se) for eqslist in se.equivalent_sites: site = eqslist[0] isite = se.structure.index(site) try: if strategy.uniquely_determines_coordination_environments: ces = strategy.get_site_coordination_environments( site) else: ces = strategy.get_site_coordination_environments_fractions( site) except NeighborsNotComputedChemenvError: continue if ces is None: continue if len(ces) == 0: continue comp = site.species # ce = strategy.get_site_coordination_environment(site) if strategy.uniquely_determines_coordination_environments: ce = ces[0] if ce is None: continue thecg = allcg.get_geometry_from_mp_symbol(ce[0]) mystring = 'Environment for site #{} {} ({}) : {} ({})\n'.format( str(isite), comp.get_reduced_formula_and_factor()[0], str(comp), thecg.name, ce[0]) else: mystring = 'Environments for site #{} {} ({}) : \n'.format( str(isite), comp.get_reduced_formula_and_factor()[0], str(comp)) for ce in ces: cg = allcg.get_geometry_from_mp_symbol(ce[0]) csm = ce[1]['other_symmetry_measures'][ 'csm_wcs_ctwcc'] mystring += ' - {} ({}): {:.2f} % (csm : {:2f})\n'.format( cg.name, cg.mp_symbol, 100.0 * ce[2], csm) if test in [ 'd', 'g' ] and strategy.uniquely_determines_coordination_environments: if thecg.mp_symbol != UNCLEAR_ENVIRONMENT_SYMBOL: mystring += ' <Continuous symmetry measures> ' mingeoms = se.ce_list[isite][ thecg. coordination_number][0].minimum_geometries() for mingeom in mingeoms: csm = mingeom[1]['other_symmetry_measures'][ 'csm_wcs_ctwcc'] mystring += '{} : {:.2f} '.format( mingeom[0], csm) print(mystring) if test == 'g': while True: test = input( 'Enter index of site(s) (e.g. 0 1 2, separated by spaces) for which you want to see the grid ' 'of parameters : ') try: indices = [int(x) for x in test.split()] print(str(indices)) for isite in indices: if isite < 0: raise IndexError se.plot_environments( isite, additional_condition=se.AC.ONLY_ACB) break except ValueError: print('This is not a valid site') except IndexError: print('This site is out of the site range') if no_vis: test = input('Go to next structure ? ("y" to do so)') if test == 'y': break continue test = input( 'View structure with environments ? ("y" for the unit cell or "m" for a supercell or "n") : ' ) if test in ['y', 'm']: if test == 'm': mydeltas = [] while True: try: test = input('Enter multiplicity (e.g. 3 2 2) : ') nns = test.split() for i0 in range(int(nns[0])): for i1 in range(int(nns[1])): for i2 in range(int(nns[2])): mydeltas.append( np.array( [1.0 * i0, 1.0 * i1, 1.0 * i2], np.float)) break except (ValueError, IndexError): print('Not a valid multiplicity') else: mydeltas = [np.zeros(3, np.float)] if firsttime: vis = StructureVis(show_polyhedron=False, show_unit_cell=True) vis.show_help = False firsttime = False vis.set_structure(se.structure) strategy.set_structure_environments(se) for isite, site in enumerate(se.structure): try: ces = strategy.get_site_coordination_environments(site) except NeighborsNotComputedChemenvError: continue if len(ces) == 0: continue ce = strategy.get_site_coordination_environment(site) if ce is not None and ce[0] != UNCLEAR_ENVIRONMENT_SYMBOL: for mydelta in mydeltas: psite = PeriodicSite(site.species, site.frac_coords + mydelta, site.lattice, properties=site.properties) vis.add_site(psite) neighbors = strategy.get_site_neighbors(psite) draw_cg(vis, psite, neighbors, cg=lgf.allcg.get_geometry_from_mp_symbol( ce[0]), perm=ce[1]['permutation']) vis.show() test = input('Go to next structure ? ("y" to do so) : ') if test == 'y': break print('')
def setUpClass(cls): r = CifParser(os.path.join(test_dir, "CoO19128.cif")) cls.structure = r.get_structures()[0] cls.atoms = Atoms(cls.structure, "O", 10.0)
from pymatgen.io.cif import CifParser __author__ = "Yue-Wen FANG" __maintainer__ = "Yue-Wen FANG" __email__ = "*****@*****.**" __status__ = "Development" __creation_date__ = "Nov. 1, 2018" """ This script converts the cif to vasp Note that the output POSCAR will overwirte the former POSCAR. """ filename = input('input the cif file: ') structure_parser = CifParser(filename) print(structure_parser) structure = structure_parser.get_structures() print(structure) structure[0].to(filename='POSCAR')