def run_task(self, fw_spec): from pymatgen.analysis.eos import EOS tag = self["tag"] db_file = env_chk(self.get("db_file"), fw_spec) summary_dict = {"eos": self["eos"]} mmdb = MMVaspDb.from_db_file(db_file, admin=True) # get the optimized structure d = mmdb.collection.find_one({"task_label": "{} structure optimization".format(tag)}) structure = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) summary_dict["structure"] = structure.as_dict() # get the data(energy, volume, force constant) from the deformation runs docs = mmdb.collection.find({"task_label": {"$regex": "{} bulk_modulus*".format(tag)}, "formula_pretty": structure.composition.reduced_formula}) energies = [] volumes = [] for d in docs: s = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) energies.append(d["calcs_reversed"][-1]["output"]['energy']) volumes.append(s.volume) summary_dict["energies"] = energies summary_dict["volumes"] = volumes # fit the equation of state eos = EOS(self["eos"]) eos_fit = eos.fit(volumes, energies) summary_dict["results"] = dict(eos_fit.results) with open("bulk_modulus.json", "w") as f: f.write(json.dumps(summary_dict, default=DATETIME_HANDLER)) logger.info("BULK MODULUS CALCULATION COMPLETE")
def _match_material(self, doc): """ Returns the material_id that has the same structure as this doc as determined by the structure matcher. Returns None if no match. Args: doc: a JSON-like document Returns: (int) matching material_id or None """ formula = doc["formula_reduced_abc"] sgnum = doc["spacegroup"]["number"] for m in self._materials.find({"formula_reduced_abc": formula, "sg_number": sgnum}, {"structure": 1, "material_id": 1}): m_struct = Structure.from_dict(m["structure"]) t_struct = Structure.from_dict(doc["structure"]) sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False, allow_subset=False, comparator=ElementComparator()) if sm.fit(m_struct, t_struct): return m["material_id"] return None
def test_ordering_enumeration(self): # simple afm structure = Structure.from_file(os.path.join(ref_dir, "ordering/LaMnO3.json")) wf = MagneticOrderingsWF(structure) self.assertEqual(wf.input_origin, "afm") # ferrimagnetic (Cr produces net spin) structure = Structure.from_file(os.path.join(ref_dir, "ordering/Cr2NiO4.json")) wf = MagneticOrderingsWF(structure) self.assertEqual(wf.input_origin, "ferri_by_Cr") # antiferromagnetic on single magnetic site structure = Structure.from_file(os.path.join(ref_dir, "ordering/Cr2WO6.json")) wf = MagneticOrderingsWF(structure) self.assertEqual(wf.input_origin, "afm_by_Cr") # afm requiring large cell size # (enable for further development of workflow, too slow for CI) # structure = Structure.from_file(os.path.join(ref_dir, "CuO.json")) # wf = MagneticOrderingsWF(structure, default_magmoms={'Cu': 1.73}, # transformation_kwargs={'max_cell_size': 4}) # self.assertEqual(wf.input_origin, "afm") # antiferromagnetic by structural motif structure = Structure.from_file(os.path.join(ref_dir, "ordering/Ca3Co2O6.json")) wf = MagneticOrderingsWF( structure, strategies=("antiferromagnetic_by_motif",), # this example just misses default cut-off, so do not truncate truncate_by_symmetry=False, transformation_kwargs={"max_cell_size": 2}, ) self.assertEqual(wf.input_origin, "afm_by_motif_2a")
def test_unique_structure_substitutions( self ): # integration test # Create a pymatgen structure with 16 sites in a 4x4 square grid coords = np.array( [ [ 0.0, 0.0, 0.0 ], [ 0.25, 0.0, 0.0 ], [ 0.5, 0., 0.0 ], [ 0.75, 0.0, 0.0 ], [ 0.0, 0.25, 0.0 ], [ 0.25, 0.25, 0.0 ], [ 0.5, 0.25, 0.0 ], [ 0.75, 0.25, 0.0 ], [ 0.0, 0.5, 0.0 ], [ 0.25, 0.5, 0.0 ], [ 0.5, 0.5, 0.0 ], [ 0.75, 0.5, 0.0 ], [ 0.0, 0.75, 0.0 ], [ 0.25, 0.75, 0.0 ], [ 0.5, 0.75, 0.0 ], [ 0.75, 0.75, 0.0 ] ] ) atom_list = [ 'Li' ] * len( coords ) lattice = Lattice.from_parameters( a = 3.0, b=3.0, c=3.0, alpha=90, beta=90, gamma=90 ) parent_structure = Structure( lattice, atom_list, coords ) parent_structure.replace( 0, 'O' ) # substitute one site with 'O' ns = unique_structure_substitutions( parent_structure, 'Li', { 'Na':1, 'Li':14 } ) self.assertEqual( len( ns ), 5 ) distances = np.array( sorted( [ s.get_distance( s.indices_from_symbol('O')[0], s.indices_from_symbol('Na')[0] ) for s in ns ] ) ) np.testing.assert_array_almost_equal( distances, np.array( [ 0.75 , 1.06066 , 1.5 , 1.677051, 2.12132 ] ) ) np.testing.assert_array_equal( np.array( sorted( [ s.number_of_equivalent_configurations for s in ns ] ) ), np.array( [ 1, 2, 4, 4, 4 ] ) ) np.testing.assert_array_equal( np.array( sorted( [ s.full_configuration_degeneracy for s in ns ] ) ), np.array( [ 1, 2, 4, 4, 4 ] ) )
def setUp(self): with open(os.path.join(test_dir, 'LobsterCompleteDos_spin.json'), 'r') as f: data_spin = json.load(f) self.LobsterCompleteDOS_spin = LobsterCompleteDos.from_dict(data_spin) with open(os.path.join(test_dir, 'LobsterCompleteDos_nonspin.json'), 'r') as f: data_nonspin = json.load(f) self.LobsterCompleteDOS_nonspin = LobsterCompleteDos.from_dict(data_nonspin) with open(os.path.join(test_dir, 'structure_KF.json'), 'r') as f: data_structure = json.load(f) self.structure = Structure.from_dict(data_structure) with open(os.path.join(test_dir, 'LobsterCompleteDos_MnO.json'), 'r') as f: data_MnO = json.load(f) self.LobsterCompleteDOS_MnO = LobsterCompleteDos.from_dict(data_MnO) with open(os.path.join(test_dir, 'LobsterCompleteDos_MnO_nonspin.json'), 'r') as f: data_MnO_nonspin = json.load(f) self.LobsterCompleteDOS_MnO_nonspin = LobsterCompleteDos.from_dict(data_MnO_nonspin) with open(os.path.join(test_dir, 'structure_MnO.json'), 'r') as f: data_MnO = json.load(f) self.structure_MnO = Structure.from_dict(data_MnO)
def _match_material(self, taskdoc): """ Returns the material_id that has the same structure as this task as determined by the structure matcher. Returns None if no match. Args: taskdoc (dict): a JSON-like task document Returns: (int) matching material_id or None """ formula = taskdoc["formula_reduced_abc"] if "parent_structure" in taskdoc: # this is used to intentionally combine multiple data w/same formula but slightly different structure, e.g. from an ordering scheme t_struct = Structure.from_dict(taskdoc["parent_structure"]["structure"]) q = {"formula_reduced_abc": formula, "parent_structure.spacegroup.number": taskdoc["parent_structure"]["spacegroup"]["number"]} else: sgnum = taskdoc["output"]["spacegroup"]["number"] t_struct = Structure.from_dict(taskdoc["output"]["structure"]) q = {"formula_reduced_abc": formula, "sg_number": sgnum} for m in self._materials.find(q, {"parent_structure": 1, "structure": 1, "material_id": 1}): s_dict = m["parent_structure"]["structure"] if "parent_structure" in m else m["structure"] m_struct = Structure.from_dict(s_dict) sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False, allow_subset=False, comparator=ElementComparator()) if sm.fit(m_struct, t_struct): return m["material_id"] return None
def test_disordered_primitive_to_ordered_supercell(self): sm_atoms = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size='num_atoms', comparator=OrderDisorderElementComparator()) sm_sites = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size='num_sites', comparator=OrderDisorderElementComparator()) lp = Lattice.orthorhombic(10, 20, 30) pcoords = [[0, 0, 0], [0.5, 0.5, 0.5]] ls = Lattice.orthorhombic(20, 20, 30) scoords = [[0, 0, 0], [0.75, 0.5, 0.5]] prim = Structure(lp, [{'Na': 0.5}, {'Cl': 0.5}], pcoords) supercell = Structure(ls, ['Na', 'Cl'], scoords) supercell.make_supercell([[-1, 1, 0], [0, 1, 1], [1, 0, 0]]) self.assertFalse(sm_sites.fit(prim, supercell)) self.assertTrue(sm_atoms.fit(prim, supercell)) self.assertRaises(ValueError, sm_atoms.get_s2_like_s1, prim, supercell) self.assertEqual(len(sm_atoms.get_s2_like_s1(supercell, prim)), 4)
def poscar_from_sitelist( configs, labels, sitelists, structure, subset = None ): """ Uses pymatgen Structure.to() method to generates POSCAR files for a set of configurations within a parent structure. Args: configs (list): site configurations labels (list): atom labels to output sitelist (list): list of sites in fractional coords structure (pymatgen Structure): Parent structure subset (Optional [list]): list of atom indices to output """ if subset: species_clean = [ spec for i,spec in enumerate( structure.species ) if i not in subset ] species_config = [ spec for i,spec in enumerate( structure.species ) if i in subset ] frac_coords_clean = [ coord for i, coord in enumerate( structure.frac_coords ) if i not in subset ] clean_structure = Structure( structure.lattice, species_clean, frac_coords_clean ) else: clean_structure = Structure( structure.lattice, [], [] ) species_config = structure.species for idx, config in enumerate( configs, start=1 ): structure_config = clean_structure.copy() for label in labels: for pos in config.position( label ): for sitelist in sitelists: structure_config.append( species_config[ pos ], sitelist[ pos ] ) structure_config.to( filename="POSCAR_{}.vasp".format( idx ) )
def setUp(self): self.structure = Structure.from_spacegroup("Fm-3m", Lattice.cubic(3.5), ["Ni"], [[0, 0, 0]]) lattice = Lattice.cubic(3.010) frac_coords = [[0.00000, 0.00000, 0.00000], [0.00000, 0.50000, 0.50000], [0.50000, 0.00000, 0.50000], [0.50000, 0.50000, 0.00000], [0.50000, 0.00000, 0.00000], [0.50000, 0.50000, 0.50000], [0.00000, 0.00000, 0.50000], [0.00000, 0.50000, 0.00000]] species = ['Mg', 'Mg', 'Mg', 'Mg', 'O', 'O', 'O', 'O'] self.MgO = Structure(lattice, species, frac_coords) slabs = generate_all_slabs(self.structure, max_index=2, min_slab_size=6.0, min_vacuum_size=15.0, max_normal_search=1, center_slab=True) self.slab_dict = {''.join([str(i) for i in slab.miller_index]): slab for slab in slabs} self.asf_211 = AdsorbateSiteFinder(self.slab_dict["211"]) self.asf_100 = AdsorbateSiteFinder(self.slab_dict["100"]) self.asf_111 = AdsorbateSiteFinder(self.slab_dict["111"]) self.asf_110 = AdsorbateSiteFinder(self.slab_dict["110"]) self.asf_struct = AdsorbateSiteFinder( Structure.from_sites(self.slab_dict["111"].sites))
def run_task(self, fw_spec): prev_dir = fw_spec.get('PREV_DIR', None) self.custom_params = self.get('custom_params', None) if isinstance(self["structure"], Structure): s = self["structure"] elif isinstance(self["structure"], dict): s = Structure.from_dict(self["structure"]) else: s = Structure.from_file(os.path.join(prev_dir, self["structure"])) vis = load_class("pymatgen.io.vasp.sets", self["vasp_input_set"])( **self.get("input_set_params", {})) vis.write_input(s, ".") # Write Custom KPOINTS settings if necessary ksettings = self.custom_params.get('user_kpts_settings', None) if isinstance( self.custom_params, dict) else None if ksettings: style = ksettings.get('kpts_style', 'Gamma') kpoints = ksettings.get('kpts', [16,16,16]) shift = ksettings.get('kpts_shift', [0,0,0]) k = Kpoints(kpts=[kpoints], kpts_shift=shift) k.style = style k.write_file("KPOINTS")
def test_structure(self): quartz = self.quartz.structure np.testing.assert_array_equal(quartz.lattice.matrix, [[4.913400, 0, 0], [-2.456700, 4.255129, 0], [0, 0, 5.405200]]) self.assertEqual(quartz.formula, "Si3 O6") self.assertNotIn("molecule-ID", self.quartz.atoms.columns) ethane = self.ethane.structure np.testing.assert_array_equal(ethane.lattice.matrix, np.diag([10.0] * 3)) lbounds = np.array(self.ethane.box.bounds)[:, 0] coords = self.ethane.atoms[["x", "y", "z"]].values - lbounds np.testing.assert_array_equal(ethane.cart_coords, coords) np.testing.assert_array_equal(ethane.site_properties["charge"], self.ethane.atoms["q"]) tatb = self.tatb.structure frac_coords = tatb.frac_coords[381] real_frac_coords = frac_coords - np.floor(frac_coords) np.testing.assert_array_almost_equal(real_frac_coords, [0.01553397, 0.71487872, 0.14134139]) co = Structure.from_spacegroup(194, Lattice.hexagonal(2.50078, 4.03333), ["Co"], [[1/3, 2/3, 1/4]]) ld_co = LammpsData.from_structure(co) self.assertEqual(ld_co.structure.composition.reduced_formula, "Co") ni = Structure.from_spacegroup(225, Lattice.cubic(3.50804), ["Ni"], [[0, 0, 0]]) ld_ni = LammpsData.from_structure(ni) self.assertEqual(ld_ni.structure.composition.reduced_formula, "Ni")
def run_task(self, fw_spec): tag = self["tag"] db_file = env_chk(self.get("db_file"), fw_spec) t_step = self.get("t_step", 10) t_min = self.get("t_min", 0) t_max = self.get("t_max", 1000) mesh = self.get("mesh", [20, 20, 20]) eos = self.get("eos", "vinet") qha_type = self.get("qha_type", "debye_model") pressure = self.get("pressure", 0.0) gibbs_summary_dict = {} mmdb = MMVaspDb.from_db_file(db_file, admin=True) # get the optimized structure d = mmdb.collection.find_one({"task_label": "{} structure optimization".format(tag)}) structure = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) gibbs_summary_dict["structure"] = structure.as_dict() # get the data(energy, volume, force constant) from the deformation runs docs = mmdb.collection.find({"task_label": {"$regex": "{} gibbs*".format(tag)}, "formula_pretty": structure.composition.reduced_formula}) energies = [] volumes = [] force_constants = [] for d in docs: s = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) energies.append(d["calcs_reversed"][-1]["output"]['energy']) if qha_type not in ["debye_model"]: force_constants.append(d["calcs_reversed"][-1]["output"]['force_constants']) volumes.append(s.volume) gibbs_summary_dict["energies"] = energies gibbs_summary_dict["volumes"] = volumes if qha_type not in ["debye_model"]: gibbs_summary_dict["force_constants"] = force_constants G, T = None, None # use debye model if qha_type in ["debye_model"]: from atomate.tools.analysis import get_debye_model_gibbs G, T = get_debye_model_gibbs(energies, volumes, structure, t_min, t_step, t_max, eos, pressure) # use the phonopy interface else: from atomate.tools.analysis import get_phonopy_gibbs G, T = get_phonopy_gibbs(energies, volumes, force_constants, structure, t_min, t_step, t_max, mesh, eos, pressure) gibbs_summary_dict["G"] = G gibbs_summary_dict["T"] = T with open("gibbs.json", "w") as f: f.write(json.dumps(gibbs_summary_dict, default=DATETIME_HANDLER)) logger.info("GIBBS FREE ENERGY CALCULATION COMPLETE")
def run_task(self, fw_spec): from pymatgen.analysis.eos import EOS eos = self.get("eos", "vinet") tag = self["tag"] db_file = env_chk(self.get("db_file"), fw_spec) summary_dict = {"eos": eos} to_db = self.get("to_db", True) # collect and store task_id of all related tasks to make unique links with "tasks" collection all_task_ids = [] mmdb = VaspCalcDb.from_db_file(db_file, admin=True) # get the optimized structure d = mmdb.collection.find_one({"task_label": "{} structure optimization".format(tag)}) all_task_ids.append(d["task_id"]) structure = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) summary_dict["structure"] = structure.as_dict() summary_dict["formula_pretty"] = structure.composition.reduced_formula # get the data(energy, volume, force constant) from the deformation runs docs = mmdb.collection.find({"task_label": {"$regex": "{} bulk_modulus*".format(tag)}, "formula_pretty": structure.composition.reduced_formula}) energies = [] volumes = [] for d in docs: s = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) energies.append(d["calcs_reversed"][-1]["output"]['energy']) volumes.append(s.volume) all_task_ids.append(d["task_id"]) summary_dict["energies"] = energies summary_dict["volumes"] = volumes summary_dict["all_task_ids"] = all_task_ids # fit the equation of state eos = EOS(eos) eos_fit = eos.fit(volumes, energies) summary_dict["bulk_modulus"] = eos_fit.b0_GPa # TODO: find a better way for passing tags of the entire workflow to db - albalu if fw_spec.get("tags", None): summary_dict["tags"] = fw_spec["tags"] summary_dict["results"] = dict(eos_fit.results) summary_dict["created_at"] = datetime.utcnow() # db_file itself is required but the user can choose to pass the results to db or not if to_db: mmdb.collection = mmdb.db["eos"] mmdb.collection.insert_one(summary_dict) else: with open("bulk_modulus.json", "w") as f: f.write(json.dumps(summary_dict, default=DATETIME_HANDLER)) # TODO: @matk86 - there needs to be a builder to put it into materials collection... -computron logger.info("Bulk modulus calculation complete.")
def test_apply_transformation_mult(self): # Test returning multiple structures from each transformation. disord = Structure(np.eye(3) * 4.209, [{"Cs+": 0.5, "K+": 0.5}, "Cl-"], [[0, 0, 0], [0.5, 0.5, 0.5]]) disord.make_supercell([2, 2, 1]) tl = [EnumerateStructureTransformation(), OrderDisorderedStructureTransformation()] t = SuperTransformation(tl, nstructures_per_trans=10) self.assertEqual(len(t.apply_transformation(disord, return_ranked_list=20)), 8) t = SuperTransformation(tl) self.assertEqual(len(t.apply_transformation(disord, return_ranked_list=20)), 2)
def setUp(self): c1 = [[0.5] * 3, [0.9] * 3] c2 = [[0.5] * 3, [0.9, 0.1, 0.1]] s1 = Structure(Lattice.cubic(5), ['Si', 'Si'], c1) s2 = Structure(Lattice.cubic(5), ['Si', 'Si'], c2) structs = [] for s in s1.interpolate(s2, 3, pbc=True): structs.append(Structure.from_sites(s.sites, to_unit_cell=True)) self.structures = structs self.vis = MITNEBSet(self.structures)
def test_supercell_fit(self): sm = StructureMatcher(attempt_supercell=False) s1 = Structure.from_file(os.path.join(test_dir, "Al3F9.json")) s2 = Structure.from_file(os.path.join(test_dir, "Al3F9_distorted.json")) self.assertFalse(sm.fit(s1, s2)) sm = StructureMatcher(attempt_supercell=True) self.assertTrue(sm.fit(s1, s2)) self.assertTrue(sm.fit(s2, s1))
def test_write_inputs(self): c1 = [[0.5] * 3, [0.9] * 3] c2 = [[0.5] * 3, [0.9, 0.1, 0.1]] s1 = Structure(Lattice.cubic(5), ['Si', 'Si'], c1) s2 = Structure(Lattice.cubic(5), ['Si', 'Si'], c2) structs = [] for s in s1.interpolate(s2, 3, pbc=True): structs.append(Structure.from_sites(s.sites, to_unit_cell=True)) fc = self.vis._process_structures(structs)[2].frac_coords self.assertTrue(np.allclose(fc, [[0.5]*3,[0.9, 1.033333, 1.0333333]]))
def run(self): if os.path.exists("CONTCAR"): structure = Structure.from_file("CONTCAR") elif (not self.contcar_only) and os.path.exists("POSCAR"): structure = Structure.from_file("POSCAR") else: raise RuntimeError("No CONTCAR/POSCAR detected to generate input!") modname, classname = self.input_set.rsplit(".", 1) mod = __import__(modname, globals(), locals(), [classname], 0) vis = getattr(mod, classname)(structure, **self.kwargs) vis.write_input(".")
def test_dict_to_object(self): coords = [[0, 0, 0], [0.75, 0.5, 0.75]] lattice = Lattice([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]) struct = Structure(lattice, ["Si"] * 2, coords) d = {'structure_dict': [struct.as_dict(), struct.as_dict()]} df = DataFrame(data=d) df["structure"] = dict_to_object(df["structure_dict"]) self.assertEqual(df["structure"].tolist()[0], struct) self.assertEqual(df["structure"].tolist()[1], struct)
def setUp(self): # trivial example, simple square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H'], [[0, 0, 0]]) self.square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) # body-centered square lattice for testing structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(-1, -1, 0)) self.bc_square_sg.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) # body-centered square lattice for testing # directions reversed, should be equivalent to as bc_square structure = Structure(Lattice.tetragonal(5.0, 50.0), ['H', 'He'], [[0, 0, 0], [0.5, 0.5, 0.5]]) self.bc_square_sg_r = StructureGraph.with_empty_graph(structure, edge_weight_name="", edge_weight_units="") self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(-1, 0, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, 1, 0)) self.bc_square_sg_r.add_edge(0, 0, from_jimage=(0, 0, 0), to_jimage=(0, -1, 0)) self.bc_square_sg_r.add_edge(0, 1, from_jimage=(0, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, 0, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(-1, -1, 0), to_jimage=(0, 0, 0)) self.bc_square_sg_r.add_edge(1, 0, from_jimage=(0, -1, 0), to_jimage=(0, 0, 0)) # MoS2 example, structure graph obtained from critic2 # (not ground state, from mp-1023924, single layer) stdout_file = os.path.join(os.path.dirname(__file__), "..", "..", "..", 'test_files/critic2/MoS2_critic2_stdout.txt') with open(stdout_file, 'r') as f: reference_stdout = f.read() self.structure = Structure.from_file(os.path.join(os.path.dirname(__file__), "..", "..", "..", 'test_files/critic2/MoS2.cif')) c2o = Critic2Output(self.structure, reference_stdout) self.mos2_sg = c2o.structure_graph(edge_weight="bond_length", edge_weight_units="Å") 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).get_primitive_structure()
def run_task(self, fw_spec): from atomate.vasp.analysis.phonopy import get_phonopy_thermal_expansion tag = self["tag"] db_file = env_chk(self.get("db_file"), fw_spec) t_step = self.get("t_step", 10) t_min = self.get("t_min", 0) t_max = self.get("t_max", 1000) mesh = self.get("mesh", [20, 20, 20]) eos = self.get("eos", "vinet") pressure = self.get("pressure", 0.0) summary_dict = {} mmdb = VaspCalcDb.from_db_file(db_file, admin=True) # get the optimized structure d = mmdb.collection.find_one({"task_label": "{} structure optimization".format(tag)}) structure = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) summary_dict["structure"] = structure.as_dict() summary_dict["formula_pretty"] = structure.composition.reduced_formula # get the data(energy, volume, force constant) from the deformation runs docs = mmdb.collection.find({"task_label": {"$regex": "{} thermal_expansion*".format(tag)}, "formula_pretty": structure.composition.reduced_formula}) energies = [] volumes = [] force_constants = [] for d in docs: s = Structure.from_dict(d["calcs_reversed"][-1]["output"]['structure']) energies.append(d["calcs_reversed"][-1]["output"]['energy']) volumes.append(s.volume) force_constants.append(d["calcs_reversed"][-1]["output"]['force_constants']) summary_dict["energies"] = energies summary_dict["volumes"] = volumes summary_dict["force_constants"] = force_constants alpha, T = get_phonopy_thermal_expansion(energies, volumes, force_constants, structure, t_min, t_step, t_max, mesh, eos, pressure) summary_dict["alpha"] = alpha summary_dict["T"] = T with open("thermal_expansion.json", "w") as f: f.write(json.dumps(summary_dict, default=DATETIME_HANDLER)) # TODO: @matk86 - there needs to be a way to insert this into a database! And also # a builder to put it into materials collection... -computron logger.info("Thermal expansion coefficient calculation complete.")
def test_partial_disorder(self): s = Structure.from_file(filename=os.path.join(test_dir, "garnet.cif")) a = SpacegroupAnalyzer(s, 0.1) prim = a.find_primitive() s = prim.copy() s["Al3+"] = {"Al3+": 0.5, "Ga3+": 0.5} adaptor = EnumlibAdaptor(s, 1, 1, enum_precision_parameter=0.01) adaptor.run() structures = adaptor.structures self.assertEqual(len(structures), 7) for s in structures: self.assertEqual(s.formula, 'Ca12 Al4 Ga4 Si12 O48') s = prim.copy() s["Ca2+"] = {"Ca2+": 1/3, "Mg2+": 2/3} adaptor = EnumlibAdaptor(s, 1, 1, enum_precision_parameter=0.01) adaptor.run() structures = adaptor.structures self.assertEqual(len(structures), 20) for s in structures: self.assertEqual(s.formula, 'Ca4 Mg8 Al8 Si12 O48') s = prim.copy() s["Si4+"] = {"Si4+": 1/3, "Ge4+": 2/3} adaptor = EnumlibAdaptor(s, 1, 1, enum_precision_parameter=0.01) adaptor.run() structures = adaptor.structures self.assertEqual(len(structures), 18) for s in structures: self.assertEqual(s.formula, 'Ca12 Al8 Si4 Ge8 O48')
def run_task(self, fw_spec): s = Structure.from_dict(self["structure"]) mod = __import__("pymatgen.io.vaspio_set", globals(), locals(), [self["vasp_input_set"]], -1) vis = load_class("pymatgen.io.vaspio_set", self["vasp_input_set"])( **self.get("input_set_params", {})) vis.write_input(s, ".")
def test_timeout(self): s = Structure.from_file(filename=os.path.join(test_dir, "garnet.cif")) a = SpacegroupAnalyzer(s, 0.1) s["Al3+"] = {"Al3+": 0.5, "Ga3+": 0.5} adaptor = EnumlibAdaptor(s, 1, 1, enum_precision_parameter=0.01, timeout=0.0000000000001) self.assertRaises(TimeoutError, adaptor._run_multienum)
def generate_diffraction_plot(args): s = Structure.from_file(args.filenames[0]) c = XRDCalculator() if args.outfile: c.get_xrd_plot(s).savefig(args.outfile[0]) else: c.show_xrd_plot(s)
def _create_new_material(self, taskdoc): """ Create a new material document. Args: taskdoc (dict): a JSON-like task document Returns: (int) - material_id of the new document """ doc = {"created_at": datetime.utcnow()} doc["_tasksbuilder"] = {"all_task_ids": [], "prop_metadata": {"labels": {}, "task_ids": {}}, "updated_at": datetime.utcnow()} doc["spacegroup"] = taskdoc["output"]["spacegroup"] doc["sg_symbol"] = doc["spacegroup"]["symbol"] doc["sg_number"] = doc["spacegroup"]["number"] doc["structure"] = taskdoc["output"]["structure"] doc["material_id"] = self.mid_str(self._counter.find_one_and_update( {"_id": "materialid"}, {"$inc": {"c": 1}}, return_document=ReturnDocument.AFTER)["c"]) for x in ["formula_anonymous", "formula_pretty", "formula_reduced_abc", "elements", "nelements", "chemsys"]: doc[x] = taskdoc[x] if "parent_structure" in taskdoc: doc["parent_structure"] = taskdoc["parent_structure"] t_struct = Structure.from_dict(taskdoc["parent_structure"]["structure"]) doc["parent_structure"]["formula_reduced_abc"] = t_struct.composition.reduced_formula self._materials.insert_one(doc) return doc["material_id"]
def run(self): print("MaterialsEhullBuilder starting...") self._build_indexes() q = {"thermo.energy": {"$exists": True}} if not self.update_all: q["stability"] = {"$exists": False} mats = [m for m in self._materials.find(q, {"calc_settings": 1, "structure": 1, "thermo.energy": 1, "material_id": 1})] pbar = tqdm(mats) for m in pbar: pbar.set_description("Processing materials_id: {}".format(m['material_id'])) try: params = {} for x in ["is_hubbard", "hubbards", "potcar_spec"]: params[x] = m["calc_settings"][x] structure = Structure.from_dict(m["structure"]) energy = m["thermo"]["energy"] my_entry = ComputedEntry(structure.composition, energy, parameters=params) self._materials.update_one({"material_id": m["material_id"]}, {"$set": {"stability": self.mpr.get_stability([my_entry])[0]}}) mpids = self.mpr.find_structure(structure) self._materials.update_one({"material_id": m["material_id"]}, {"$set": {"mpids": mpids}}) except: import traceback print("<---") print("There was an error processing material_id: {}".format(m)) traceback.print_exc() print("--->") print("MaterialsEhullBuilder finished processing.")
def create_df(): newcoll = db['abc3'] newcoll.drop() x = 0 for doc in db['pauling_file_min_tags'].find().batch_size(75): x += 1 if x % 1000 == 0: print x if doc['metadata']['_structure']['anonymized_formula'] == 'ABC3' and doc['is_ht'] in [True,False] \ and 'TiO3' in doc['metadata']['_structure']['reduced_cell_formula']: newcoll.insert(doc) cursor = newcoll.find() df = pd.DataFrame(list(cursor)) for i, row in df.iterrows(): df.set_value(i, 'reduced_cell_formula', row['metadata']['_structure']['reduced_cell_formula']) try: df.set_value(i, 'space_group', int(row['metadata']['_Springer']['geninfo']['Space Group'])) except: df.set_value(i, 'space_group', None) try: df.set_value(i, 'density', float(row['metadata']['_Springer']['geninfo']['Density'].split()[2])) except IndexError as e: df.set_value(i, 'density', None) structure = Structure.from_dict(row['structure']) num_density = (structure.num_sites/structure.volume) no_of_atoms = Composition(structure.composition).num_atoms num_vol = (structure.volume/no_of_atoms) df.set_value(i, 'number_density', num_density) df.set_value(i, 'number_volume', num_vol) if row['metadata']['_structure']['is_ordered']: df.set_value(i, 'is_ordered', 1) else: df.set_value(i, 'is_ordered', 0) df.to_pickle('abc3.pkl')
def setUp(self): with open(os.path.join(test_dir, "TiO2_entries.json"), 'r') as fp: entries = json.load(fp, cls=MontyDecoder) self.struct_list = [e.structure for e in entries] self.oxi_structs = [self.get_structure("Li2O"), Structure.from_file(os.path.join( test_dir, "POSCAR.Li2O"))]
def get(self, cid, name): """Retrieve structure for contribution in CIF format. --- operationId: get_cif parameters: - name: cid in: path type: string pattern: '^[a-f0-9]{24}$' required: true description: contribution ID (ObjectId) - name: name in: path type: string required: true description: name of structure responses: 200: description: structure in CIF format schema: type: string """ mask = [f'content.structures.{name}'] entry = Contributions.objects.only(*mask).get(id=cid) structure = Structure.from_dict(entry.content.structures.get(name)) if structure: return CifWriter(structure, symprec=1e-10).__str__() return f"Structure with name {name} not found for {cid}!" # TODO raise 404?
def substrate(self): """ Return the substrate (Structure) of the interface. """ return Structure.from_sites(self.substrate_sites)
def setUp(self): self.single_bond = Structure( Lattice.cubic(10), ["H", "H", "H"], [[1, 0, 0], [0, 0, 0], [6, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.linear = Structure( Lattice.cubic(10), ["H", "H", "H"], [[1, 0, 0], [0, 0, 0], [2, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.bent45 = Structure( Lattice.cubic(10), ["H", "H", "H"], [[0, 0, 0], [0.707, 0.707, 0], [0.707, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.cubic = Structure( Lattice.cubic(1), ["H"], [[0, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.bcc = Structure( Lattice.cubic(1), ["H", "H"], [[0, 0, 0], [0.5, 0.5, 0.5]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.fcc = Structure( Lattice.cubic(1), ["H", "H", "H", "H"], [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.hcp = Structure( Lattice.hexagonal(1, 1.633), ["H", "H"], [[0.3333, 0.6667, 0.25], [0.6667, 0.3333, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.diamond = Structure( Lattice.cubic(1), ["H", "H", "H", "H", "H", "H", "H", "H"], [[0, 0, 0.5], [0.75, 0.75, 0.75], [0, 0.5, 0], [0.75, 0.25, 0.25], [0.5, 0, 0], [0.25, 0.75, 0.25], [0.5, 0.5, 0.5], [0.25, 0.25, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.trigonal_off_plane = Structure( Lattice.cubic(100), ["H", "H", "H", "H"], [[0.50, 0.50, 0.50], [0.25, 0.75, 0.25], [0.25, 0.25, 0.75], [0.75, 0.25, 0.25]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.regular_triangle = Structure( Lattice.cubic(30), ["H", "H", "H", "H"], [[15, 15.28867, 15.65], [14.5, 15, 15], [15.5, 15, 15], [15, 15.866, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.trigonal_planar = Structure( Lattice.cubic(30), ["H", "H", "H", "H"], [[15, 15.28867, 15], [14.5, 15, 15], [15.5, 15, 15], [15, 15.866, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square_planar = Structure( Lattice.cubic(30), ["H", "H", "H", "H", "H"], [[15, 15, 15], [14.75, 14.75, 15], [14.75, 15.25, 15], [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square = Structure( Lattice.cubic(30), ["H", "H", "H", "H", "H"], [[15, 15, 15.707], [14.75, 14.75, 15], [14.75, 15.25, 15], [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.T_shape = Structure( Lattice.cubic(30), ["H", "H", "H", "H"], [[15, 15, 15], [15, 15, 15.5], [15, 15.5, 15], [15, 14.5, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square_pyramid = Structure( Lattice.cubic(30), ["H", "H", "H", "H", "H", "H"], [[15, 15, 15], [15, 15, 15.3535], [14.75, 14.75, 15], [14.75, 15.25, 15], [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.pentagonal_planar = Structure( Lattice.cubic(30), ["Xe", "F", "F", "F", "F", "F"], [[0, -1.6237, 0], [1.17969, 0, 0], [-1.17969, 0, 0], [1.90877, -2.24389, 0], [-1.90877, -2.24389, 0], [0, -3.6307, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.pentagonal_pyramid = Structure( Lattice.cubic(30), ["Xe", "F", "F", "F", "F", "F", "F"], [[0, -1.6237, 0], [0, -1.6237, 1.17969], [1.17969, 0, 0], [-1.17969, 0, 0], [1.90877, -2.24389, 0], [-1.90877, -2.24389, 0], [0, -3.6307, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.pentagonal_bipyramid = Structure( Lattice.cubic(30), ["Xe", "F", "F", "F", "F", "F", "F", "F"], [[0, -1.6237, 0], [0, -1.6237, -1.17969], [0, -1.6237, 1.17969], [1.17969, 0, 0], [-1.17969, 0, 0], [1.90877, -2.24389, 0], [-1.90877, -2.24389, 0], [0, -3.6307, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.hexagonal_planar = Structure( Lattice.cubic(30), ["H", "C", "C", "C", "C", "C", "C"], [[0, 0, 0], [0.71, 1.2298, 0], [-0.71, 1.2298, 0], [0.71, -1.2298, 0], [-0.71, -1.2298, 0], [1.4199, 0, 0], [-1.4199, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.hexagonal_pyramid = Structure( Lattice.cubic(30), ["H", "Li", "C", "C", "C", "C", "C", "C"], [[0, 0, 0], [0, 0, 1.675], [0.71, 1.2298, 0], [-0.71, 1.2298, 0], [0.71, -1.2298, 0], [-0.71, -1.2298, 0], [1.4199, 0, 0], [-1.4199, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.hexagonal_bipyramid = Structure( Lattice.cubic(30), ["H", "Li", "Li", "C", "C", "C", "C", "C", "C"], [[0, 0, 0], [0, 0, 1.675], [0, 0, -1.675], [0.71, 1.2298, 0], [-0.71, 1.2298, 0], [0.71, -1.2298, 0], [-0.71, -1.2298, 0], [1.4199, 0, 0], [-1.4199, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.trigonal_pyramid = Structure( Lattice.cubic(30), ["P", "Cl", "Cl", "Cl", "Cl"], [[0, 0, 0], [0, 0, 2.14], [0, 2.02, 0], [1.74937, -1.01, 0], [-1.74937, -1.01, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.trigonal_bipyramidal = Structure( Lattice.cubic(30), ["P", "Cl", "Cl", "Cl", "Cl", "Cl"], [[0, 0, 0], [0, 0, 2.14], [0, 2.02, 0], [1.74937, -1.01, 0], [-1.74937, -1.01, 0], [0, 0, -2.14]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.cuboctahedron = Structure( Lattice.cubic(30), ["H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H"], [[15, 15, 15], [15, 14.5, 14.5], [15, 14.5, 15.5], [15, 15.5, 14.5], [15, 15.5, 15.5], [14.5, 15, 14.5], [14.5, 15, 15.5], [15.5, 15, 14.5], [15.5, 15, 15.5], [14.5, 14.5, 15], [14.5, 15.5, 15], [15.5, 14.5, 15], [15.5, 15.5, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.see_saw_rect = Structure( Lattice.cubic(30), ["H", "H", "H", "H", "H"], [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0], [-1.0, 0.0, 0.0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.sq_face_capped_trig_pris = Structure( Lattice.cubic(30), ["H", "H", "H", "H", "H", "H", "H", "H"], [[0, 0, 0], [-0.6546536707079771, -0.37796447300922725, 0.6546536707079771], [0.6546536707079771, -0.37796447300922725, 0.6546536707079771], [0.0, 0.7559289460184545, 0.6546536707079771], [-0.6546536707079771, -0.37796447300922725, -0.6546536707079771], [0.6546536707079771, -0.37796447300922725, -0.6546536707079771], [0.0, 0.7559289460184545, -0.6546536707079771], [0.0, -1.0, 0.0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None)
def setUp(self): self.diamond = Structure( Lattice([[2.189, 0, 1.264], [0.73, 2.064, 1.264], [0, 0, 2.528]]), ["C", "C"], [[2.554, 1.806, 4.423], [0.365, 0.258, 0.632]], coords_are_cartesian=True )
def test_oxide_type(self): el_li = Element("Li") el_o = Element("O") latt = Lattice([[3.985034, 0.0, 0.0], [0.0, 4.881506, 0.0], [0.0, 0.0, 2.959824]]) elts = [el_li, el_li, el_o, el_o, el_o, el_o] coords = list() coords.append([0.500000, 0.500000, 0.500000]) coords.append([0.0, 0.0, 0.0]) coords.append([0.632568, 0.085090, 0.500000]) coords.append([0.367432, 0.914910, 0.500000]) coords.append([0.132568, 0.414910, 0.000000]) coords.append([0.867432, 0.585090, 0.000000]) struct = Structure(latt, elts, coords) self.assertEqual(oxide_type(struct, 1.1), "superoxide") el_li = Element("Li") el_o = Element("O") elts = [el_li, el_o, el_o, el_o] latt = Lattice.from_parameters(3.999911, 3.999911, 3.999911, 133.847504, 102.228244, 95.477342) coords = [[0.513004, 0.513004, 1.000000], [0.017616, 0.017616, 0.000000], [0.649993, 0.874790, 0.775203], [0.099587, 0.874790, 0.224797]] struct = Structure(latt, elts, coords) self.assertEqual(oxide_type(struct, 1.1), "ozonide") latt = Lattice.from_parameters(3.159597, 3.159572, 7.685205, 89.999884, 89.999674, 60.000510) el_li = Element("Li") el_o = Element("O") elts = [el_li, el_li, el_li, el_li, el_o, el_o, el_o, el_o] coords = [[0.666656, 0.666705, 0.750001], [0.333342, 0.333378, 0.250001], [0.000001, 0.000041, 0.500001], [0.000001, 0.000021, 0.000001], [0.333347, 0.333332, 0.649191], [0.333322, 0.333353, 0.850803], [0.666666, 0.666686, 0.350813], [0.666665, 0.666684, 0.149189]] struct = Structure(latt, elts, coords) self.assertEqual(oxide_type(struct, 1.1), "peroxide") el_li = Element("Li") el_o = Element("O") el_h = Element("H") latt = Lattice.from_parameters(3.565276, 3.565276, 4.384277, 90.000000, 90.000000, 90.000000) elts = [el_h, el_h, el_li, el_li, el_o, el_o] coords = [[0.000000, 0.500000, 0.413969], [0.500000, 0.000000, 0.586031], [0.000000, 0.000000, 0.000000], [0.500000, 0.500000, 0.000000], [0.000000, 0.500000, 0.192672], [0.500000, 0.000000, 0.807328]] struct = Structure(latt, elts, coords) self.assertEqual(oxide_type(struct, 1.1), "hydroxide") el_li = Element("Li") el_n = Element("N") el_h = Element("H") latt = Lattice.from_parameters(3.565276, 3.565276, 4.384277, 90.000000, 90.000000, 90.000000) elts = [el_h, el_h, el_li, el_li, el_n, el_n] coords = [[0.000000, 0.500000, 0.413969], [0.500000, 0.000000, 0.586031], [0.000000, 0.000000, 0.000000], [0.500000, 0.500000, 0.000000], [0.000000, 0.500000, 0.192672], [0.500000, 0.000000, 0.807328]] struct = Structure(latt, elts, coords) self.assertEqual(oxide_type(struct, 1.1), "None") el_o = Element("O") latt = Lattice.from_parameters(4.389828, 5.369789, 5.369789, 70.786622, 69.244828, 69.244828) elts = [el_o, el_o, el_o, el_o, el_o, el_o, el_o, el_o] coords = [[0.844609, 0.273459, 0.786089], [0.155391, 0.213911, 0.726541], [0.155391, 0.726541, 0.213911], [0.844609, 0.786089, 0.273459], [0.821680, 0.207748, 0.207748], [0.178320, 0.792252, 0.792252], [0.132641, 0.148222, 0.148222], [0.867359, 0.851778, 0.851778]] struct = Structure(latt, elts, coords) self.assertEqual(oxide_type(struct, 1.1), "None")
def run_task(self, fw_spec): gibbs_dict = {} tag = self["tag"] t_step = self.get("t_step", 10) t_min = self.get("t_min", 0) t_max = self.get("t_max", 1000) mesh = self.get("mesh", [20, 20, 20]) eos = self.get("eos", "vinet") qha_type = self.get("qha_type", "debye_model") pressure = self.get("pressure", 0.0) poisson = self.get("poisson", 0.25) anharmonic_contribution = self.get("anharmonic_contribution", False) gibbs_dict["metadata"] = self.get("metadata", {}) db_file = env_chk(self.get("db_file"), fw_spec) mmdb = VaspCalcDb.from_db_file(db_file, admin=True) # get the optimized structure d = mmdb.collection.find_one( {"task_label": "{} structure optimization".format(tag)}, {"calcs_reversed": 1}) structure = Structure.from_dict( d["calcs_reversed"][-1]["output"]['structure']) gibbs_dict["structure"] = structure.as_dict() gibbs_dict["formula_pretty"] = structure.composition.reduced_formula # get the data(energy, volume, force constant) from the deformation runs docs = mmdb.collection.find( { "task_label": { "$regex": "{} gibbs*".format(tag) }, "formula_pretty": structure.composition.reduced_formula }, {"calcs_reversed": 1}) energies = [] volumes = [] force_constants = [] for d in docs: s = Structure.from_dict( d["calcs_reversed"][-1]["output"]['structure']) energies.append(d["calcs_reversed"][-1]["output"]['energy']) if qha_type not in ["debye_model"]: force_constants.append( d["calcs_reversed"][-1]["output"]['force_constants']) volumes.append(s.volume) gibbs_dict["energies"] = energies gibbs_dict["volumes"] = volumes if qha_type not in ["debye_model"]: gibbs_dict["force_constants"] = force_constants try: # use quasi-harmonic debye approximation if qha_type in ["debye_model"]: from pymatgen.analysis.quasiharmonic import QuasiharmonicDebyeApprox qhda = QuasiharmonicDebyeApprox( energies, volumes, structure, t_min, t_step, t_max, eos, pressure=pressure, poisson=poisson, anharmonic_contribution=anharmonic_contribution) gibbs_dict.update(qhda.get_summary_dict()) gibbs_dict["anharmonic_contribution"] = anharmonic_contribution gibbs_dict["success"] = True # use the phonopy interface else: from atomate.vasp.analysis.phonopy import get_phonopy_gibbs G, T = get_phonopy_gibbs(energies, volumes, force_constants, structure, t_min, t_step, t_max, mesh, eos, pressure) gibbs_dict["gibbs_free_energy"] = G gibbs_dict["temperatures"] = T gibbs_dict["success"] = True # quasi-harmonic analysis failed, set the flag to false except: import traceback logger.warn("Quasi-harmonic analysis failed!") gibbs_dict["success"] = False gibbs_dict["traceback"] = traceback.format_exc() gibbs_dict['metadata'].update({"task_label_tag": tag}) gibbs_dict["created_at"] = datetime.utcnow() gibbs_dict = jsanitize(gibbs_dict) # TODO: @matk86: add a list of task_ids that were used to construct the analysis to DB? # -computron if not db_file: dump_file = "gibbs.json" logger.info("Dumping the analysis summary to {}".format(dump_file)) with open(dump_file, "w") as f: f.write(json.dumps(gibbs_dict, default=DATETIME_HANDLER)) else: coll = mmdb.db["gibbs_tasks"] coll.insert_one(gibbs_dict) logger.info("Gibbs free energy calculation complete.") if not gibbs_dict["success"]: return FWAction(defuse_children=True)
def test_ensure_vacuum_for_SiP(self): # Compound test for add_vacuum and get_spacing. os.chdir(ROOT) structure = Structure.from_file('POSCAR_SiP') structure = ensure_vacuum(structure, vacuum=15) self.assertAlmostEqual(get_spacing(structure), 15.0)
def get_structure(self, sid): """Convenience function to get pymatgen structure.""" return Structure.from_dict( self.structures.get_entry(pk=sid, _fields=["lattice", "sites", "charge"]).result())
[['Fe', 'Y'], [u'sandbox-mvc-819'], [u'sandbox-mvc-1830']], [['Co', 'Y'], [u'sandbox-mvc-1596'], []], [['Ni', 'Y'], [u'mp-25595'], [u'sandbox-mvc-1778']] ] batt_list = [] for result in results: if [] not in result: id_charge = result[1][0] id_discharge = result[2][0] dict_charge = materials.find({"task_id": id_charge})[0] dict_discharge = materials.find({"task_id": id_discharge})[0] charge_struc = Structure.from_dict(dict_charge["structure"]) charge_energy = dict_charge["final_energy"] entry_charge = ComputedStructureEntry(charge_struc, charge_energy) charge_ehull = dict_charge["e_above_hull"] discharge_struc = Structure.from_dict(dict_discharge["structure"]) discharge_energy = dict_discharge["final_energy"] entry_discharge = ComputedStructureEntry(discharge_struc, discharge_energy) discharge_ehull = dict_discharge["e_above_hull"] mpr = MPRester(api_key=API_KEY, host="www.materialsproject.org") entries = mpr.get_entries(result[0][1], inc_structure="final") counter = 0 energies = []
def main(): """ logicMain function. Does the cli """ options = docopt(__doc__) poscar_path = options['<poscar>'] if not exists(poscar_path): raise IOError('POSCAR file "{0}" does not exist.'.format(poscar_path)) else: try: structure = Poscar.from_file(poscar_path).structure species = set( map_structure(structure, apply=lambda s: s.specie.symbol)) except: raise IOError( 'Could not parse POSCAR file "{0}"'.format(poscar_path)) if options['--incar']: incar_path = options['--incar'] if not exists(incar_path): raise IOError( 'INCAR file "{0}" does not exist.'.format(incar_path)) else: try: incar = Incar.from_file(incar_path) except: raise IOError( 'Could not parse INCAR file "{0}"'.format(incar_path)) if options['supercell']: try: sx, sy, sz = [int(options['<s{0}>'.format(k)]) for k in 'xyz'] except: raise ValueError('Could not parse supercell parameters') else: structure.make_supercell([sx, sy, sz]) if options['direction']: try: dx, dy, dz = [int(options['<d{0}>'.format(k)]) for k in 'xyz'] except: raise ValueError('Could not parse direction') else: cl_direction = unit_vector(np.array([dx, dy, dz])) else: cl_direction = unit_vector(np.array([1.0, 0.0, 0.0])) lengths = parse_lengths(options['<lengths>']) if not all([k in species for k in lengths.keys()]): missing_elements = set(lengths.keys()) - species raise ValueError( 'The following element{0} {1} not specified in "{2}": {3}'.format( 's' if len(missing_elements) > 1 else '', 'are' if len(missing_elements) > 1 else 'is', poscar_path, ', '.join(list(missing_elements)))) for missing_element in species - set(lengths.keys()): lengths[missing_element] = 0.0 if options['ncl']: magmoms = generate_spins_vecs_ncl(structure, lengths) # Check if net magnetic moment is really zero sum_vec = np.array([array for _, v in magmoms.items() for array in v]) assert np.isclose(np.sum(sum_vec, axis=0), np.zeros((3, ))).all() if options['cl']: if options['--imbalanced']: balanced = False else: balanced = True magmoms = generate_spins_vecs_cl(structure, lengths, direction=cl_direction, balanced=balanced) # Check if net magnetic moment is really zero sum_vec = np.array([array for _, v in magmoms.items() for array in v]) assert np.isclose(np.sum(sum_vec, axis=0), np.zeros((3, ))).all() if options['fm']: magmoms = generate_spins_vecs_fm(structure, lengths, direction=cl_direction) frac_coords_list = [] species_list = [] magmom_str = [] magmoms_site_property = {'magmom': []} for spec, magm in magmoms.items(): # Assemble the species list and the fractional coords in the same order as the generated magnetic moments current_frac_coords = map_structure( structure, predicate=lambda site: site.specie.symbol == spec, apply=lambda site: site.frac_coords) species_list.extend([spec] * len(current_frac_coords)) frac_coords_list.extend(current_frac_coords) # If direction is given calculate the projection of the moment onto the direction which gives length and # orientation if options['direction'] or options['ncl']: magmom_str.extend([ ' '.join([make_format_crumb(i) for i in range(3)]).format(mag_x, mag_y, mag_z) for mag_x, mag_y, mag_z in magm ]) magmoms_site_property['magmom'].extend( [mag_x, mag_y, mag_z] for mag_x, mag_y, mag_z in magm) else: magmom_str.extend([ make_format_crumb(0).format( np.dot(cl_direction, np.array([mag_x, mag_y, mag_z]))) for mag_x, mag_y, mag_z in magm ]) magmoms_site_property['magmom'].extend([ np.dot(cl_direction, np.array([mag_x, mag_y, mag_z])) for mag_x, mag_y, mag_z in magm ]) # Create the new structure new_structure = Structure(structure.lattice, species_list, frac_coords_list, site_properties=magmoms_site_property) magmom_str = ' '.join(magmom_str) # Write the new Posar file Poscar(new_structure).write_file( file_exists('{0}{1}'.format(poscar_path, OUTPUT_SUFFIX))) if options['--incar']: incar['MAGMOM'] = magmom_str incar.write_file(file_exists('INCAR{0}'.format(OUTPUT_SUFFIX))) else: # Print the magnetic moment vector to the terminal print('MAGMOM = {0}'.format(magmom_str)) if options['--plot']: plot_magmoms(magmoms) if options['--cif']: cif_writer = CifWriter(new_structure, write_magmoms=True) cif_writer.write_file( file_exists('{0}{1}.cif'.format(poscar_path, OUTPUT_SUFFIX)))
def test_calculate(self): s1 = Structure.from_spacegroup(227, Lattice.cubic(5.46873), ['Si'], [[0, 0, 0]]) profile1 = dict(Si=dict(r=0.5, w=1.9), C=dict(r=0.5, w=2.55)) diag1 = np.random.randint(4) tjm1 = np.random.randint(1, 11) calculator1 = SpectralNeighborAnalysis(rcutfac=5, twojmax=tjm1, element_profile=profile1, quadratic=False, diagonalstyle=diag1) sna1, snad1, snav1, elem1 = calculator1.calculate([s1])[0] n1 = calculator1.n_bs self.assertAlmostEqual(sna1[0][0], 585.920) self.assertEqual(sna1.shape, (len(s1), n1)) self.assertEqual(snad1.shape, (len(s1), n1 * 3 * len(profile1))) self.assertEqual(snav1.shape, (len(s1), n1 * 6 * len(profile1))) self.assertEqual(len(np.unique(elem1)), 1) calculator4 = SpectralNeighborAnalysis(rcutfac=5, twojmax=tjm1, element_profile=profile1, quadratic=True, diagonalstyle=diag1) sna4, snad4, snav4, elem4 = calculator4.calculate([s1])[0] n4 = calculator4.n_bs n4 += int((1 + n4) * n4 / 2) self.assertAlmostEqual(sna4[0][0], 585.920) self.assertEqual(sna4.shape, (len(s1), n4)) self.assertEqual(snad4.shape, (len(s1), n4 * 3 * len(profile1))) self.assertEqual(snav4.shape, (len(s1), n4 * 6 * len(profile1))) self.assertEqual(len(np.unique(elem4)), 1) s2 = Structure.from_spacegroup(225, Lattice.cubic(5.69169), ['Na', 'Cl'], [[0, 0, 0], [0, 0, 0.5]]) profile2 = dict(Na=dict(r=0.3, w=0.9), Cl=dict(r=0.7, w=3.0)) diag2 = np.random.randint(4) tjm2 = np.random.randint(1, 11) calculator2 = SpectralNeighborAnalysis(rcutfac=5, twojmax=tjm2, element_profile=profile2, quadratic=False, diagonalstyle=diag2) sna2, snad2, snav2, elem2 = calculator2.calculate([s2])[0] n2 = calculator2.n_bs self.assertAlmostEqual(sna2[0][0], 525.858) self.assertEqual(sna2.shape, (len(s2), n2)) self.assertEqual(snad2.shape, (len(s2), n2 * 3 * len(profile2))) self.assertEqual(snav2.shape, (len(s2), n2 * 6 * len(profile2))) self.assertEqual(len(np.unique(elem2)), len(profile2)) calculator5 = SpectralNeighborAnalysis(rcutfac=5, twojmax=tjm2, element_profile=profile2, quadratic=True, diagonalstyle=diag2) sna5, snad5, snav5, elem5 = calculator5.calculate([s2])[0] n5 = calculator5.n_bs n5 += int((1 + n5) * n5 / 2) self.assertAlmostEqual(sna5[0][0], 525.858) self.assertEqual(sna5.shape, (len(s2), n5)) self.assertEqual(snad5.shape, (len(s2), n5 * 3 * len(profile2))) self.assertEqual(snav5.shape, (len(s2), n5 * 6 * len(profile2))) self.assertEqual(len(np.unique(elem5)), len(profile2)) s3 = Structure.from_spacegroup(221, Lattice.cubic(3.88947), ['Ca', 'Ti', 'O'], [[0.5, 0.5, 0.5], [0, 0, 0], [0, 0, 0.5]]) profile3 = dict(Ca=dict(r=0.4, w=1.0), Ti=dict(r=0.3, w=1.5), O=dict(r=0.75, w=3.5)) diag3 = np.random.randint(4) tjm3 = np.random.randint(1, 11) calculator3 = SpectralNeighborAnalysis(rcutfac=5, twojmax=tjm3, element_profile=profile3, quadratic=False, diagonalstyle=diag3) sna3, snad3, snav3, elem3 = calculator3.calculate([s3])[0] n3 = calculator3.n_bs self.assertAlmostEqual(sna3[0][0], 25506.3) self.assertEqual(sna3.shape, (len(s3), n3)) self.assertEqual(snad3.shape, (len(s3), n3 * 3 * len(profile3))) self.assertEqual(snav3.shape, (len(s3), n3 * 6 * len(profile3))) self.assertEqual(len(np.unique(elem3)), len(profile3)) calculator6 = SpectralNeighborAnalysis(rcutfac=5, twojmax=tjm3, element_profile=profile3, quadratic=True, diagonalstyle=diag3) sna6, snad6, snav6, elem6 = calculator6.calculate([s3])[0] n6 = calculator6.n_bs n6 += int((1 + n6) * n6 / 2) self.assertAlmostEqual(sna6[0][0], 25506.3) self.assertEqual(sna6.shape, (len(s3), n6)) self.assertEqual(snad6.shape, (len(s3), n6 * 3 * len(profile3))) self.assertEqual(snav6.shape, (len(s3), n6 * 6 * len(profile3))) self.assertEqual(len(np.unique(elem6)), len(profile3))
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())
from pymatgen import Structure from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from pymatgen.transformations.advanced_transformations import EnumerateStructureTransformation from pymatgen.io.vasp.sets import batch_write_input, MPRelaxSet structure = Structure.from_file( "D:/Program Files (x86)/python2/file/EntryWithCollCode418490.cif") # (获取文件 当在自己电脑中调试的时候需要将相关的路径统一一下) print(structure) # loop over all sites in the structure for i, site in enumerate(structure): # (enumerate 为枚举类型) # change the occupancy of Li+ disordered sites to 0.5 if not site.is_ordered: structure[i] = {"Li+": 0.5} print("The composition after adjustments is %s." % structure.composition.reduced_formula) analyzer = SpacegroupAnalyzer(structure) # SpacegroupAnalyzer为空间群分析 晶体内部结构中全部对称要素的集合称为 “空间群” 。 # 一切晶体结构中总共只能有230种不同的对称要素组合方式,即230个空间群所谓点空间群, # 是由一个平移群和一个点群对称操作组合而成的,它的一般对称操作可以写成(R | t (αβγ)),其中R表示点群对称操作,t(αβγ)表示平移操作 # 为了保持可排序的顺序,我们只在原始单元上执行枚举。原始单元可以使用*空间群分析器*获得 prim_cell = analyzer.find_primitive() print(prim_cell) enum = EnumerateStructureTransformation() # 变换枚举结构 enumerated = enum.apply_transformation(prim_cell, 90) # 在这需要限制返回结构的数量 structures = [d["structure"] for d in enumerated] print("%d structures returned." % len(structures))
def test_get_structure_type_for_conventional_material(self): os.chdir(ROOT) structure = Structure.from_file('POSCAR_Fe') test_type = get_structure_type(structure) self.assertEqual(test_type, 'conventional')
def film(self): """ Return the film (Structure) of the interface. """ return Structure.from_sites(self.film_sites)
def get_wf_surface(slabs, molecules=[], bulk_structure=None, slab_gen_params=None, vasp_cmd="vasp", db_file=None, ads_structures_params={}, add_molecules_in_box=False): """ Args: slabs (list of Slabs or Structures): slabs to calculate molecules (list of Molecules): molecules to place as adsorbates bulk_structure (Structure): bulk structure from which generate slabs after reoptimization. If supplied, workflow will begin with bulk structure optimization. slab_gen_params (dict): dictionary of slab generation parameters used to generate the slab, necessary to get the slab that corresponds to the bulk structure if in that mode ads_structures_params (dict): parameters to be supplied as kwargs to AdsorbateSiteFinder.generate_adsorption_structures add_molecules_in_box (boolean): flag to add calculation of molecule energies to the workflow db_file (string): path to database file vasp_cmd (string): vasp command Returns: Workflow """ fws, parents = [], [] if bulk_structure: vis = MVLSlabSet(bulk_structure, bulk=True) fws.append( OptimizeFW(structure=bulk_structure, vasp_input_set=vis, vasp_cmd="vasp", db_file=db_file)) parents = fws[0] for slab in slabs: name = slab.composition.reduced_formula if getattr(slab, "miller_index", None): name += "_{}".format(slab.miller_index) fws.append( get_slab_fw(slab, bulk_structure, slab_gen_params, db_file=db_file, vasp_cmd=vasp_cmd, parents=parents, name=name + " slab optimization")) for molecule in molecules: ads_slabs = AdsorbateSiteFinder( slab).generate_adsorption_structures(molecule, **ads_structures_params) for n, ads_slab in enumerate(ads_slabs): ads_name = "{}-{} adsorbate optimization {}".format( molecule.composition.formula, name, n) fws.append( get_slab_fw(ads_slab, bulk_structure, slab_gen_params, db_file=db_file, vasp_cmd=vasp_cmd, parents=parents, name=ads_name)) if add_molecules_in_box: for molecule in molecules: # molecule in box m_struct = Structure(Lattice.cubic(10), molecule.species_and_occu, molecule.cart_coords, coords_are_cartesian=True) m_struct.translate_sites( list(range(len(m_struct))), np.array([0.5] * 3) - np.average(m_struct.frac_coords, axis=0)) vis = MVLSlabSet(m_struct) fws.append( OptimizeFW(structure=molecule, job_type="normal", vasp_input_set=vis, db_file=db_file, vasp_cmd=vasp_cmd)) # TODO: add analysis framework return Workflow(fws, name="{} surfaces wf, e.g., {}".format( len(fws), fws[0].name))
import itertools import json import os import collections from collections import Counter import numpy as np from pymatgen import Structure from statistics import mode import shutil # Step 1: # ## Open a folder and determine the 'cheapest' method of calculating simularities p = Structure.from_file(filename='/Users/budmacaulay/Desktop/newruns/0' + '/POSCAR') # Pretty sure it's more light weight to use dicts and such but im a terrible coder and honestly im painfully lazy c = collections.Counter(p.species) leastcom = [] for site in p: if site.specie.name == c.most_common()[-1][0].name: leastcom.append(site) checkele = c.most_common()[-2][0].name # # # - - - Checking first 100 desired sites are in correct position - - - # # # thecount = 0 for folder in range(1, 100): # 1 Open poscar comped = Structure.from_file(filename='/Users/budmacaulay/Desktop/newtestssss/' + str(folder) + '/POSCAR') # 2 Check if it compares i = 0
import math from pymatgen import Structure, Element import os import numpy as np s = Structure.from_file('CONTCAR') sr = [] ti = [] z = [] for i in s.sites: if i.specie == Element.O: z.append(i.z) elif i.specie == Element.Ti or i.specie == Element.Ti: ti.append(i.z) elif i.specie is Element.Ba or i.specie == Element.Ba: sr.append(i.z) arr_Sr = [(x, x - y) for x,y in zip(sorted(sr), sorted(z)[2::3])] arr_Ti = [(x, x - y) for x,y in zip(sorted(ti), sorted(z)[1::3])] print(arr_Sr) print(arr_Ti) np.savetxt('sr.dat', arr_Sr, delimiter='\t') np.savetxt('ti.dat', arr_Ti, delimiter='\t')
def add_magnetism(mat): mag_types = {"NM": "Non-magnetic", "FiM": "Ferri", "AFM": "AFM", "FM": "FM"} struc = Structure.from_dict(mat["structure"]) msa = CollinearMagneticStructureAnalyzer(struc) mat["magnetic_type"] = mag_types[msa.ordering.value]
def test_get_magmom_string_for_FeCl2(self): os.chdir(ROOT) structure = Structure.from_file('POSCAR_FeCl2') test_string = get_magmom_string(structure) self.assertEqual(test_string, u'1.0*6.0 2.0*0.5')
def run_task(self, fw_spec): ref_struct = self['structure'] d = {"analysis": {}, "initial_structure": self['structure'].as_dict()} # Get optimized structure calc_locs_opt = [ cl for cl in fw_spec.get('calc_locs', []) if 'optimiz' in cl['name'] ] if calc_locs_opt: optimize_loc = calc_locs_opt[-1]['path'] logger.info("Parsing initial optimization directory: {}".format( optimize_loc)) drone = VaspDrone() optimize_doc = drone.assimilate(optimize_loc) opt_struct = Structure.from_dict( optimize_doc["calcs_reversed"][0]["output"]["structure"]) d.update({"optimized_structure": opt_struct.as_dict()}) ref_struct = opt_struct eq_stress = -0.1 * Stress(optimize_doc["calcs_reversed"][0] ["output"]["ionic_steps"][-1]["stress"]) else: eq_stress = None if self.get("fw_spec_field"): d.update({ self.get("fw_spec_field"): fw_spec.get(self.get("fw_spec_field")) }) # Get the stresses, strains, deformations from deformation tasks defo_dicts = fw_spec["deformation_tasks"].values() stresses, strains, deformations = [], [], [] for defo_dict in defo_dicts: stresses.append(Stress(defo_dict["stress"])) strains.append(Strain(defo_dict["strain"])) deformations.append(Deformation(defo_dict["deformation_matrix"])) # Add derived stresses and strains if symmops is present for symmop in defo_dict.get("symmops", []): stresses.append(Stress(defo_dict["stress"]).transform(symmop)) strains.append(Strain(defo_dict["strain"]).transform(symmop)) deformations.append( Deformation( defo_dict["deformation_matrix"]).transform(symmop)) stresses = [-0.1 * s for s in stresses] pk_stresses = [ stress.piola_kirchoff_2(deformation) for stress, deformation in zip(stresses, deformations) ] d['fitting_data'] = { 'cauchy_stresses': stresses, 'eq_stress': eq_stress, 'strains': strains, 'pk_stresses': pk_stresses, 'deformations': deformations } logger.info("Analyzing stress/strain data") # TODO: @montoyjh: what if it's a cubic system? don't need 6. -computron # TODO: Can add population method but want to think about how it should # be done. -montoyjh order = self.get('order', 2) if order > 2: method = 'finite_difference' else: method = self.get('fitting_method', 'finite_difference') if method == 'finite_difference': result = ElasticTensorExpansion.from_diff_fit(strains, pk_stresses, eq_stress=eq_stress, order=order) if order == 2: result = ElasticTensor(result[0]) elif method == 'pseudoinverse': result = ElasticTensor.from_pseudoinverse(strains, pk_stresses) elif method == 'independent': result = ElasticTensor.from_independent_strains( strains, pk_stresses, eq_stress=eq_stress) else: raise ValueError( "Unsupported method, method must be finite_difference, " "pseudoinverse, or independent") ieee = result.convert_to_ieee(ref_struct) d.update({ "elastic_tensor": { "raw": result.voigt, "ieee_format": ieee.voigt } }) if order == 2: d.update({ "derived_properties": ieee.get_structure_property_dict(ref_struct) }) else: soec = ElasticTensor(ieee[0]) d.update({ "derived_properties": soec.get_structure_property_dict(ref_struct) }) d["formula_pretty"] = ref_struct.composition.reduced_formula d["fitting_method"] = method d["order"] = order d = jsanitize(d) # Save analysis results in json or db db_file = env_chk(self.get('db_file'), fw_spec) if not db_file: with open("elasticity.json", "w") as f: f.write(json.dumps(d, default=DATETIME_HANDLER)) else: db = VaspCalcDb.from_db_file(db_file, admin=True) db.collection = db.db["elasticity"] db.collection.insert_one(d) logger.info("Elastic analysis complete.") return FWAction()
def run_task(self, fw_spec): wfid = list(filter(lambda x: 'wfid' in x, fw_spec['tags'])).pop() db_file = env_chk(self.get("db_file"), fw_spec) vaspdb = VaspCalcDb.from_db_file(db_file, admin=True) # ferroelectric workflow groups calculations by generated wfid tag polarization_tasks = vaspdb.collection.find({ "tags": wfid, "task_label": { "$regex": ".*polarization" } }) tasks = [] outcars = [] structure_dicts = [] sort_weight = [] energies_per_atom = [] energies = [] zval_dicts = [] for p in polarization_tasks: # Grab data from each polarization task energies_per_atom.append( p['calcs_reversed'][0]['output']['energy_per_atom']) energies.append(p['calcs_reversed'][0]['output']['energy']) tasks.append(p['task_label']) outcars.append(p['calcs_reversed'][0]['output']['outcar']) structure_dicts.append( p['calcs_reversed'][0]['input']['structure']) zval_dicts.append( p['calcs_reversed'][0]['output']['outcar']['zval_dict']) # Add weight for sorting # Want polarization calculations in order of nonpolar to polar for Polarization object # This number needs to be bigger than the number of calculations max_sort_weight = 1000000 if 'nonpolar_polarization' in p['task_label']: sort_weight.append(0) elif "polar_polarization" in p['task_label']: sort_weight.append(max_sort_weight) elif "interpolation_" in p['task_label']: num = 0 part = re.findall(r'interpolation_[0-9]+_polarization', p['task_label']) if part != []: part2 = re.findall(r'[0-9]+', part.pop()) if part2 != []: num = part2.pop() sort_weight.append(max_sort_weight - int(num)) # Sort polarization tasks # nonpolar -> interpolation_n -> interpolation_n-1 -> ... -> interpolation_1 -> polar data = zip(tasks, structure_dicts, outcars, energies_per_atom, energies, sort_weight) data = sorted(data, key=lambda x: x[-1]) # Get the tasks, structures, etc in sorted order from the zipped data. tasks, structure_dicts, outcars, energies_per_atom, energies, sort_weight = zip( *data) structures = [ Structure.from_dict(structure) for structure in structure_dicts ] # If LCALCPOL = True then Outcar will parse and store the pseudopotential zvals. zval_dict = zval_dicts.pop() # Assumes that we want to calculate the ionic contribution to the dipole moment. # VASP's ionic contribution is sometimes strange. # See pymatgen.analysis.ferroelectricity.polarization.Polarization for details. p_elecs = [outcar['p_elec'] for outcar in outcars] p_ions = [ get_total_ionic_dipole(structure, zval_dict) for structure in structures ] polarization = Polarization(p_elecs, p_ions, structures) p_change = polarization.get_polarization_change().A1.tolist() p_norm = polarization.get_polarization_change_norm() polarization_max_spline_jumps = polarization.max_spline_jumps() same_branch = polarization.get_same_branch_polarization_data( convert_to_muC_per_cm2=True) raw_elecs, raw_ions = polarization.get_pelecs_and_pions() quanta = polarization.get_lattice_quanta(convert_to_muC_per_cm2=True) energy_trend = EnergyTrend(energies_per_atom) energy_max_spline_jumps = energy_trend.max_spline_jump() polarization_dict = {} def split_abc(var, var_name): d = {} for i, j in enumerate('abc'): d.update({var_name + "_{}".format(j): var[:, i].A1.tolist()}) return d # Add some sort of id for the structures? Like cid but more general? # polarization_dict.update({'cid': cid}) # General information polarization_dict.update( {'pretty_formula': structures[0].composition.reduced_formula}) polarization_dict.update({'wfid': wfid}) polarization_dict.update({'task_label_order': tasks}) # Polarization information polarization_dict.update({'polarization_change': p_change}) polarization_dict.update({'polarization_change_norm': p_norm}) polarization_dict.update( {'polarization_max_spline_jumps': polarization_max_spline_jumps}) polarization_dict.update( split_abc(same_branch, "same_branch_polarization")) polarization_dict.update( split_abc(raw_elecs, "raw_electron_polarization")) polarization_dict.update( split_abc(raw_ions, "raw_electron_polarization")) polarization_dict.update(split_abc(quanta, "polarization_quanta")) polarization_dict.update({"zval_dict": zval_dict}) # Energy information polarization_dict.update( {'energy_per_atom_max_spline_jumps': energy_max_spline_jumps}) polarization_dict.update({"energies": energies}) polarization_dict.update({"energies_per_atom": energies_per_atom}) polarization_dict.update({'outcars': outcars}) polarization_dict.update({"structures": structure_dicts}) # Write all the info to db. coll = vaspdb.db["polarization_tasks"] coll.insert_one(polarization_dict)
def test_get_structure_type_for_0D_material(self): os.chdir(ROOT) structure = Structure.from_file('POSCAR_O2') test_type = get_structure_type(structure) self.assertEqual(test_type, 'molecular')
def run_task(self, fw_spec): from pymatgen.analysis.eos import EOS eos = self.get("eos", "vinet") tag = self["tag"] db_file = env_chk(self.get("db_file"), fw_spec) summary_dict = {"eos": eos} to_db = self.get("to_db", True) # collect and store task_id of all related tasks to make unique links with "tasks" collection all_task_ids = [] mmdb = VaspCalcDb.from_db_file(db_file, admin=True) # get the optimized structure d = mmdb.collection.find_one( {"task_label": "{} structure optimization".format(tag)}) all_task_ids.append(d["task_id"]) structure = Structure.from_dict( d["calcs_reversed"][-1]["output"]['structure']) summary_dict["structure"] = structure.as_dict() summary_dict["formula_pretty"] = structure.composition.reduced_formula # get the data(energy, volume, force constant) from the deformation runs docs = mmdb.collection.find({ "task_label": { "$regex": "{} bulk_modulus*".format(tag) }, "formula_pretty": structure.composition.reduced_formula }) energies = [] volumes = [] for d in docs: s = Structure.from_dict( d["calcs_reversed"][-1]["output"]['structure']) energies.append(d["calcs_reversed"][-1]["output"]['energy']) volumes.append(s.volume) all_task_ids.append(d["task_id"]) summary_dict["energies"] = energies summary_dict["volumes"] = volumes summary_dict["all_task_ids"] = all_task_ids # fit the equation of state eos = EOS(eos) eos_fit = eos.fit(volumes, energies) summary_dict["bulk_modulus"] = eos_fit.b0_GPa # TODO: find a better way for passing tags of the entire workflow to db - albalu if fw_spec.get("tags", None): summary_dict["tags"] = fw_spec["tags"] summary_dict["results"] = dict(eos_fit.results) summary_dict["created_at"] = datetime.utcnow() # db_file itself is required but the user can choose to pass the results to db or not if to_db: mmdb.collection = mmdb.db["eos"] mmdb.collection.insert_one(summary_dict) else: with open("bulk_modulus.json", "w") as f: f.write(json.dumps(summary_dict, default=DATETIME_HANDLER)) # TODO: @matk86 - there needs to be a builder to put it into materials collection... -computron logger.info("Bulk modulus calculation complete.")
def test_get_structure_type_for_layered_material(self): os.chdir(ROOT) structure = Structure.from_file('POSCAR_FeCl2') test_type = get_structure_type(structure) self.assertEqual(test_type, 'layered')
from pymatgen import Structure from pymatgen.core.surface import SlabGenerator structure = Structure.from_file('POSCAR_conv') structure.add_oxidation_state_by_element({"Ca": 2, "Bi": -3, "O": -2}) #structure.add_oxidation_state_by_guess() # These are distances in Angstroms dist = [10, 15, 20, 25, 30] # We iterate through the distances twice, once for vac, once for slab for vac in dist: for thickness in dist: slabgen = SlabGenerator(structure, miller_index=(0, 0, 1), min_slab_size=thickness, min_vacuum_size=vac, lll_reduce=True) slabs = slabgen.get_slabs() dipole_free_slabs = [] for slab in slabs: if not slab.is_polar(): dipole_free_slabs.append(slab) slab = dipole_free_slabs[0] # <-- put a number in here! slab.to(fmt='poscar', filename='slab_{}_{}.vasp'.format(thickness, vac))
def get_elastic_analysis(opt_task, defo_tasks): """ Performs the analysis of opt_tasks and defo_tasks necessary for an elastic analysis Args: opt_task: task doc corresponding to optimization defo_tasks: task_doc corresponding to deformations Returns: elastic document with fitted elastic tensor and analysis """ elastic_doc = {"warnings": []} opt_struct = Structure.from_dict(opt_task['output']['structure']) d_structs = [ Structure.from_dict(d['output']['structure']) for d in defo_tasks ] defos = [ calculate_deformation(opt_struct, def_structure) for def_structure in d_structs ] # Warning if deformation is not equivalent to stored deformation stored_defos = [d['transmuter']['transformation_params'][0]\ ['deformation'] for d in defo_tasks] if not np.allclose(defos, stored_defos, atol=1e-5): wmsg = "Inequivalent stored and calc. deformations." logger.warning(wmsg) elastic_doc["warnings"].append(wmsg) # Collect all fitting data and task ids defos = [Deformation(d) for d in defos] strains = [d.green_lagrange_strain for d in defos] vasp_stresses = [d['output']['stress'] for d in defo_tasks] cauchy_stresses = [-0.1 * Stress(s) for s in vasp_stresses] pk_stresses = [ Stress(s.piola_kirchoff_2(d)) for s, d in zip(cauchy_stresses, defos) ] defo_task_ids = [d['task_id'] for d in defo_tasks] # Determine whether data is sufficient to fit tensor # If raw data is insufficient but can be symmetrically transformed # to provide a sufficient set, use the expanded set with appropriate # symmetry transformations, fstresses/strains are "fitting # strains" below. vstrains = [s.voigt for s in strains] if np.linalg.matrix_rank(vstrains) < 6: symmops = SpacegroupAnalyzer(opt_struct).get_symmetry_operations() fstrains = [[s.transform(symmop) for symmop in symmops] for s in strains] fstrains = list(chain.from_iterable(fstrains)) vfstrains = [s.voigt for s in fstrains] if not np.linalg.matrix_rank(vfstrains) == 6: logger.warning("Insufficient data to form SOEC") elastic_doc['warnings'].append("insufficient strains") return None else: fstresses = [[s.transform(symmop) for symmop in symmops] for s in pk_stresses] fstresses = list(chain.from_iterable(fstresses)) else: fstrains = strains fstresses = pk_stresses with warnings.catch_warnings(): warnings.simplefilter('ignore') if len(cauchy_stresses) == 24: elastic_doc['legacy_fit'] = legacy_fit(strains, cauchy_stresses) et_raw = ElasticTensor.from_pseudoinverse(fstrains, fstresses) et = et_raw.voigt_symmetrized.convert_to_ieee(opt_struct) defo_tasks = sorted(defo_tasks, key=lambda x: x['completed_at']) vasp_input = opt_task['input'] vasp_input.pop('structure') elastic_doc.update({ "deformation_task_ids": defo_task_ids, "optimization_task_id": opt_task['task_id'], "pk_stresses": pk_stresses, "cauchy_stresses": cauchy_stresses, "strains": strains, "deformations": defos, "elastic_tensor": et.voigt, "elastic_tensor_raw": et_raw.voigt, "optimized_structure": opt_struct, "completed_at": defo_tasks[-1]['completed_at'], "optimization_input": vasp_input }) # Process input elastic_doc['warnings'] = get_warnings(et, opt_struct) or None #TODO: process MPWorks metadata? #TODO: higher order #TODO: add some of the relevant DFT params, kpoints elastic_doc['state'] = "filter_failed" if elastic_doc['warnings']\ else "successful" return elastic_doc
def run_task(self, fw_spec): # handle arguments and database setup db_file = env_chk(self.get("db_file"), fw_spec) tag = self["tag"] vasp_db = VaspCalcDb.from_db_file(db_file, admin=True) # get the energies, volumes and DOS objects by searching for the tag static_calculations = vasp_db.collection.find( {'$and': [{ 'metadata.tag': tag }, { 'adopted': True }]}) energies = [] volumes = [] dos_objs = [] # pymatgen.electronic_structure.dos.Dos objects structure = None # single Structure for QHA calculation for calc in static_calculations: energies.append(calc['output']['energy']) volumes.append(calc['output']['structure']['lattice']['volume']) dos_objs.append(vasp_db.get_dos(calc['task_id'])) # get a Structure. We only need one for the masses and number of atoms in the unit cell. if structure is None: structure = Structure.from_dict(calc['output']['structure']) # sort everything in volume order # note that we are doing volume last because it is the thing we are sorting by! energies = sort_x_by_y(energies, volumes) dos_objs = sort_x_by_y(dos_objs, volumes) volumes = sorted(volumes) qha_result = {} qha_result['structure'] = structure.as_dict() qha_result['formula_pretty'] = structure.composition.reduced_formula qha_result['elements'] = sorted( [el.name for el in structure.composition.elements]) qha_result['metadata'] = self.get('metadata', {}) qha_result['has_phonon'] = self['phonon'] poisson = self.get('poisson', 0.363615) bp2gru = self.get('bp2gru', 1) # phonon properties if self['phonon']: # get the vibrational properties from the FW spec phonon_calculations = list(vasp_db.db['phonon'].find( {'$and': [{ 'metadata.tag': tag }, { 'adopted': True }]})) vol_vol = [ calc['volume'] for calc in phonon_calculations ] # these are just used for sorting and will be thrown away vol_f_vib = [calc['F_vib'] for calc in phonon_calculations] # sort them order of the unit cell volumes vol_f_vib = sort_x_by_y(vol_f_vib, vol_vol) f_vib = np.vstack(vol_f_vib) qha = Quasiharmonic(energies, volumes, structure, dos_objects=dos_objs, F_vib=f_vib, t_min=self['t_min'], t_max=self['t_max'], t_step=self['t_step'], poisson=poisson, bp2gru=bp2gru) qha_result['phonon'] = qha.get_summary_dict() qha_result['phonon']['temperatures'] = qha_result['phonon'][ 'temperatures'].tolist() # calculate the Debye model results no matter what qha_debye = Quasiharmonic(energies, volumes, structure, dos_objects=dos_objs, F_vib=None, t_min=self['t_min'], t_max=self['t_max'], t_step=self['t_step'], poisson=poisson, bp2gru=bp2gru) # fit 0 K EOS for good measure eos = Vinet(volumes, energies) eos.fit() errors = eos.func(volumes) - energies sum_square_error = float(np.sum(np.square(errors))) eos_res = {} eos_res['b0_GPa'] = float(eos.b0_GPa) eos_res['b0'] = float(eos.b0) eos_res['b1'] = float(eos.b1) eos_res['eq_volume'] = float(eos.v0) eos_res['eq_energy'] = float(eos.e0) eos_res['energies'] = energies eos_res['volumes'] = volumes eos_res['name'] = 'Vinet' eos_res['error'] = {} eos_res['error']['difference'] = errors.tolist( ) # volume by volume differences eos_res['error']['sum_square_error'] = sum_square_error qha_result['eos'] = eos_res qha_result['debye'] = qha_debye.get_summary_dict() qha_result['debye']['poisson'] = poisson qha_result['debye']['bp2gru'] = bp2gru qha_result['debye']['temperatures'] = qha_result['debye'][ 'temperatures'].tolist() qha_result['version_atomate'] = atomate_ver qha_result['version_dfttk'] = dfttk_ver volumes_false = [] energies_false = [] static_falses = vasp_db.collection.find( {'$and': [{ 'metadata.tag': tag }, { 'adopted': False }]}) for static_false in static_falses: volumes_false.append( static_false['output']['structure']['lattice']['volume']) energies_false.append(static_false['output']['energy']) qha_result['Volumes_fitting_false'] = volumes_false qha_result['Energies_fitting_false'] = energies_false print('Volumes_fitting_false : %s' % volumes_false) print('Energies_fitting_false: %s' % energies_false) # write to JSON for debugging purposes import json with open('qha_summary.json', 'w') as fp: json.dump(qha_result, fp) if self['phonon']: vasp_db.db['qha_phonon'].insert_one(qha_result) else: vasp_db.db['qha'].insert_one(qha_result)
def run_task(self, fw_spec): additional_fields = self.get("additional_fields", {}) # pass the additional_fields first to avoid overriding BoltztrapAnalyzer items d = additional_fields.copy() btrap_dir = os.path.join(os.getcwd(), "boltztrap") d["boltztrap_dir"] = btrap_dir bta = BoltztrapAnalyzer.from_files(btrap_dir) d.update(bta.as_dict()) d["scissor"] = bta.intrans["scissor"] # trim the output for x in [ 'cond', 'seebeck', 'kappa', 'hall', 'mu_steps', 'mu_doping', 'carrier_conc' ]: del d[x] if not self.get("hall_doping"): del d["hall_doping"] bandstructure_dir = os.getcwd() d["bandstructure_dir"] = bandstructure_dir # add the structure v, o = get_vasprun_outcar(bandstructure_dir, parse_eigen=False, parse_dos=False) structure = v.final_structure d["structure"] = structure.as_dict() d["formula_pretty"] = structure.composition.reduced_formula d.update(get_meta_from_structure(structure)) # add the spacegroup sg = SpacegroupAnalyzer(Structure.from_dict(d["structure"]), 0.1) d["spacegroup"] = { "symbol": sg.get_space_group_symbol(), "number": sg.get_space_group_number(), "point_group": sg.get_point_group_symbol(), "source": "spglib", "crystal_system": sg.get_crystal_system(), "hall": sg.get_hall() } d["created_at"] = datetime.utcnow() db_file = env_chk(self.get('db_file'), fw_spec) if not db_file: del d["dos"] with open(os.path.join(btrap_dir, "boltztrap.json"), "w") as f: f.write(json.dumps(d, default=DATETIME_HANDLER)) else: mmdb = VaspCalcDb.from_db_file(db_file, admin=True) # dos gets inserted into GridFS dos = json.dumps(d["dos"], cls=MontyEncoder) fsid, compression = mmdb.insert_gridfs( dos, collection="dos_boltztrap_fs", compress=True) d["dos_boltztrap_fs_id"] = fsid del d["dos"] mmdb.db.boltztrap.insert(d)
for struct, fname in zip(structs, fnames): filename = NAME + '_' + fname.lower() + '.' + fmt if "POSCAR" in fname and flag: # it is a bug in pymatgen print("The string POSCAR in filename will be replaced by poscar") flag = False if fmt == 'lammps': system = structure2system(struct) system.to_lammps_lmp(filename) continue try: print("Write {0:20s} {1:s}".format(fname, 'Pymatgen:Struture')) struct.to(fmt, filename) except: print("Write {0:20s} {1:s} ".format(fname, 'Atoms:Atoms')) atoms = pmg2ase(struct) write(filename) return True if __name__ == "__main__": from pymatgen import Structure structure = Structure.from_file('POSCAR') system = structure2system(structure) print(system) print('--') covert_operation([structure], ["POSCAR"], 'lammps')
modify_incar_params = { 'Full relax': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'PreStatic': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'PS2': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, 'static': {'incar_update': {"LAECHG":False,"LCHARG":False,"LWAVE":False}}, """ modify_incar_params = {} #dict, dict of class ModifyKpoints with keywords in Workflow name, similar with modify_incar_params modify_kpoints_params = {} #bool, print(True) or not(False) some informations, used for debug verbose = False ###################### DO NOT CHANGE THE FOLLOWING LINES ############################## from pymatgen import MPRester, Structure from dfttk.wflows import get_wf_gibbs structure = Structure.from_file(TEMPLATE_STRUCTURE_FILENAME) if magmom: structure.add_site_property('magmom', magmom) if not db_file: from fireworks.fw_config import config_to_dict from monty.serialization import loadfn db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] wf = get_wf_gibbs(structure, num_deformations=num_deformations, deformation_fraction=deformation_fraction, phonon=phonon, phonon_supercell_matrix=phonon_supercell_matrix, t_min=t_min,