def test_requires_hubbard(self): compat = MaterialsProjectCompatibility() self.assertTrue(compat.requires_hubbard("Fe2O3")) self.assertTrue(compat.requires_hubbard("FeSO4")) self.assertFalse(compat.requires_hubbard("FeS2")) self.assertFalse(compat.requires_hubbard("Li2O")) self.assertTrue(compat.requires_hubbard("FeOF"))
def setUp(self): self.entry1 = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.entry2 = ComputedEntry( 'Fe3O4', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.entry3 = ComputedEntry( 'FeO', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 4.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.compat = MaterialsProjectCompatibility(check_potcar_hash=False) self.ggacompat = MaterialsProjectCompatibility("GGA", check_potcar_hash=False)
def prepare_entry(structure_type, tot_e, species): """ Prepare entries from total energy and species. Args: structure_type(str): "garnet" or "perovskite" tot_e (float): total energy in eV/f.u. species (dict): species in dictionary. Returns: ce (ComputedEntry) """ formula = spe2form(structure_type, species) composition = Composition(formula) elements = [el.name for el in composition] potcars = ["pbe %s" % CONFIG['POTCAR'][el] for el in elements] parameters = {"potcar_symbols": list(potcars), "oxide_type": 'oxide'} for el in elements: if el in LDAUU: parameters.update({"hubbards": {el: LDAUU[el]}}) ce = ComputedEntry(composition=composition, energy=0, parameters=parameters) ce.uncorrected_energy = tot_e compat = MaterialsProjectCompatibility() ce = compat.process_entry(ce) # Correction added return ce
def test_get_stability(self): entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) modified_entries = [] for entry in entries: # Create modified entries with energies that are 0.01eV higher # than the corresponding entries. if entry.composition.reduced_formula == "Fe2O3": modified_entries.append( ComputedEntry(entry.composition, entry.uncorrected_energy + 0.01, parameters=entry.parameters, entry_id="mod_{}".format(entry.entry_id))) rest_ehulls = self.rester.get_stability(modified_entries) all_entries = entries + modified_entries compat = MaterialsProjectCompatibility() all_entries = compat.process_entries(all_entries) pd = PhaseDiagram(all_entries) for e in all_entries: if str(e.entry_id).startswith("mod"): for d in rest_ehulls: if d["entry_id"] == e.entry_id: data = d break self.assertAlmostEqual(pd.get_e_above_hull(e), data["e_above_hull"])
def get_mp_phase_graph(): mpr = check_apikey() compat = MaterialsProjectCompatibility() print("input the elements list") wait_sep() in_str = wait() elements = in_str.split() web = "materials.org" proc_str = "Reading Data From " + web + " ..." step_count = 1 procs(proc_str, step_count, sp='-->>') unprocessed_entries = mpr.get_entries_in_chemsys(elements) processed_entries = compat.process_entries(unprocessed_entries) pd = PhaseDiagram(processed_entries) pdp = PDPlotter(pd, show_unstable=True) try: pdp.show() except: pass finally: step_count += 1 filename = 'phase' + '-'.join(elements) + '.png' proc_str = "Writing Data to " + filename + " File..." procs(proc_str, step_count, sp='-->>') pdp.write_image(filename) return True
def get_decomposed_entries(structure_type, species, oxides_table_path): """ Get decomposed entries for mix types Args:one species (dict): species in dictionary. structure_type(str): garnet or perovskite Returns: decompose entries(list): list of entries prepared from unmix garnets/perovskite decomposed from input mix garnet/perovskite """ def decomposed(specie_complex): """Decompose those have sub-dict to individual dict objects.""" for site, specie in specie_complex.items(): spe_copy = specie_complex.copy() if len(specie) > 1: for spe, amt in specie.items(): spe_copy[site] = {spe: 1} yield spe_copy decompose_entries = [] model, scaler, graph = load_model_and_scaler(structure_type, "unmix") std_formula = STD_FORMULA[structure_type] for unmix_species in decomposed(species): charge = sum([ spe.oxi_state * amt * SITE_INFO[structure_type][site]["num_atoms"] for site in SITE_INFO[structure_type].keys() for spe, amt in unmix_species[site].items() ]) if not abs(charge - 2 * std_formula['O']) < 0.1: continue formula = spe2form(structure_type, unmix_species) calc_entries = [entry for entry in CALC_ENTRIES[structure_type] if \ entry.name == Composition(formula).reduced_formula] if calc_entries: for entry in calc_entries: decompose_entries.append(entry) else: descriptors = get_descriptor(structure_type, unmix_species) with graph.as_default(): form_e = get_form_e(descriptors, model, scaler) # tot_e = get_tote(form_e * std_formula.num_atoms, unmix_species) tot_e = get_tote(structure_type, form_e * std_formula.num_atoms, unmix_species, oxides_table_path) entry = prepare_entry(structure_type, tot_e, unmix_species) compat = MaterialsProjectCompatibility() entry = compat.process_entry(entry) decompose_entries.append(entry) return decompose_entries
def get_entries(self, chemsys_formula_id, compatible_only=True, inc_structure=None): """ Get a list of ComputedEntries or ComputedStructureEntries corresponding to a chemical system, formula, or materials_id. Args: chemsys_formula_id (str): A chemical system (e.g., Li-Fe-O), or formula (e.g., Fe2O3) or materials_id (e.g., mp-1234). compatible_only (bool): Whether to return only "compatible" entries. Compatible entries are entries that have been processed using the MaterialsProjectCompatibility class, which performs adjustments to allow mixing of GGA and GGA+U calculations for more accurate phase diagrams and reaction energies. inc_structure (str): If None, entries returned are ComputedEntries. If inc_structure="final", ComputedStructureEntries with final structures are returned. Otherwise, ComputedStructureEntries with initial structures are returned. Returns: List of ComputedEntry or ComputedStructureEntry objects. """ # TODO: This is a very hackish way of doing this. It should be fixed # on the REST end. if compatible_only: data = self.get_data(chemsys_formula_id, prop="entry") entries = [d["entry"] for d in data] if inc_structure: for i, e in enumerate(entries): s = self.get_structure_by_material_id( e.entry_id, inc_structure == "final") entries[i] = ComputedStructureEntry( s, e.energy, e.correction, e.parameters, e.data, e.entry_id) entries = MaterialsProjectCompatibility().process_entries(entries) else: entries = [] for d in self.get_data(chemsys_formula_id, prop="task_ids"): for i in d["task_ids"]: e = self.get_task_data(i, prop="entry") e = e[0]["entry"] if inc_structure: s = self.get_task_data( i, prop="structure")[0]["structure"] e = ComputedStructureEntry(s, e.energy, e.correction, e.parameters, e.data, e.entry_id) entries.append(e) return entries
def get_entries(self, chemsys_formula_id, compatible_only=True, inc_structure=None): """ Get a list of ComputedEntries or ComputedStructureEntries corresponding to a chemical system, formula, or materials_id. Args: chemsys_formula_id (str): A chemical system (e.g., Li-Fe-O), or formula (e.g., Fe2O3) or materials_id (e.g., mp-1234). compatible_only (bool): Whether to return only "compatible" entries. Compatible entries are entries that have been processed using the MaterialsProjectCompatibility class, which performs adjustments to allow mixing of GGA and GGA+U calculations for more accurate phase diagrams and reaction energies. inc_structure (str): If None, entries returned are ComputedEntries. If inc_structure="final", ComputedStructureEntries with final structures are returned. Otherwise, ComputedStructureEntries with initial structures are returned. Returns: List of ComputedEntry or ComputedStructureEntry objects. """ # TODO: This is a very hackish way of doing this. It should be fixed # on the REST end. if compatible_only: data = self.get_data(chemsys_formula_id, prop="entry") entries = [d["entry"] for d in data] if inc_structure: for i, e in enumerate(entries): s = self.get_structure_by_material_id( e.entry_id, inc_structure == "final") entries[i] = ComputedStructureEntry( s, e.energy, e.correction, e.parameters, e.data, e.entry_id) entries = MaterialsProjectCompatibility().process_entries(entries) else: entries = [] for d in self.get_data(chemsys_formula_id, prop="task_ids"): for i in d["task_ids"]: e = self.get_task_data(i, prop="entry") e = e[0]["entry"] if inc_structure: s = self.get_task_data(i, prop="structure")[0]["structure"] e = ComputedStructureEntry( s, e.energy, e.correction, e.parameters, e.data, e.entry_id) entries.append(e) return entries
def test_get_explanation_dict(self): compat = MaterialsProjectCompatibility(check_potcar_hash=False) entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel': 'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': "7a25bc5b9a5393f46600a4939d357982"}]}) d = compat.get_explanation_dict(entry) self.assertEqual('MPRelaxSet Potcar Correction', d["corrections"][0][ "name"])
def getEhull(new=''): drone = VaspToComputedEntryDrone() queen = BorgQueen(drone, './', 4) entriesorig = queen.get_data() queen.load_data( os.path.join(os.path.dirname(__file__), '../ML/data/missingels.json')) entriesextra = queen.get_data() if new != '': compat = MaterialsProjectCompatibility(check_potcar=False) entriesorig = compat.process_entries(entriesorig) for entry in entriesorig: name = entry.name line = re.findall('[A-Z][^A-Z]*', name.replace('(', '').replace(')', '')) searchset = set(re.sub('\d', ' ', ' '.join(line)).split()) entries = filter( lambda e: set( re.sub('\d', ' ', str(e.composition).replace(' ', '')).split()) == searchset, entriesorig) entriesextra = filter( lambda e: set( re.sub('\d', ' ', str(e.composition).replace(' ', '')).split()) & searchset, entriesextra) a = MPRester("s2vUo6mzETOHLdbu") all_entries = a.get_entries_in_chemsys( set(searchset)) + list(entries) + list(entriesextra) pd = PhaseDiagram(all_entries) #,None for e in pd.stable_entries: if e.entry_id == None: reaction = pd.get_equilibrium_reaction_energy(e) return str(reaction) + ' None' for e in pd.unstable_entries: decomp, e_above_hull = pd.get_decomp_and_e_above_hull(e) pretty_decomp = [("{}:{}".format(k.composition.reduced_formula, k.entry_id), round(v, 2)) for k, v in decomp.items()] if e.entry_id == None: return str(e_above_hull) + ' ' + str(pretty_decomp)
def get_ehull(structure_type, tot_e, species, unmix_entries=None, all_entries=None, debug=False): """ Get Ehull predicted under given total energy and species. The composition can be either given by the species dict(for garnet only) or a formula. Args: tot_e (float): total energy, the unit is in accordance with given composition. species (dict): species in dictionary. unmix_entries (list): additional list of unmix entries. Returns: ehull (float): energy above hull. """ formula = spe2form(structure_type, species) composition = Composition(formula) unmix_entries = [] if unmix_entries is None else unmix_entries if not all_entries: all_entries = m.get_entries_in_chemsys([el.name for el in composition], inc_structure=True) all_entries = filter_entries(structure_type, all_entries, species) all_calc_entries = [e for e in CALC_ENTRIES[structure_type] if set(e.composition).issubset(set(composition)) \ and e.name != composition.reduced_formula] if all_calc_entries: all_entries = all_entries + all_calc_entries compat = MaterialsProjectCompatibility() all_entries = compat.process_entries(all_entries) if not all_entries: raise ValueError("Incomplete") entry = prepare_entry(structure_type, tot_e, species) if debug: return entry, all_entries phase_diagram = PhaseDiagram(all_entries + [entry] + unmix_entries) return phase_diagram.get_decomp_and_e_above_hull(entry)
def __init__(self, materials, thermo, query=None, compatibility=None, **kwargs): """ Calculates thermodynamic quantities for materials from phase diagram constructions Args: materials (Store): Store of materials documents thermo (Store): Store of thermodynamic data such as formation energy and decomposition pathway query (dict): dictionary to limit materials to be analyzed compatibility (PymatgenCompatability): Compatability module to ensure energies are compatible """ self.materials = materials self.thermo = thermo self.query = query if query else {} self.compatibility = (compatibility if compatibility else MaterialsProjectCompatibility("Advanced")) self.completed_tasks = set() self.entries_cache = defaultdict(list) super().__init__(sources=[materials], targets=[thermo], **kwargs)
def __init__(self, materials, thermo, query={}, compatibility=MaterialsProjectCompatibility('Advanced'), **kwargs): """ Calculates thermodynamic quantities for materials from phase diagram constructions Args: materials (Store): Store of materials documents thermo (Store): Store of thermodynamic data such as formation energy and decomposition pathway query (dict): dictionary to limit materials to be analyzed compatibility (PymatgenCompatability): Compatability module to ensure energies are compatible """ self.materials = materials self.thermo = thermo self.query = query self.__compat = compatibility self.__logger = logging.getLogger(__name__) self.__logger.addHandler(logging.NullHandler()) super().__init__(sources=[materials], targets=[thermo], **kwargs)
def get_entry(doc): """ Helper function to get a processed computed entry from the document Args: doc ({}): doc from which to get the entry Returns: (ComputedEntry) computed entry derived from doc """ params = [ "run_type", "is_hubbard", "pseudo_potential", "hubbards", "potcar_symbols", "oxide_type" ] doc["potcar_symbols"] = [ "%s %s" % (doc["pseudo_potential"]["functional"], l) for l in doc["pseudo_potential"]["labels"] ] entry = ComputedEntry(doc["unit_cell_formula"], doc["final_energy"], parameters={k: doc[k] for k in params}, data={"oxide_type": doc['oxide_type']}, entry_id=doc["task_id"]) entry = MaterialsProjectCompatibility().process_entries([entry])[0] return entry
def __init__(self, materials, electro, working_ion, query=None, compatibility=MaterialsProjectCompatibility("Advanced"), **kwargs): """ Calculates physical parameters of battery materials the battery entries using groups of ComputedStructureEntry and the entry for the most stable version of the working_ion in the system Args: materials (Store): Store of materials documents that contains the structures electro (Store): Store of insertion electrodes data such as voltage and capacity query (dict): dictionary to limit materials to be analyzed --- only applied to the materials when we need to group structures the phase diagram is still constructed with the entire set compatibility (PymatgenCompatability): Compatability module to ensure energies are compatible """ self.sm = StructureMatcher(comparator=ElementComparator(), primitive_cell=False) self.materials = materials self.electro = electro self.working_ion = working_ion self.query = query if query else {} self.compatibility = compatibility self.completed_tasks = set() self.working_ion_entry = None super().__init__(sources=[materials], targets=[electro], **kwargs)
def build_corrected_pd(entries): """build_corrected_pd Builds a PD with entries using Mat.Proj. compatibility. :param entries: List of ComputedEntry objects :return: A Phase diagram object """ corrected = MaterialsProjectCompatibility().process_entries(entries) return PhaseDiagram(corrected)
def get_pd(self): """ get the phase diagram object for this compound Returns: phase diagram, entry """ #make MP compatible entry from vasprun entry = self.vasprun.get_computed_entry() compat = MaterialsProjectCompatibility() entry = compat.process_entry(entry) el = [specie.symbol for specie in entry.composition.keys()] with MPRester(api_key=API_KEY) as mpr: entries = mpr.get_entries_in_chemsys(el) entries.append(entry) pd = PhaseDiagram(entries) return pd, entry
def get_pd(self): """ get the phase diagram object Returns: pd: the phase diagram object entry: entry contained in vasprun entries: all entries used to construct the phase diagram """ entry = self.vasprun.get_computed_entry() compat = MaterialsProjectCompatibility() entry = compat.process_entry(entry) el = [specie.symbol for specie in entry.composition.keys()] with MPRester(api_key="64JmsIV32c8lUaxu") as mpr: entries = mpr.get_entries_in_chemsys(el) entries.append(entry) pd = PhaseDiagram(entries) return pd, entry, entries
def main(): """ Main function. """ # Read the calculation results into a ComputedEntry. entl = VaspToComputedEntryDrone().assimilate(sys.argv[1]) # Check if our local calculation is compatible with MP. if MaterialsProjectCompatibility().process_entry(entl) is None: print("Calculation not compatible with MP.") sys.exit(0) # Get other entries sharing a chemical system with the results. chemsys = [ele for ele in entl.composition.as_dict()] with MPRester() as mpr: chemsys_entries = mpr.get_entries_in_chemsys(chemsys) # Append our local calculation to the list of entries. chemsys_entries.append(entl) # Process the entries. p_e = MaterialsProjectCompatibility().process_entries(chemsys_entries) # Build a phase diagram and an analyzer for it. p_d = PhaseDiagram(p_e) pda = PDAnalyzer(p_d) # Scan stable entries for our calculation. for ent in p_d.stable_entries: if ent.entry_id is None: print(str(ent.composition.reduced_formula) + " 0.0") sys.exit(0) # Scan unstable entries for our calculation and print decomposition. for ent in p_d.unstable_entries: if ent.entry_id is None: dco, ehull = pda.get_decomp_and_e_above_hull(ent) pretty_dc = [("{}:{}".format(k.composition.reduced_formula, k.entry_id), round(v, 2)) for k, v in dco.items()] print( str(ent.composition.reduced_formula) + " %.3f" % ehull + " " + str(pretty_dc))
def test_get_corrections_dict(self): compat = MaterialsProjectCompatibility() ggacompat = MaterialsProjectCompatibility("GGA") #Correct parameters entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE O 08Apr2002']}) c = compat.get_corrections_dict(entry) self.assertAlmostEqual(c["MP Gas Correction"], -2.10687) self.assertAlmostEqual(c["MP Advanced Correction"], -5.466) entry.parameters["is_hubbard"] = False del entry.parameters["hubbards"] c = ggacompat.get_corrections_dict(entry) self.assertNotIn("MP Advanced Correction", c)
def test_get_corrections_dict(self): compat = MaterialsProjectCompatibility(check_potcar_hash=False) ggacompat = MaterialsProjectCompatibility("GGA", check_potcar_hash=False) #Correct parameters entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': "7a25bc5b9a5393f46600a4939d357982"}]}) c = compat.get_corrections_dict(entry) self.assertAlmostEqual(c["MP Anion Correction"], -2.10687) self.assertAlmostEqual(c["MP Advanced Correction"], -5.466) entry.parameters["is_hubbard"] = False del entry.parameters["hubbards"] c = ggacompat.get_corrections_dict(entry) self.assertNotIn("MP Advanced Correction", c)
def test_get_corrections_dict(self): compat = MaterialsProjectCompatibility() ggacompat = MaterialsProjectCompatibility("GGA") #Correct parameters entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={ 'is_hubbard': True, 'hubbards': { 'Fe': 5.3, 'O': 0 }, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE O 08Apr2002'] }) c = compat.get_corrections_dict(entry) self.assertAlmostEqual(c["MP Gas Correction"], -2.10687) self.assertAlmostEqual(c["MP Advanced Correction"], -5.466) entry.parameters["is_hubbard"] = False del entry.parameters["hubbards"] c = ggacompat.get_corrections_dict(entry) self.assertNotIn("MP Advanced Correction", c)
def setUp(self): self.entry1 = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.entry_sulfide = ComputedEntry( 'FeS', -1, 0.0, parameters={'is_hubbard': False, 'run_type': 'GGA', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE S 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.entry2 = ComputedEntry( 'Fe3O4', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.entry3 = ComputedEntry( 'FeO', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 4.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.compat = MaterialsProjectCompatibility(check_potcar_hash=False) self.ggacompat = MaterialsProjectCompatibility("GGA", check_potcar_hash=False) warnings.simplefilter("ignore")
def get_pourbaix_entries( self, chemsys, solid_compat=MaterialsProjectCompatibility() ): """ A helper function to get all entries necessary to generate a pourbaix diagram from the rest interface. Args: chemsys ([str]): A list of elements comprising the chemical system, e.g. ['Li', 'Fe'] solid_compat: Compatiblity scheme used to pre-process solid DFT energies prior to applying aqueous energy adjustments. Default: MaterialsProjectCompatibility(). """ raise NotImplementedError
def calculate_phase_stability(args): #This initializes the REST adaptor. a = MPRester(args.api_key) drone = VaspToComputedEntryDrone() entry = drone.assimilate(args.directory) compat = MaterialsProjectCompatibility() entry = compat.process_entry(entry) if not entry: print "Calculation parameters are not consistent with Materials " + \ "Project parameters." sys.exit() syms = [el.symbol for el in entry.composition.elements] #This gets all entries belonging to the relevant system. entries = a.get_entries_in_chemsys(syms) entries.append(entry) #Process entries with Materials Project compatibility. entries = compat.process_entries(entries) print [e.composition.reduced_formula for e in entries]
def build_complete_pd(f, calc_list): """build_complete_pd Builds a PD including appropriate local calcs. :param f: Formula for which we seek to construct a PD. :param calc_list: A list of folders containing local calculations. :return: A Phasediagram object. """ entries = pd_tools.get_pruned_chemsys(f) csys = [el for el in Composition(f).as_dict()] for d in calc_list: data_dir = root_dir + "/" + d + "/relax_final" if set(eles_in_calc(data_dir)).issubset(set(csys)): entries.append(create_entry(data_dir)) entries_proc = MaterialsProjectCompatibility().process_entries(entries) return PhaseDiagram(entries_proc)
def get_entries(self, chemsys_formula_id, compatible_only=True, inc_structure=None): """ Get a list of ComputedEntries or ComputedStructureEntries corresponding to a chemical system, formula, or materials_id. Args: chemsys_formula_id: A chemical system (e.g., Li-Fe-O), or formula (e.g., Fe2O3) or materials_id (e.g., mp-1234). compatible_only: Whether to return only "compatible" entries. Compatible entries are entries that have been processed using the MaterialsProjectCompatibility class, which performs adjustments to allow mixing of GGA and GGA+U calculations for more accurate phase diagrams and reaction energies. inc_structure: If None, entries returned are ComputedEntries. If inc_structure="final", ComputedStructureEntries with final structures are returned. Otherwise, ComputedStructureEntries with initial structures are returned. Returns: List of ComputedEntry or ComputedStructureEntry objects. """ data = self.get_data(chemsys_formula_id, prop="entry") entries = [d["entry"] for d in data] def make_struct_entry(entry): s = self.get_structure_by_material_id(entry.entry_id, inc_structure == "final") return ComputedStructureEntry(s, entry.energy, entry.correction, entry.parameters, entry.data, entry.entry_id) if inc_structure: entries = map(make_struct_entry, entries) if compatible_only: entries = MaterialsProjectCompatibility().process_entries(entries) return entries
def run_task(self, fw_spec): # import here to prevent import errors in bigger MPCollab # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ filename = get_slug( 'JOB--' + fw_spec['mpsnl'].structure.composition.reduced_formula + '--' + fw_spec['task_type']) with open(filename, 'w+') as f: f.write('') # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) props = {"calculations": 1, "task_id": 1, "state": 1, "pseudo_potential": 1, "run_type": 1, "is_hubbard": 1, "hubbards": 1, "unit_cell_formula": 1} m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: time.sleep(60) # only thing to think of is wait for DB insertion(?) m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: raise ValueError("Could not find task with dir_name: {}".format(block_part)) if m_task['state'] != 'successful': raise ValueError("Cannot run Boltztrap; parent job unsuccessful") nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output']['crystal'] bs = BandStructure.from_dict(bs_dict) print 'Band Structure found:', bool(bs) print nelect # run Boltztrap runner = BoltztrapRunner(bs, nelect) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) # 8/21/15 - Anubhav removed fs_id (also see line further below, ted['boltztrap_full_fs_id'] ...) # 8/21/15 - this is to save space in MongoDB, as well as non-use of full Boltztrap output (vs rerun) """ data = bta.as_dict() data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] del data['hall'] # remove because it is too large and not useful fs = gridfs.GridFS(tdb, "boltztrap_full_fs") btid = fs.put(json.dumps(jsanitize(data))) """ # now for the "sanitized" data ted = bta.as_dict() del ted['seebeck'] del ted['hall'] del ted['kappa'] del ted['cond'] # ted['boltztrap_full_fs_id'] = btid ted['snlgroup_id'] = fw_spec['snlgroup_id'] ted['run_tags'] = fw_spec['run_tags'] ted['snl'] = fw_spec['mpsnl'].as_dict() ted['dir_name_full'] = dir ted['dir_name'] = get_block_part(dir) ted['task_id'] = m_task['task_id'] ted['pf_doping'] = bta.get_power_factor(output='tensor', relaxation_time=self.TAU) ted['zt_doping'] = bta.get_zt(output='tensor', relaxation_time=self.TAU, kl=self.KAPPAL) ted['pf_eigs'] = self.get_eigs(ted, 'pf_doping') ted['pf_best'] = self.get_extreme(ted, 'pf_eigs') ted['pf_best_dope18'] = self.get_extreme(ted, 'pf_eigs', max_didx=3) ted['pf_best_dope19'] = self.get_extreme(ted, 'pf_eigs', max_didx=4) ted['zt_eigs'] = self.get_eigs(ted, 'zt_doping') ted['zt_best'] = self.get_extreme(ted, 'zt_eigs') ted['zt_best_dope18'] = self.get_extreme(ted, 'zt_eigs', max_didx=3) ted['zt_best_dope19'] = self.get_extreme(ted, 'zt_eigs', max_didx=4) ted['seebeck_eigs'] = self.get_eigs(ted, 'seebeck_doping') ted['seebeck_best'] = self.get_extreme(ted, 'seebeck_eigs') ted['seebeck_best_dope18'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=3) ted['seebeck_best_dope19'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=4) ted['cond_eigs'] = self.get_eigs(ted, 'cond_doping') ted['cond_best'] = self.get_extreme(ted, 'cond_eigs') ted['cond_best_dope18'] = self.get_extreme(ted, 'cond_eigs', max_didx=3) ted['cond_best_dope19'] = self.get_extreme(ted, 'cond_eigs', max_didx=4) ted['kappa_eigs'] = self.get_eigs(ted, 'kappa_doping') ted['kappa_best'] = self.get_extreme(ted, 'kappa_eigs', maximize=False) ted['kappa_best_dope18'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=3) ted['kappa_best_dope19'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=4) try: from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB bzspb = BoltzSPB(ted) maxpf_p = bzspb.get_maximum_power_factor('p', temperature=0, tau=1E-14, ZT=False, kappal=0.5,\ otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxpf_n = bzspb.get_maximum_power_factor('n', temperature=0, tau=1E-14, ZT=False, kappal=0.5,\ otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_p = bzspb.get_maximum_power_factor('p', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_n = bzspb.get_maximum_power_factor('n', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) ted['zt_best_finemesh'] = {'p': maxzt_p, 'n': maxzt_n} ted['pf_best_finemesh'] = {'p': maxpf_p, 'n': maxpf_n} except: import traceback traceback.print_exc() print 'COULD NOT GET FINE MESH DATA' # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = m_task["pseudo_potential"]["functional"] labels = m_task["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = {"run_type": m_task["run_type"], "is_hubbard": m_task["is_hubbard"], "hubbards": m_task["hubbards"], "potcar_symbols": symbols} entry = ComputedEntry(Composition(m_task["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=m_task["task_id"]) ted["is_compatible"] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility, task_id: {}'.format(m_task["task_id"]) ted["is_compatible"] = None tdb.boltztrap.insert(jsanitize(ted)) update_spec = {'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'].as_dict(), 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters')} return FWAction(update_spec=update_spec)
def get_decomposed_entries(structure_type, species): """ Get decomposed entries for mix types Args: structure_type(str): "garnet" or "perovskite" species (dict): species in dictionary. structure_type(str): garnet or perovskite Returns: decompose entries(list): list of entries prepared from unmix garnets/perovskite decomposed from input mix garnet/perovskite """ def decomposed(specie_complex): """Decompose those have sub-dict to individual dict objects.""" for site, specie in specie_complex.items(): spe_copy = specie_complex.copy() if len(specie) > 1: for spe, amt in specie.items(): spe_copy[site] = {spe: 1} yield spe_copy decompose_entries = [] model, scaler = load_model_and_scaler(structure_type, "unmix") std_formula = STD_FORMULA[structure_type] for unmix_species in decomposed(species): charge = sum([ spe.oxi_state * amt * SITE_INFO[structure_type][site]["num_atoms"] for site in SITE_INFO[structure_type].keys() for spe, amt in unmix_species[site].items() ]) if not abs(charge - 2 * std_formula['O']) < 0.1: continue formula = spe2form(structure_type, unmix_species) composition = Composition(formula) elements = [el.name for el in composition] chemsy = '-'.join(sorted(elements)) calc_entries = [] if CALC_ENTRIES[structure_type].get(chemsy): calc_entries = [entry for entry in CALC_ENTRIES[structure_type][chemsy] if \ entry.name == Composition(formula).reduced_formula] else: pass if calc_entries: decompose_entries.extend(calc_entries) else: cn_specific = True if structure_type == 'garnet' else False descriptors = get_descriptor(structure_type, unmix_species, cn_specific=cn_specific) form_e = get_form_e(descriptors, model, scaler) # tot_e = get_tote(form_e * std_formula.num_atoms, unmix_species) tot_e = get_tote(structure_type, form_e * std_formula.num_atoms, unmix_species) entry = prepare_entry(structure_type, tot_e, unmix_species) compat = MaterialsProjectCompatibility() entry = compat.process_entry(entry) decompose_entries.append(entry) return decompose_entries
def biased_hull(atomate_db, comp_list, anions=['N', 'O'], bias=[0]): with MPRester() as mpr: for pretty in comp_list: composition = Composition(pretty) composition = [str(i) for i in composition.elements] # anion_num = composition[2] # composition.pop() # composition.append(anions[0]) # composition.append(anions[1]) #First, build the phase diagram and hull orig_entries = mpr.get_entries_in_chemsys(composition) #orig_entries = mpr.get_entries_in_chemsys(chemsys_list[k]) entries = [] for i in range(len(bias)): entries.append(copy.deepcopy(orig_entries)) for j in range(0, len(entries[i])): temp = entries[i][j].parameters['potcar_symbols'] if temp in [['PBE ' + anions[0]], ['PBE ' + anions[1]], ['PBE ' + anions[0], 'PBE ' + anions[1]], ['PBE ' + anions[1], 'PBE ' + anions[0]]]: new_entry = ComputedEntry( entries[i][j].composition, entries[i][j].energy + bias[i]) #add arbitrary energy to gas phase entries[i][j] = copy.deepcopy(new_entry) #Then, find each entry in atomate_db which has this composition and get its hull energy print(pretty) structures = [] cursor = atomate_db.collection.find({ 'task_label': 'static', 'formula_pretty': pretty }) for structure in cursor: structures.append(structure) struct_entries = [] for structure in structures: temp = structure['calcs_reversed'][0] struct_entry = ComputedEntry( temp['composition_unit_cell'], temp['output']['energy'], parameters={ 'run_type': temp['run_type'], 'is_hubbard': structure['input']['is_hubbard'], 'pseudo_potential': structure['input']['pseudo_potential'], 'hubbards': structure['input']['hubbards'], 'potcar_symbols': structure['orig_inputs']['potcar']['symbols'], 'oxide_type': 'oxide' }, data={'oxide_type': 'oxide'}) for i in range(0, 4): struct_entry.parameters['potcar_symbols'][ i] = 'PBE ' + struct_entry.parameters[ 'potcar_symbols'][i] struct_entry = MaterialsProjectCompatibility().process_entries( [struct_entry ])[0] #takes list as argument and returns list struct_entries.append(struct_entry) bias_strings = [] stable_polymorph = {'id': 0, 'tilt_order': ''} for i in range(len(bias)): entries[i].extend(struct_entries) pd = PhaseDiagram(entries[i]) bias_string = 'ehull_' + str(bias[i]) + 'eV' bias_strings.append(bias_string) stable_polymorph[bias_strings[i]] = 1000 print(bias_strings) for j in range(0, len(struct_entries)): stability = pd.get_decomp_and_e_above_hull( struct_entries[j]) print(structures[j]['formula_pretty'], structures[j]['task_id'], [phase.composition for phase in stability[0]], stability[1]) if stability[1] < stable_polymorph[bias_strings[i]]: stable_polymorph['id'] = structures[j]['task_id'] stable_polymorph[bias_strings[i]] = stability[1] if 'tags' in structures[j]: if structures[j]['tags'][1] == 'tetra': stable_polymorph['tilt_order'] = structures[j][ 'tags'][2] else: stable_polymorph['tilt_order'] = structures[j][ 'tags'][1] output_dict[structures[j] ['formula_pretty']] = stable_polymorph return output_dict
def get_entries(self, chemsys_formula_id_criteria, compatible_only=True, inc_structure=None, property_data=None, conventional_unit_cell=False): """ Get a list of ComputedEntries or ComputedStructureEntries corresponding to a chemical system, formula, or materials_id or full criteria. Args: chemsys_formula_id_criteria (str/dict): A chemical system (e.g., Li-Fe-O), or formula (e.g., Fe2O3) or materials_id (e.g., mp-1234) or full Mongo-style dict criteria. compatible_only (bool): Whether to return only "compatible" entries. Compatible entries are entries that have been processed using the MaterialsProjectCompatibility class, which performs adjustments to allow mixing of GGA and GGA+U calculations for more accurate phase diagrams and reaction energies. inc_structure (str): If None, entries returned are ComputedEntries. If inc_structure="final", ComputedStructureEntries with final structures are returned. Otherwise, ComputedStructureEntries with initial structures are returned. property_data (list): Specify additional properties to include in entry.data. If None, no data. Should be a subset of supported_properties. conventional_unit_cell (bool): Whether to get the standard conventional unit cell Returns: List of ComputedEntry or ComputedStructureEntry objects. """ # TODO: This is a very hackish way of doing this. It should be fixed # on the REST end. params = [ "run_type", "is_hubbard", "pseudo_potential", "hubbards", "potcar_symbols", "oxide_type" ] props = ["energy", "unit_cell_formula", "task_id"] + params if property_data: props += property_data if inc_structure: if inc_structure == "final": props.append("structure") else: props.append("initial_structure") if not isinstance(chemsys_formula_id_criteria, dict): criteria = MPRester.parse_criteria(chemsys_formula_id_criteria) else: criteria = chemsys_formula_id_criteria try: data = self.query(criteria, props) except MPRestError: return [] entries = [] for d in data: d["potcar_symbols"] = [ "%s %s" % (d["pseudo_potential"]["functional"], l) for l in d["pseudo_potential"]["labels"] ] data = {"oxide_type": d["oxide_type"]} if property_data: data.update({k: d[k] for k in property_data}) if not inc_structure: e = ComputedEntry(d["unit_cell_formula"], d["energy"], parameters={k: d[k] for k in params}, data=data, entry_id=d["task_id"]) else: prim = d["structure"] if inc_structure == "final" else d[ "initial_structure"] if conventional_unit_cell: s = SpacegroupAnalyzer( prim).get_conventional_standard_structure() energy = d["energy"] * (len(s) / len(prim)) else: s = prim.copy() energy = d["energy"] e = ComputedStructureEntry( s, energy, parameters={k: d[k] for k in params}, data=data, entry_id=d["task_id"]) entries.append(e) if compatible_only: from pymatgen.entries.compatibility import \ MaterialsProjectCompatibility entries = MaterialsProjectCompatibility().process_entries(entries) return entries
def test_process_entries(self): compat = MaterialsProjectCompatibility() entries = compat.process_entries([self.entry1, self.entry2, self.entry3]) self.assertEqual(len(entries), 2)
class MaterialsProjectCompatibilityTest(unittest.TestCase): def setUp(self): self.entry1 = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.entry2 = ComputedEntry( 'Fe3O4', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.entry3 = ComputedEntry( 'FeO', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 4.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.compat = MaterialsProjectCompatibility(check_potcar_hash=False) self.ggacompat = MaterialsProjectCompatibility("GGA", check_potcar_hash=False) def test_process_entry(self): #Correct parameters self.assertIsNotNone(self.compat.process_entry(self.entry1)) self.assertIsNone(self.ggacompat.process_entry(self.entry1)) #Correct parameters entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': False, "hubbards": {}, 'run_type': 'GGA', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.assertIsNone(self.compat.process_entry(entry)) self.assertIsNotNone(self.ggacompat.process_entry(entry)) entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.assertIsNotNone(self.compat.process_entry(entry)) def test_correction_values(self): #test_corrections self.assertAlmostEqual(self.compat.process_entry(self.entry1).correction, - 2.733 * 2 - 0.70229 * 3) entry = ComputedEntry( 'FeF3', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'F': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE F 08Apr2002', 'hash': '180141c33d032bfbfff30b3bea9d23dd'}]}) self.assertIsNotNone(self.compat.process_entry(entry)) #Check actual correction self.assertAlmostEqual(self.compat.process_entry(entry).correction, -2.733) def test_U_values(self): #Wrong U value entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.2, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.assertIsNone(self.compat.process_entry(entry)) #GGA run of U entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': False, 'hubbards': None, 'run_type': 'GGA', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.assertIsNone(self.compat.process_entry(entry)) #GGA+U run of non-U entry = ComputedEntry( 'Al2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Al': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel': 'PAW_PBE Al 06Sep2000', 'hash': '805c888bbd2793e462311f6a20d873d9'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.assertIsNone(self.compat.process_entry(entry)) #Materials project should not have a U for sulfides entry = ComputedEntry( 'FeS2', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'S': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {"titel": 'PAW_PBE S 08Apr2002', 'hash': "f7f8e4a74a6cbb8d63e41f4373b54df2"}]}) self.assertIsNone(self.compat.process_entry(entry)) def test_wrong_psp(self): #Wrong psp entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe 06Sep2000', 'hash': '9530da8244e4dac17580869b4adab115'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}]}) self.assertIsNone(self.compat.process_entry(entry)) def test_element_processing(self): entry = ComputedEntry( 'O', -1, 0.0, parameters={'is_hubbard': False, 'hubbards': {}, 'potcar_spec': [{'titel': 'PAW_PBE O 08Apr2002', 'hash': '7a25bc5b9a5393f46600a4939d357982'}], 'run_type': 'GGA'}) entry = self.compat.process_entry(entry) # self.assertEqual(entry.entry_id, -8) self.assertAlmostEqual(entry.energy, -1) self.assertAlmostEqual(self.ggacompat.process_entry(entry).energy, -1) def test_get_corrections_dict(self): compat = MaterialsProjectCompatibility(check_potcar_hash=False) ggacompat = MaterialsProjectCompatibility("GGA", check_potcar_hash=False) #Correct parameters entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_spec': [{'titel':'PAW_PBE Fe_pv 06Sep2000', 'hash': '994537de5c4122b7f1b77fb604476db4'}, {'titel': 'PAW_PBE O 08Apr2002', 'hash': "7a25bc5b9a5393f46600a4939d357982"}]}) c = compat.get_corrections_dict(entry) self.assertAlmostEqual(c["MP Gas Correction"], -2.10687) self.assertAlmostEqual(c["MP Advanced Correction"], -5.466) entry.parameters["is_hubbard"] = False del entry.parameters["hubbards"] c = ggacompat.get_corrections_dict(entry) self.assertNotIn("MP Advanced Correction", c) def test_process_entries(self): entries = self.compat.process_entries([self.entry1, self.entry2, self.entry3]) self.assertEqual(len(entries), 2)
from pymatgen.ext.matproj import MPRester from pymatgen.apps.borg.hive import VaspToComputedEntryDrone from pymatgen.apps.borg.queen import BorgQueen from pymatgen.entries.compatibility import MaterialsProjectCompatibility from pymatgen.analysis.phase_diagram import PhaseDiagram from pymatgen.analysis.phase_diagram import PDPlotter # Assimilate VASP calculations into ComputedEntry object. Let's assume that # the calculations are for a series of new LixFeyOz phases that we want to # know the phase stability. drone = VaspToComputedEntryDrone() queen = BorgQueen(drone, rootpath=".") entries = queen.get_data() # Obtain all existing Li-Fe-O phases using the Materials Project REST API with MPRester("key") as m: mp_entries = m.get_entries_in_chemsys(["Li", "Sn", "S"]) # Combined entry from calculated run with Materials Project entries entries.extend(mp_entries) # Process entries using the MaterialsProjectCompatibility compat = MaterialsProjectCompatibility() entries = compat.process_entries(entries) # Generate and plot Li-Fe-O phase diagram pd = PhaseDiagram(entries) plotter = PDPlotter(pd) plotter.show()
def get_entries(self, chemsys_formula_id_criteria, compatible_only=True, inc_structure=None, property_data=None): """ Get a list of ComputedEntries or ComputedStructureEntries corresponding to a chemical system, formula, or materials_id or full criteria. Args: chemsys_formula_id_criteria (str/dict): A chemical system (e.g., Li-Fe-O), or formula (e.g., Fe2O3) or materials_id (e.g., mp-1234) or full Mongo-style dict criteria. compatible_only (bool): Whether to return only "compatible" entries. Compatible entries are entries that have been processed using the MaterialsProjectCompatibility class, which performs adjustments to allow mixing of GGA and GGA+U calculations for more accurate phase diagrams and reaction energies. inc_structure (str): If None, entries returned are ComputedEntries. If inc_structure="final", ComputedStructureEntries with final structures are returned. Otherwise, ComputedStructureEntries with initial structures are returned. property_data (list): Specify additional properties to include in entry.data. If None, no data. Should be a subset of supported_properties. Returns: List of ComputedEntry or ComputedStructureEntry objects. """ # TODO: This is a very hackish way of doing this. It should be fixed # on the REST end. params = ["run_type", "is_hubbard", "pseudo_potential", "hubbards", "potcar_symbols"] if compatible_only: props = ["energy", "unit_cell_formula", "task_id"] + params if property_data: props += property_data if inc_structure: if inc_structure == "final": props.append("structure") else: props.append("initial_structure") if not isinstance(chemsys_formula_id_criteria, dict): criteria = MPRester.parse_criteria(chemsys_formula_id_criteria) else: criteria = chemsys_formula_id_criteria data = self.query(criteria, props) entries = [] for d in data: d["potcar_symbols"] = [ "%s %s" % (d["pseudo_potential"]["functional"], l) for l in d["pseudo_potential"]["labels"]] data = {k: d[k] for k in property_data} if property_data else None if not inc_structure: e = ComputedEntry(d["unit_cell_formula"], d["energy"], parameters={k: d[k] for k in params}, data=data, entry_id=d["task_id"]) else: s = d["structure"] if inc_structure == "final" else d[ "initial_structure"] e = ComputedStructureEntry( s, d["energy"], parameters={k: d[k] for k in params}, data=data, entry_id=d["task_id"]) entries.append(e) from pymatgen.entries.compatibility import \ MaterialsProjectCompatibility entries = MaterialsProjectCompatibility().process_entries(entries) else: entries = [] for d in self.get_data(chemsys_formula_id_criteria, prop="task_ids"): for i in d["task_ids"]: e = self.get_task_data(i, prop="entry") e = e[0]["entry"] if inc_structure: s = self.get_task_data(i, prop="structure")[0]["structure"] e = ComputedStructureEntry( s, e.energy, e.correction, e.parameters, e.data, e.entry_id) entries.append(e) return entries
def assimilate(self, path, launches_coll=None): """ Parses vasp runs. Then insert the result into the db. and return the task_id or doc of the insertion. Returns: If in simulate_mode, the entire doc is returned for debugging purposes. Else, only the task_id of the inserted doc is returned. """ d = self.get_task_doc(path) if self.additional_fields: d.update(self.additional_fields) # always add additional fields, even for failed jobs try: d["dir_name_full"] = d["dir_name"].split(":")[1] d["dir_name"] = get_block_part(d["dir_name_full"]) d["stored_data"] = {} except: print 'COULD NOT GET DIR NAME' pprint.pprint(d) print traceback.format_exc() raise ValueError('IMPROPER PARSING OF {}'.format(path)) if not self.simulate: # Perform actual insertion into db. Because db connections cannot # be pickled, every insertion needs to create a new connection # to the db. conn = MongoClient(self.host, self.port) db = conn[self.database] if self.user: db.authenticate(self.user, self.password) coll = db[self.collection] # Insert dos data into gridfs and then remove it from the dict. # DOS data tends to be above the 4Mb limit for mongo docs. A ref # to the dos file is in the dos_fs_id. result = coll.find_one({"dir_name": d["dir_name"]}) if result is None or self.update_duplicates: if self.parse_dos and "calculations" in d: for calc in d["calculations"]: if "dos" in calc: dos = json.dumps(calc["dos"], cls=MontyEncoder) fs = gridfs.GridFS(db, "dos_fs") dosid = fs.put(dos) calc["dos_fs_id"] = dosid del calc["dos"] d["last_updated"] = datetime.datetime.today() if result is None: if ("task_id" not in d) or (not d["task_id"]): d["task_id"] = "mp-{}".format( db.counter.find_one_and_update( {"_id": "taskid"}, {"$inc": {"c": 1}} )["c"]) logger.info("Inserting {} with taskid = {}" .format(d["dir_name"], d["task_id"])) elif self.update_duplicates: d["task_id"] = result["task_id"] logger.info("Updating {} with taskid = {}" .format(d["dir_name"], d["task_id"])) #Fireworks processing self.process_fw(path, d) try: #Add oxide_type struct=Structure.from_dict(d["output"]["crystal"]) d["oxide_type"]=oxide_type(struct) except: logger.error("can't get oxide_type for {}".format(d["task_id"])) d["oxide_type"] = None #Override incorrect outcar subdocs for two step relaxations if "optimize structure" in d['task_type'] and \ os.path.exists(os.path.join(path, "relax2")): try: run_stats = {} for i in [1,2]: o_path = os.path.join(path,"relax"+str(i),"OUTCAR") o_path = o_path if os.path.exists(o_path) else o_path+".gz" outcar = Outcar(o_path) d["calculations"][i-1]["output"]["outcar"] = outcar.as_dict() run_stats["relax"+str(i)] = outcar.run_stats except: logger.error("Bad OUTCAR for {}.".format(path)) try: overall_run_stats = {} for key in ["Total CPU time used (sec)", "User time (sec)", "System time (sec)", "Elapsed time (sec)"]: overall_run_stats[key] = sum([v[key] for v in run_stats.values()]) run_stats["overall"] = overall_run_stats except: logger.error("Bad run stats for {}.".format(path)) d["run_stats"] = run_stats # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = d["pseudo_potential"]["functional"] labels = d["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = {"run_type": d["run_type"], "is_hubbard": d["is_hubbard"], "hubbards": d["hubbards"], "potcar_symbols": symbols} entry = ComputedEntry(Composition(d["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=d["task_id"]) d['is_compatible'] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility' d['is_compatible'] = None #task_type dependent processing if 'static' in d['task_type']: launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) for i in ["conventional_standard_structure", "symmetry_operations", "symmetry_dataset", "refined_structure"]: try: d['stored_data'][i] = launch_doc['action']['stored_data'][i] except: pass #parse band structure if necessary if ('band structure' in d['task_type'] or "Uniform" in d['task_type'])\ and d['state'] == 'successful': launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) vasp_run = Vasprun(zpath(os.path.join(path, "vasprun.xml")), parse_projected_eigen=False) if 'band structure' in d['task_type']: def string_to_numlist(stringlist): g=re.search('([0-9\-\.eE]+)\s+([0-9\-\.eE]+)\s+([0-9\-\.eE]+)', stringlist) return [float(g.group(i)) for i in range(1,4)] for i in ["kpath_name", "kpath"]: d['stored_data'][i] = launch_doc['action']['stored_data'][i] kpoints_doc = d['stored_data']['kpath']['kpoints'] for i in kpoints_doc: kpoints_doc[i]=string_to_numlist(kpoints_doc[i]) bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=True) else: bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=False) bs_json = json.dumps(bs.as_dict(), cls=MontyEncoder) fs = gridfs.GridFS(db, "band_structure_fs") bs_id = fs.put(bs_json) d['calculations'][0]["band_structure_fs_id"] = bs_id # also override band gap in task doc gap = bs.get_band_gap() vbm = bs.get_vbm() cbm = bs.get_cbm() update_doc = {'bandgap': gap['energy'], 'vbm': vbm['energy'], 'cbm': cbm['energy'], 'is_gap_direct': gap['direct']} d['analysis'].update(update_doc) d['calculations'][0]['output'].update(update_doc) coll.update_one({"dir_name": d["dir_name"]}, {'$set': d}, upsert=True) return d["task_id"], d else: logger.info("Skipping duplicate {}".format(d["dir_name"])) return result["task_id"], result else: d["task_id"] = 0 logger.info("Simulated insert into database for {} with task_id {}" .format(d["dir_name"], d["task_id"])) return 0, d
def test_process_entry(self): compat = MaterialsProjectCompatibility() ggacompat = MaterialsProjectCompatibility("GGA") #Correct parameters self.assertIsNotNone(compat.process_entry(self.entry1)) self.assertIsNone(ggacompat.process_entry(self.entry1)) #Correct parameters entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': False, "hubbards": {}, 'run_type': 'GGA', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE O 08Apr2002']}) self.assertIsNone(compat.process_entry(entry)) self.assertIsNotNone(ggacompat.process_entry(entry)) entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE O 08Apr2002']}) self.assertIsNotNone(compat.process_entry(entry)) #Check actual correction self.assertAlmostEqual(compat.process_entry(entry).correction, - 2.733 * 2 - 0.70229 * 3) entry = ComputedEntry( 'FeF3', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'F': 0}, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE F 08Apr2002']}) self.assertIsNotNone(compat.process_entry(entry)) #Check actual correction self.assertAlmostEqual(compat.process_entry(entry).correction, -2.733) #Wrong U value entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.2, 'O': 0}, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE O 08Apr2002']}) self.assertIsNone(compat.process_entry(entry)) #GGA run of U entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': False, 'hubbards': None, 'run_type': 'GGA', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE O 08Apr2002']}) self.assertIsNone(compat.process_entry(entry)) #GGA+U run of non-U entry = ComputedEntry( 'Al2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Al': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Al 06Sep2000', 'PAW_PBE O 08Apr2002']}) self.assertIsNone(compat.process_entry(entry)) #Materials project should not have a U for sulfides entry = ComputedEntry( 'FeS2', -2, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'S': 0}, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Fe_pv 06Sep2000', 'PAW_PBE S 08Apr2002']}) self.assertIsNone(compat.process_entry(entry)) #Wrong psp entry = ComputedEntry( 'Fe2O3', -1, 0.0, parameters={'is_hubbard': True, 'hubbards': {'Fe': 5.3, 'O': 0}, 'run_type': 'GGA+U', 'potcar_symbols': ['PAW_PBE Fe 06Sep2000', 'PAW_PBE O 08Apr2002']}) self.assertIsNone(compat.process_entry(entry)) #Testing processing of elements. entry = ComputedEntry( 'O', -1, 0.0, parameters={'is_hubbard': False, 'hubbards': {}, 'potcar_symbols': ['PAW_PBE O 08Apr2002'], 'run_type': 'GGA'}) entry = compat.process_entry(entry) # self.assertEqual(entry.entry_id, -8) self.assertAlmostEqual(entry.energy, -1) self.assertAlmostEqual(ggacompat.process_entry(entry).energy, -1)
class AnalyseMaterialsProjectJsonDataWithComputedEntries(): """ Class which will wrap around boilerplate analysis of MaterialsProject-like json files, containing data extracted using borgs and queens. It will be assumed that we are providing ComputedEntries objects directly. """ def __init__(self): # some MP analysis power tools self.compat = MaterialsProjectCompatibility() return def extract_alkali_energy(self, computed_Alkali_entry ): processed_Alkali_entry = self.compat.process_entry(computed_Alkali_entry) self.E_Alkali = processed_Alkali_entry.energy return def extract_phase_diagram_info(self,MP_phase_diagram_json_data_filename): computed_entries = self._extract_MP_data(MP_phase_diagram_json_data_filename) processed_entries = self.compat.process_entries(computed_entries) pd = PhaseDiagram(processed_entries) self.phase_diagram_analyser = PDAnalyzer(pd) return def extract_processed_entries(self,computed_entries): processed_entries = self.compat.process_entries(computed_entries) return processed_entries def extract_energies_above_hull(self,computed_entries,alkali): processed_entries = self.extract_processed_entries(computed_entries) list_energy_above_hull = [] list_alkali_content = [] for entry in processed_entries: decomposition_dict, energy_above_hull = \ self.phase_diagram_analyser.get_decomp_and_e_above_hull(entry, allow_negative=True) list_energy_above_hull.append(energy_above_hull) list_alkali_content.append(entry.composition[alkali]) list_energy_above_hull = np.array(list_energy_above_hull) list_alkali_content = np.array(list_alkali_content ) return list_alkali_content, list_energy_above_hull def extract_energies(self,computed_entries,alkali): processed_entries = self.extract_processed_entries(computed_entries) list_energy = [] list_alkali_content = [] for entry in processed_entries: list_energy.append(entry.energy) list_alkali_content.append(entry.composition[alkali]) list_energy = np.array(list_energy) list_alkali_content = np.array(list_alkali_content ) I = np.argsort(list_alkali_content ) return list_alkali_content[I], list_energy[I] def _extract_MP_data(self,MP_data_filename): drone = VaspToComputedEntryDrone() queen = BorgQueen(drone, "dummy", 1) queen.load_data(MP_data_filename) computed_entries = queen.get_data() del drone del queen return computed_entries
def test_properties(self): filepath = os.path.join(test_dir, 'vasprun.xml.nonlm') vasprun = Vasprun(filepath, parse_potcar_file=False) orbs = list(vasprun.complete_dos.pdos[vasprun.final_structure[ 0]].keys()) self.assertIn(OrbitalType.s, orbs) filepath = os.path.join(test_dir, 'vasprun.xml') vasprun = Vasprun(filepath, parse_potcar_file=False) #Test NELM parsing. self.assertEqual(vasprun.parameters["NELM"], 60) #test pdos parsing pdos0 = vasprun.complete_dos.pdos[vasprun.final_structure[0]] self.assertAlmostEqual(pdos0[Orbital.s][Spin.up][16], 0.0026) self.assertAlmostEqual(pdos0[Orbital.pz][Spin.down][16], 0.0012) self.assertEqual(pdos0[Orbital.s][Spin.up].shape, (301, )) filepath2 = os.path.join(test_dir, 'lifepo4.xml') vasprun_ggau = Vasprun(filepath2, parse_projected_eigen=True, parse_potcar_file=False) totalscsteps = sum([len(i['electronic_steps']) for i in vasprun.ionic_steps]) self.assertEqual(29, len(vasprun.ionic_steps)) self.assertEqual(len(vasprun.structures), len(vasprun.ionic_steps)) self.assertEqual(vasprun.lattice, vasprun.lattice_rec.reciprocal_lattice) for i, step in enumerate(vasprun.ionic_steps): self.assertEqual(vasprun.structures[i], step["structure"]) self.assertTrue(all([vasprun.structures[i] == vasprun.ionic_steps[i][ "structure"] for i in range(len(vasprun.ionic_steps))])) self.assertEqual(308, totalscsteps, "Incorrect number of energies read from vasprun.xml") self.assertEqual(['Li'] + 4 * ['Fe'] + 4 * ['P'] + 16 * ["O"], vasprun.atomic_symbols) self.assertEqual(vasprun.final_structure.composition.reduced_formula, "LiFe4(PO4)4") self.assertIsNotNone(vasprun.incar, "Incar cannot be read") self.assertIsNotNone(vasprun.kpoints, "Kpoints cannot be read") self.assertIsNotNone(vasprun.eigenvalues, "Eigenvalues cannot be read") self.assertAlmostEqual(vasprun.final_energy, -269.38319884, 7) self.assertAlmostEqual(vasprun.tdos.get_gap(), 2.0589, 4) expectedans = (2.539, 4.0906, 1.5516, False) (gap, cbm, vbm, direct) = vasprun.eigenvalue_band_properties self.assertAlmostEqual(gap, expectedans[0]) self.assertAlmostEqual(cbm, expectedans[1]) self.assertAlmostEqual(vbm, expectedans[2]) self.assertEqual(direct, expectedans[3]) self.assertFalse(vasprun.is_hubbard) self.assertEqual(vasprun.potcar_symbols, ['PAW_PBE Li 17Jan2003', 'PAW_PBE Fe 06Sep2000', 'PAW_PBE Fe 06Sep2000', 'PAW_PBE P 17Jan2003', 'PAW_PBE O 08Apr2002']) self.assertIsNotNone(vasprun.kpoints, "Kpoints cannot be read") self.assertIsNotNone(vasprun.actual_kpoints, "Actual kpoints cannot be read") self.assertIsNotNone(vasprun.actual_kpoints_weights, "Actual kpoints weights cannot be read") for atomdoses in vasprun.pdos: for orbitaldos in atomdoses: self.assertIsNotNone(orbitaldos, "Partial Dos cannot be read") # test skipping ionic steps. vasprun_skip = Vasprun(filepath, 3, parse_potcar_file=False) self.assertEqual(vasprun_skip.nionic_steps, 29) self.assertEqual(len(vasprun_skip.ionic_steps), int(vasprun.nionic_steps / 3) + 1) self.assertEqual(len(vasprun_skip.ionic_steps), len(vasprun_skip.structures)) self.assertEqual(len(vasprun_skip.ionic_steps), int(vasprun.nionic_steps / 3) + 1) # Check that nionic_steps is preserved no matter what. self.assertEqual(vasprun_skip.nionic_steps, vasprun.nionic_steps) self.assertNotAlmostEqual(vasprun_skip.final_energy, vasprun.final_energy) # Test with ionic_step_offset vasprun_offset = Vasprun(filepath, 3, 6, parse_potcar_file=False) self.assertEqual(len(vasprun_offset.ionic_steps), int(len(vasprun.ionic_steps) / 3) - 1) self.assertEqual(vasprun_offset.structures[0], vasprun_skip.structures[2]) self.assertTrue(vasprun_ggau.is_hubbard) self.assertEqual(vasprun_ggau.hubbards["Fe"], 4.3) self.assertAlmostEqual(vasprun_ggau.projected_eigenvalues[(Spin.up, 0, 0, 96, Orbital.s)], 0.0032) d = vasprun_ggau.as_dict() self.assertEqual(d["elements"], ["Fe", "Li", "O", "P"]) self.assertEqual(d["nelements"], 4) filepath = os.path.join(test_dir, 'vasprun.xml.unconverged') with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") # Trigger a warning. vasprun_unconverged = Vasprun(filepath, parse_potcar_file=False) # Verify some things self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, UnconvergedVASPWarning)) self.assertTrue(vasprun_unconverged.converged_ionic) self.assertFalse(vasprun_unconverged.converged_electronic) self.assertFalse(vasprun_unconverged.converged) filepath = os.path.join(test_dir, 'vasprun.xml.dfpt') vasprun_dfpt = Vasprun(filepath, parse_potcar_file=False) self.assertAlmostEqual(vasprun_dfpt.epsilon_static[0][0], 3.26105533) self.assertAlmostEqual(vasprun_dfpt.epsilon_static[0][1], -0.00459066) self.assertAlmostEqual(vasprun_dfpt.epsilon_static[2][2], 3.24330517) self.assertAlmostEqual(vasprun_dfpt.epsilon_static_wolfe[0][0], 3.33402531) self.assertAlmostEqual(vasprun_dfpt.epsilon_static_wolfe[0][1], -0.00559998) self.assertAlmostEqual(vasprun_dfpt.epsilon_static_wolfe[2][2], 3.31237357) self.assertTrue(vasprun_dfpt.converged) entry = vasprun_dfpt.get_computed_entry() entry = MaterialsProjectCompatibility(check_potcar_hash=False).process_entry(entry) self.assertAlmostEqual(entry.uncorrected_energy + entry.correction, entry.energy) filepath = os.path.join(test_dir, 'vasprun.xml.dfpt.ionic') vasprun_dfpt_ionic = Vasprun(filepath, parse_potcar_file=False) self.assertAlmostEqual(vasprun_dfpt_ionic.epsilon_ionic[0][0], 515.73485838) self.assertAlmostEqual(vasprun_dfpt_ionic.epsilon_ionic[0][1], -0.00263523) self.assertAlmostEqual(vasprun_dfpt_ionic.epsilon_ionic[2][2], 19.02110169) filepath = os.path.join(test_dir, 'vasprun.xml.dfpt.unconverged') vasprun_dfpt_unconv = Vasprun(filepath, parse_potcar_file=False) self.assertFalse(vasprun_dfpt_unconv.converged_electronic) self.assertTrue(vasprun_dfpt_unconv.converged_ionic) self.assertFalse(vasprun_dfpt_unconv.converged) vasprun_uniform = Vasprun(os.path.join(test_dir, "vasprun.xml.uniform"), parse_potcar_file=False) self.assertEqual(vasprun_uniform.kpoints.style, Kpoints.supported_modes.Reciprocal) vasprun_no_pdos = Vasprun(os.path.join(test_dir, "Li_no_projected.xml"), parse_potcar_file=False) self.assertIsNotNone(vasprun_no_pdos.complete_dos) self.assertFalse(vasprun_no_pdos.dos_has_errors) vasprun_diel = Vasprun(os.path.join(test_dir, "vasprun.xml.dielectric"), parse_potcar_file=False) self.assertAlmostEqual(0.4294,vasprun_diel.dielectric[0][10]) self.assertAlmostEqual(19.941,vasprun_diel.dielectric[1][51][0]) self.assertAlmostEqual(19.941,vasprun_diel.dielectric[1][51][1]) self.assertAlmostEqual(19.941,vasprun_diel.dielectric[1][51][2]) self.assertAlmostEqual(0.0,vasprun_diel.dielectric[1][51][3]) self.assertAlmostEqual(34.186,vasprun_diel.dielectric[2][85][0]) self.assertAlmostEqual(34.186,vasprun_diel.dielectric[2][85][1]) self.assertAlmostEqual(34.186,vasprun_diel.dielectric[2][85][2]) self.assertAlmostEqual(0.0,vasprun_diel.dielectric[2][85][3]) v = Vasprun(os.path.join(test_dir, "vasprun.xml.indirect.gz")) (gap, cbm, vbm, direct) = v.eigenvalue_band_properties self.assertFalse(direct)
from pymatgen.entries.compatibility import MaterialsProjectCompatibility from pymatgen.analysis.phase_diagram import PhaseDiagram, PDPlotter, PDEntry from pymatgen.core.periodic_table import Element from pymatgen.core.composition import Composition from pymatgen.io.vasp.outputs import Vasprun import sys print("Usage: get_phase_diagram_from_MP.py 'Element1,Element2,Element3,...'") system = [el for el in sys.argv[1].split(',')] # system we want to get PD for MAPI_KEY = 'DSR45TfHVuyuB1WvP1' # You must change this to your Materials API key! (or set MAPI_KEY env variable) system_name = '-'.join(system) mpr = MPRester(MAPI_KEY) # object for connecting to MP Rest interface compat = MaterialsProjectCompatibility( ) # sets energy corrections and +U/pseudopotential choice unprocessed_entries = mpr.get_entries_in_chemsys(system, inc_structure=True) processed_entries = compat.process_entries( unprocessed_entries) # filter and add energy corrections pd = PhaseDiagram(processed_entries) pd_dict = pd.as_dict() filename = f'PD_{system_name}.json' with open(filename, 'w') as f: json.dump(pd_dict, f) print(f"PhaseDiagram object saved as dict in {filename}")
def run_task(self, fw_spec): # import here to prevent import errors in bigger MPCollab # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ filename = get_slug( 'JOB--' + fw_spec['mpsnl'].structure.composition.reduced_formula + '--' + fw_spec['task_type']) with open(filename, 'w+') as f: f.write('') # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) props = { "calculations": 1, "task_id": 1, "state": 1, "pseudo_potential": 1, "run_type": 1, "is_hubbard": 1, "hubbards": 1, "unit_cell_formula": 1 } m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: time.sleep( 60) # only thing to think of is wait for DB insertion(?) m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: raise ValueError( "Could not find task with dir_name: {}".format(block_part)) if m_task['state'] != 'successful': raise ValueError( "Cannot run Boltztrap; parent job unsuccessful") nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output'][ 'crystal'] bs = BandStructure.from_dict(bs_dict) print("find previous run with block_part {}".format(block_part)) print 'Band Structure found:', bool(bs) print(bs.as_dict()) print("nelect: {}".format(nelect)) # run Boltztrap doping = [] for d in [1e16, 1e17, 1e18, 1e19, 1e20]: doping.extend([1 * d, 2.5 * d, 5 * d, 7.5 * d]) doping.append(1e21) runner = BoltztrapRunner(bs, nelect, doping=doping) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) # 8/21/15 - Anubhav removed fs_id (also see line further below, ted['boltztrap_full_fs_id'] ...) # 8/21/15 - this is to save space in MongoDB, as well as non-use of full Boltztrap output (vs rerun) """ data = bta.as_dict() data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] del data['hall'] # remove because it is too large and not useful fs = gridfs.GridFS(tdb, "boltztrap_full_fs") btid = fs.put(json.dumps(jsanitize(data))) """ # now for the "sanitized" data ted = bta.as_dict() del ted['seebeck'] del ted['hall'] del ted['kappa'] del ted['cond'] # ted['boltztrap_full_fs_id'] = btid ted['snlgroup_id'] = fw_spec['snlgroup_id'] ted['run_tags'] = fw_spec['run_tags'] ted['snl'] = fw_spec['mpsnl'].as_dict() ted['dir_name_full'] = dir ted['dir_name'] = get_block_part(dir) ted['task_id'] = m_task['task_id'] ted['pf_doping'] = bta.get_power_factor(output='tensor', relaxation_time=self.TAU) ted['zt_doping'] = bta.get_zt(output='tensor', relaxation_time=self.TAU, kl=self.KAPPAL) ted['pf_eigs'] = self.get_eigs(ted, 'pf_doping') ted['pf_best'] = self.get_extreme(ted, 'pf_eigs') ted['pf_best_dope18'] = self.get_extreme(ted, 'pf_eigs', max_didx=3) ted['pf_best_dope19'] = self.get_extreme(ted, 'pf_eigs', max_didx=4) ted['zt_eigs'] = self.get_eigs(ted, 'zt_doping') ted['zt_best'] = self.get_extreme(ted, 'zt_eigs') ted['zt_best_dope18'] = self.get_extreme(ted, 'zt_eigs', max_didx=3) ted['zt_best_dope19'] = self.get_extreme(ted, 'zt_eigs', max_didx=4) ted['seebeck_eigs'] = self.get_eigs(ted, 'seebeck_doping') ted['seebeck_best'] = self.get_extreme(ted, 'seebeck_eigs') ted['seebeck_best_dope18'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=3) ted['seebeck_best_dope19'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=4) ted['cond_eigs'] = self.get_eigs(ted, 'cond_doping') ted['cond_best'] = self.get_extreme(ted, 'cond_eigs') ted['cond_best_dope18'] = self.get_extreme(ted, 'cond_eigs', max_didx=3) ted['cond_best_dope19'] = self.get_extreme(ted, 'cond_eigs', max_didx=4) ted['kappa_eigs'] = self.get_eigs(ted, 'kappa_doping') ted['kappa_best'] = self.get_extreme(ted, 'kappa_eigs', maximize=False) ted['kappa_best_dope18'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=3) ted['kappa_best_dope19'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=4) try: from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB bzspb = BoltzSPB(ted) maxpf_p = bzspb.get_maximum_power_factor( 'p', temperature=0, tau=1E-14, ZT=False, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxpf_n = bzspb.get_maximum_power_factor( 'n', temperature=0, tau=1E-14, ZT=False, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_p = bzspb.get_maximum_power_factor( 'p', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_n = bzspb.get_maximum_power_factor( 'n', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) ted['zt_best_finemesh'] = {'p': maxzt_p, 'n': maxzt_n} ted['pf_best_finemesh'] = {'p': maxpf_p, 'n': maxpf_n} except: import traceback traceback.print_exc() print 'COULD NOT GET FINE MESH DATA' # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = m_task["pseudo_potential"]["functional"] labels = m_task["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = { "run_type": m_task["run_type"], "is_hubbard": m_task["is_hubbard"], "hubbards": m_task["hubbards"], "potcar_symbols": symbols } entry = ComputedEntry(Composition(m_task["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=m_task["task_id"]) ted["is_compatible"] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility, task_id: {}'.format( m_task["task_id"]) ted["is_compatible"] = None tdb.boltztrap.insert(jsanitize(ted)) update_spec = { 'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'].as_dict(), 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters') } return FWAction(update_spec=update_spec)
def __init__(self): # some MP analysis power tools self.compat = MaterialsProjectCompatibility() return