def get_decomposition_in_gppd(self, chempot, entries=None, exclusions=None, trypreload=False): gppd_entries = entries if entries \ else self.get_gppd_entries(chempot, exclusions=exclusions, trypreload=trypreload) pd = PhaseDiagram(gppd_entries) gppd_entries = pd.stable_entries open_el_entries = [ _ for _ in gppd_entries if _.is_element and _.composition.elements[0].symbol in chempot.keys() ] el_ref = { _.composition.elements[0].symbol: _.energy_per_atom for _ in open_el_entries } chempot_vaspref = {_: chempot[_] + el_ref[_] for _ in chempot} for open_entry in open_el_entries: open_entry.correction += chempot_vaspref[ open_entry.composition.elements[0].symbol] GPPD = GrandPotentialPhaseDiagram(gppd_entries, chempot_vaspref) GPComp = self.GPComp(chempot) decomp_GP_entries = GPPD.get_decomposition(GPComp) decomp_entries = [gpe.original_entry for gpe in decomp_GP_entries] rxn = ComputedReaction([self] + open_el_entries, decomp_entries) rxn.normalize_to(self.composition) return decomp_entries, rxn
def test_get_critical_compositions(self): c1 = Composition("Fe2O3") c2 = Composition("Li3FeO4") c3 = Composition("Li2O") comps = self.pd.get_critical_compositions(c1, c2) expected = [ Composition("Fe2O3"), Composition("Li0.3243244Fe0.1621621O0.51351349") * 7.4, Composition("Li3FeO4"), ] for crit, exp in zip(comps, expected): self.assertTrue(crit.almost_equals(exp, rtol=0, atol=1e-5)) comps = self.pd.get_critical_compositions(c1, c3) expected = [ Composition("Fe2O3"), Composition("LiFeO2"), Composition("Li5FeO4") / 3, Composition("Li2O"), ] for crit, exp in zip(comps, expected): self.assertTrue(crit.almost_equals(exp, rtol=0, atol=1e-5)) # Don't fail silently if input compositions aren't in phase diagram # Can be very confusing if you're working with a GrandPotentialPD self.assertRaises( ValueError, self.pd.get_critical_compositions, Composition("Xe"), Composition("Mn"), ) # For the moment, should also fail even if compositions are in the gppd # because it isn't handled properly gppd = GrandPotentialPhaseDiagram(self.pd.all_entries, {"Xe": 1}, self.pd.elements + [Element("Xe")]) self.assertRaises( ValueError, gppd.get_critical_compositions, Composition("Fe2O3"), Composition("Li3FeO4Xe"), ) # check that the function still works though comps = gppd.get_critical_compositions(c1, c2) expected = [ Composition("Fe2O3"), Composition("Li0.3243244Fe0.1621621O0.51351349") * 7.4, Composition("Li3FeO4"), ] for crit, exp in zip(comps, expected): self.assertTrue(crit.almost_equals(exp, rtol=0, atol=1e-5)) # case where the endpoints are identical self.assertEqual(self.pd.get_critical_compositions(c1, c1 * 2), [c1, c1 * 2])
def get_phase_diagram_data(self): """ Returns grand potential phase diagram data to external plot Assumes openelement specific element equals None :return: Data to external plot """ open_elements_specific = None open_element_all = Element(self.open_element) mpr = MPRester("settings") # Get data to make phase diagram entries = mpr.get_entries_in_chemsys(self.system, compatible_only=True) #print(entries) if open_elements_specific: gcpd = GrandPotentialPhaseDiagram(entries, open_elements_specific) self.plot_phase_diagram(gcpd, False) self.analyze_phase_diagram(gcpd) if open_element_all: pd = PhaseDiagram(entries) chempots = pd.get_transition_chempots(open_element_all) #print(chempots) #all_gcpds = list() toplot = [] # dic = {} for idx in range(len(chempots)): if idx == len(chempots) - 1: avgchempot = chempots[idx] - 0.1 else: avgchempot = 0.5 * (chempots[idx] + chempots[idx + 1]) gcpd = GrandPotentialPhaseDiagram( entries, {open_element_all: avgchempot}, pd.elements) # toplot.append(self.get_grand_potential_phase_diagram(gcpd)) min_chempot = None if idx == len(chempots) - 1 else chempots[ idx + 1] max_chempot = chempots[idx] #gcpd = GrandPotentialPhaseDiagram(entries, {open_element_all: max_chempot}, pd.elements) toplot.append(self.get_grand_potential_phase_diagram(gcpd)) #toplot.append(max_chempot) #self.plot_phase_diagram(gcpd, False) #print({open_element_all: max_chempot}) # Data to plot phase diagram return toplot
def FullChemicalPotentialWindow(target_phase, key_element): chemsys = key_element + '-' + Composition(target_phase).chemical_system with MPRester(api_key='') as mpr: entries = mpr.get_entries_in_chemsys(chemsys) pd_closed = PhaseDiagram(entries) transition_chempots = pd_closed.get_transition_chempots( Element(key_element)) # The exact mu value used to construct the plot for each range is # the average of the endpoints of the range, with the exception of the last range, # which is plotted at the value of the last endpoint minus 0.1. # https://matsci.org/t/question-on-phase-diagram-app-chemical-potential/511 average_chempots = [] if len(transition_chempots) > 1: for i in range(len(transition_chempots) - 1): ave = (transition_chempots[i] + transition_chempots[i + 1]) / 2 average_chempots.append(ave) average_chempots.append(transition_chempots[-1] - 0.1) elif len(transition_chempots) == 1: # prepare for binary systems, of which two endnodes tielined directly, like Li-Zr average_chempots.append(transition_chempots[0]) average_chempots = np.round(average_chempots, 3) boolean_list = [] for chempot in average_chempots: # GrandPotentialPhaseDiagram works good even for binary systems to find stable phases pd_open = GrandPotentialPhaseDiagram(entries, {Element(key_element): chempot}) stable_phases = [entry.name for entry in pd_open.stable_entries] boolean_list.append(target_phase in stable_phases) return (False not in boolean_list)
class GrandPotentialPhaseDiagramTest(unittest.TestCase): def setUp(self): self.entries = EntrySet.from_csv(str(module_dir / "pdentries_test.csv")) self.pd = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -5}) self.pd6 = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -6}) def test_stable_entries(self): stable_formulas = [ent.original_entry.composition.reduced_formula for ent in self.pd.stable_entries] expected_stable = ["Li5FeO4", "Li2FeO3", "LiFeO2", "Fe2O3", "Li2O2"] for formula in expected_stable: self.assertTrue(formula in stable_formulas, f"{formula} not in stable entries!") self.assertEqual(len(self.pd6.stable_entries), 4) def test_get_formation_energy(self): stable_formation_energies = { ent.original_entry.composition.reduced_formula: self.pd.get_form_energy(ent) for ent in self.pd.stable_entries } expected_formation_energies = { "Fe2O3": 0.0, "Li5FeO4": -5.305515040000046, "Li2FeO3": -2.3424741500000152, "LiFeO2": -0.43026396250000154, "Li2O2": 0.0, } for formula, energy in expected_formation_energies.items(): self.assertAlmostEqual( energy, stable_formation_energies[formula], 7, f"Calculated formation for {formula} is not correct!", ) def test_str(self): self.assertIsNotNone(str(self.pd))
def get_composition_boundaries(self, comp, fixed_chempot_delta): """ Get compositions of phases in boundary of stability with a target composition given a fixed chemical potential on one component. Currently only works for 3-component PD (to check). Used Pymatgen GrandPotentialPhaseDiagram class. The fixed chemical potential is the referenced value that is converted in the global value for the analysis with the GrandPotentialPhaseDiagram class. Parameters ---------- comp : (Pymatgen Composition object) Target composition for which you want to get the bounday phases. fixed_chempots_delta : (Dict) Dictionary with fixed Element as key and respective chemical potential as value ({Element:chempot}). The chemical potential is the referenced value Returns ------- comp1,comp2 : (Pymatgen Composition object) Compositions of the boundary phases given a fixed chemical potential for one element. """ fixed_chempot = self.get_chempots_abs(fixed_chempot_delta) entries = self.pd.all_entries gpd = GrandPotentialPhaseDiagram(entries, fixed_chempot) stable_entries = gpd.stable_entries comp_in_stable_entries = False for e in stable_entries: if e.original_comp.reduced_composition == comp: comp_in_stable_entries = True if comp_in_stable_entries == False: raise ValueError( 'Target composition %s is not a stable entry for fixed chemical potential: %s' % (comp.reduced_formula, fixed_chempot)) el = comp.elements[0] x_target = comp.get_wt_fraction(el) x_max_left = 0 x_min_right = 1 for e in stable_entries: c = e.original_comp if c != comp: x = c.get_wt_fraction(el) if x < x_target and x >= x_max_left: x_max_left = x comp1 = c if x > x_target and x <= x_min_right: x_min_right = x comp2 = c return comp1.reduced_composition, comp2.reduced_composition
def get_stable_range(self, open_el): """ Given a open element, return the chemical potential range within which this entry is stable Args: open_el: the open element, a pymaten Element object Returns: min_chempot, max_chempot """ pd, entry, entries = self.get_pd() working_chempot = [] for chempot in np.arange(-10, 0, 0.01): gcpd = GrandPotentialPhaseDiagram(entries, {open_el: chempot}, pd.elements) mp_ids = [e.entry_id for e in gcpd.stable_entries] if None in mp_ids: working_chempot.append(chempot) return working_chempot[0], working_chempot[-1]
def get_pd_with_open_element(self, open_el): """ The Materials Project website method Return a list of grand canonical phase diagrams with one open element Args: open_el: the open element, a pymaten Element object Returns: a list of grand canonical phase diagrams, a list of corresponding min_chempots, a list of corresponding avg_chempots, a list of corresponding max_chempots, """ pd, entry, entries = self.get_pd() chempots = pd.get_transition_chempots(open_el) gcpds = [] min_chempots = [] max_chempots = [] avg_chempots = [] for i in range(len(chempots)): if i == len(chempots) - 1: avg_chempot = chempots[i] - 0.1 min_chempot = None else: avg_chempot = 0.5 * (chempots[i] + chempots[i + 1]) min_chempot = chempots[i + 1] gcpds.append( GrandPotentialPhaseDiagram(entries, {open_el: avg_chempot}, pd.elements)) min_chempots.append(min_chempot) max_chempots.append(chempots[i]) avg_chempots.append(avg_chempot) return gcpds, min_chempots, avg_chempots, max_chempots
def gppd_mixing(self, chempots, gppd_entries=None): """ This function give the phase equilibria of a pseudo-binary in a open system (GPPD). It will give a complete evolution profile for mixing ratio x change from 0 to 1. x is the ratio (both entry norm. to 1 atom/fu(w/o open element) ) or each entry """ open_el = list(chempots.keys())[0] el_ref = VirtualEntry.get_mp_entry(open_el) chempots[open_el] = chempots[open_el] + el_ref.energy_per_atom gppd_entry1 = GrandPotPDEntry( self.entry1, {Element[_]: chempots[_] for _ in chempots}) gppd_entry2 = GrandPotPDEntry( self.entry2, {Element[_]: chempots[_] for _ in chempots}) if not gppd_entries: gppd_entries = self.get_gppd_entries(open_el) gppd = GrandPotentialPhaseDiagram(gppd_entries, chempots) profile = get_full_evolution_profile(gppd, gppd_entry1, gppd_entry2, 0, 1) cleaned = clean_profile(profile) return cleaned
def get_phase_diagram_data(self): """ Returns grand potential phase diagram data to external plot Assumes openelement specific element equals None :return: Data to external plot """ open_elements_specific = None open_element_all = Element(self.open_element) mpr = MPRester("key") # import do dados dos arquivos tipo vasp drone = VaspToComputedEntryDrone() queen = BorgQueen(drone, rootpath=".") entries = queen.get_data() # Get data to make phase diagram mp_entries = mpr.get_entries_in_chemsys(self.system, compatible_only=True) entries.extend(mp_entries) compat = MaterialsProjectCompatibility() entries = compat.process_entries(entries) #explanation_output = open("explain.txt",'w') entries_output = open("entries.txt", 'w') compat.explain(entries[0]) print(entries, file=entries_output) #print(entries) if open_elements_specific: gcpd = GrandPotentialPhaseDiagram(entries, open_elements_specific) self.plot_phase_diagram(gcpd, False) self.analyze_phase_diagram(gcpd) if open_element_all: pd = PhaseDiagram(entries) chempots = pd.get_transition_chempots(open_element_all) #print(chempots) #all_gcpds = list() toplot = [] # dic = {} for idx in range(len(chempots)): if idx == len(chempots) - 1: avgchempot = chempots[idx] - 0.1 else: avgchempot = 0.5 * (chempots[idx] + chempots[idx + 1]) gcpd = GrandPotentialPhaseDiagram( entries, {open_element_all: avgchempot}, pd.elements) # toplot.append(self.get_grand_potential_phase_diagram(gcpd)) min_chempot = None if idx == len(chempots) - 1 else chempots[ idx + 1] max_chempot = chempots[idx] #gcpd = GrandPotentialPhaseDiagram(entries, {open_element_all: max_chempot}, pd.elements) toplot.append(self.get_grand_potential_phase_diagram(gcpd)) #toplot.append(max_chempot) #self.plot_phase_diagram(gcpd, False) #print({open_element_all: max_chempot}) # Data to plot phase diagram return toplot
def setUp(self): self.entries = [ComputedEntry(Composition('Li'), 0), ComputedEntry(Composition('Mn'), 0), ComputedEntry(Composition('O2'), 0), ComputedEntry(Composition('MnO2'), -10), ComputedEntry(Composition('Mn2O4'), -60), ComputedEntry(Composition('MnO3'), 20), ComputedEntry(Composition('Li2O'), -10), ComputedEntry(Composition('Li2O2'), -8), ComputedEntry(Composition('LiMnO2'), -30) ] self.pd = PhaseDiagram(self.entries) chempots = {'Li': -3} self.gpd = GrandPotentialPhaseDiagram(self.entries, chempots) self.ir = [] self.ir.append( InterfacialReactivity(Composition('O2'), Composition('Mn'), self.pd, norm=0, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('MnO2'), Composition('Mn'), self.gpd, norm=0, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Mn'), Composition('O2'), self.gpd, norm=1, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Li2O'), Composition('Mn'), self.gpd, norm=0, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Mn'), Composition('O2'), self.gpd, norm=1, include_no_mixing_energy=0, pd_non_grand=self.pd, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Mn'), Composition('Li2O'), self.gpd, norm=1, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Li2O2'), Composition('Li'), self.pd, norm=0, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=True)) self.ir.append( InterfacialReactivity(Composition('Li2O2'), Composition('Li'), self.pd, norm=0, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Li2O2'), Composition('MnO2'), self.gpd, norm=0, include_no_mixing_energy=0, pd_non_grand=self.pd, use_hull_energy=True)) self.ir.append( InterfacialReactivity(Composition('Li2O2'), Composition('MnO2'), self.gpd, norm=0, include_no_mixing_energy=0, pd_non_grand=self.pd, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('O2'), Composition('Mn'), self.pd, norm=1, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Li2O2'), Composition('Li2O2'), self.gpd, norm=1, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False)) self.ir.append( InterfacialReactivity(Composition('Li2O2'), Composition('Li2O2'), self.pd, norm=1, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False)) with self.assertRaises(Exception) as context1: self.ir.append( InterfacialReactivity(Composition('Li2O2'), Composition('Li'), self.pd, norm=1, include_no_mixing_energy=1, pd_non_grand=None)) self.assertTrue( 'Please provide grand phase diagram ' 'to compute no_mixing_energy!' == str(context1.exception)) with self.assertRaises(Exception) as context2: self.ir.append( InterfacialReactivity(Composition('O2'), Composition('Mn'), self.gpd, norm=0, include_no_mixing_energy=1, pd_non_grand=None)) self.assertTrue( 'Please provide non-grand phase diagram ' 'to compute no_mixing_energy!' == str(context2.exception))
"key"] # You must change this to your Materials API key! (or set MAPI_KEY env variable) system = ["Li", "B", "O"] # system we want to get open PD for # system = ["Li", "Fe", "P", "O"] # alternate system example open_elements_specific = None # e.g., {Element("O"): 0} where 0 is the specific chemical potential open_element_all = Element( "O" ) # plot a series of open phase diagrams at critical chem pots with this element open mpr = MPRester(MAPI_KEY) # object for connecting to MP Rest interface # get data entries = mpr.get_entries_in_chemsys(system, compatible_only=True) if open_elements_specific: gcpd = GrandPotentialPhaseDiagram(entries, open_elements_specific) plot_pd(gcpd, False) analyze_pd(gcpd) if open_element_all: pd = PhaseDiagram(entries) chempots = pd.get_transition_chempots(open_element_all) all_gcpds = list() toplot = [] arquivo = open("dados.txt", "w") for idx in range(len(chempots)): if idx == len(chempots) - 1: avgchempot = chempots[idx] - 0.1 else: avgchempot = 0.5 * (chempots[idx] + chempots[idx + 1]) gcpd = GrandPotentialPhaseDiagram(entries,
def setUp(self): self.entries = [ ComputedEntry(Composition("Li"), 0), ComputedEntry(Composition("Mn"), 0), ComputedEntry(Composition("O2"), 0), ComputedEntry(Composition("MnO2"), -10), ComputedEntry(Composition("Mn2O4"), -60), ComputedEntry(Composition("MnO3"), 20), ComputedEntry(Composition("Li2O"), -10), ComputedEntry(Composition("Li2O2"), -8), ComputedEntry(Composition("LiMnO2"), -30), ] self.pd = PhaseDiagram(self.entries) chempots = {Element("Li"): -3} self.gpd = GrandPotentialPhaseDiagram(self.entries, chempots) ir_0 = InterfacialReactivity( c1=Composition("O2"), c2=Composition("Mn"), pd=self.pd, norm=False, use_hull_energy=False, ) ir_1 = GrandPotentialInterfacialReactivity( c1=Composition("MnO2"), c2=Composition("Mn"), grand_pd=self.gpd, pd_non_grand=self.pd, norm=False, include_no_mixing_energy=True, use_hull_energy=False, ) ir_2 = GrandPotentialInterfacialReactivity( c1=Composition("Mn"), c2=Composition("O2"), grand_pd=self.gpd, pd_non_grand=self.pd, norm=True, include_no_mixing_energy=True, use_hull_energy=False, ) ir_3 = GrandPotentialInterfacialReactivity( c1=Composition("Li2O"), c2=Composition("Mn"), grand_pd=self.gpd, norm=False, include_no_mixing_energy=True, pd_non_grand=self.pd, use_hull_energy=False, ) ir_4 = GrandPotentialInterfacialReactivity( c1=Composition("Mn"), c2=Composition("O2"), grand_pd=self.gpd, norm=True, include_no_mixing_energy=False, pd_non_grand=self.pd, use_hull_energy=False, ) ir_5 = GrandPotentialInterfacialReactivity( c1=Composition("Mn"), c2=Composition("Li2O"), grand_pd=self.gpd, pd_non_grand=self.pd, norm=True, include_no_mixing_energy=True, use_hull_energy=False, ) ir_6 = InterfacialReactivity( c1=Composition("Li2O2"), c2=Composition("Li"), pd=self.pd, norm=False, use_hull_energy=True, ) ir_7 = InterfacialReactivity( c1=Composition("Li2O2"), c2=Composition("Li"), pd=self.pd, norm=False, use_hull_energy=False, ) ir_8 = GrandPotentialInterfacialReactivity( c1=Composition("Li2O2"), c2=Composition("MnO2"), grand_pd=self.gpd, pd_non_grand=self.pd, norm=False, include_no_mixing_energy=False, use_hull_energy=True, ) ir_9 = GrandPotentialInterfacialReactivity( c1=Composition("Li2O2"), c2=Composition("MnO2"), grand_pd=self.gpd, pd_non_grand=self.pd, norm=False, include_no_mixing_energy=False, use_hull_energy=False, ) ir_10 = InterfacialReactivity( Composition("O2"), Composition("Mn"), pd=self.pd, norm=True, use_hull_energy=False, ) ir_11 = GrandPotentialInterfacialReactivity( Composition("Li2O2"), Composition("Li2O2"), grand_pd=self.gpd, norm=True, include_no_mixing_energy=True, pd_non_grand=self.pd, use_hull_energy=False, ) ir_12 = InterfacialReactivity( Composition("Li2O2"), Composition("Li2O2"), pd=self.pd, norm=True, use_hull_energy=False, ) with self.assertRaises(Exception) as context1: ir_13 = InterfacialReactivity(Composition("Li2O2"), Composition("Li"), pd=self.gpd, norm=True) self.assertTrue( "Please use the GrandPotentialInterfacialReactivity " "class for interfacial reactions with open elements!" == str( context1.exception)) with self.assertRaises(Exception) as context2: ir_14 = GrandPotentialInterfacialReactivity( Composition("O2"), Composition("Mn"), grand_pd=self.gpd, pd_non_grand=None, norm=False, include_no_mixing_energy=True, ) self.assertTrue( "Please provide non-grand phase diagram to compute no_mixing_energy!" == str(context2.exception)) self.ir = [ ir_0, ir_1, ir_2, ir_3, ir_4, ir_5, ir_6, ir_7, ir_8, ir_9, ir_10, ir_11, ir_12 ]
def setUp(self): self.entries = [ ComputedEntry(Composition("Li"), 0), ComputedEntry(Composition("Mn"), 0), ComputedEntry(Composition("O2"), 0), ComputedEntry(Composition("MnO2"), -10), ComputedEntry(Composition("Mn2O4"), -60), ComputedEntry(Composition("MnO3"), 20), ComputedEntry(Composition("Li2O"), -10), ComputedEntry(Composition("Li2O2"), -8), ComputedEntry(Composition("LiMnO2"), -30), ] self.pd = PhaseDiagram(self.entries) chempots = {"Li": -3} self.gpd = GrandPotentialPhaseDiagram(self.entries, chempots) self.ir = [] # ir[0] self.ir.append( InterfacialReactivity( Composition("O2"), Composition("Mn"), self.pd, norm=0, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False, ) ) # ir[1] self.ir.append( InterfacialReactivity( Composition("MnO2"), Composition("Mn"), self.gpd, norm=0, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False, ) ) # ir[2] self.ir.append( InterfacialReactivity( Composition("Mn"), Composition("O2"), self.gpd, norm=1, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False, ) ) # ir[3] self.ir.append( InterfacialReactivity( Composition("Li2O"), Composition("Mn"), self.gpd, norm=0, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False, ) ) # ir[4] self.ir.append( InterfacialReactivity( Composition("Mn"), Composition("O2"), self.gpd, norm=1, include_no_mixing_energy=0, pd_non_grand=self.pd, use_hull_energy=False, ) ) # ir[5] self.ir.append( InterfacialReactivity( Composition("Mn"), Composition("Li2O"), self.gpd, norm=1, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False, ) ) # ir[6] self.ir.append( InterfacialReactivity( Composition("Li2O2"), Composition("Li"), self.pd, norm=0, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=True, ) ) # ir[7] self.ir.append( InterfacialReactivity( Composition("Li2O2"), Composition("Li"), self.pd, norm=0, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False, ) ) # ir[8] self.ir.append( InterfacialReactivity( Composition("Li2O2"), Composition("MnO2"), self.gpd, norm=0, include_no_mixing_energy=0, pd_non_grand=self.pd, use_hull_energy=True, ) ) # ir[9] self.ir.append( InterfacialReactivity( Composition("Li2O2"), Composition("MnO2"), self.gpd, norm=0, include_no_mixing_energy=0, pd_non_grand=self.pd, use_hull_energy=False, ) ) # ir[10] self.ir.append( InterfacialReactivity( Composition("O2"), Composition("Mn"), self.pd, norm=1, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False, ) ) # ir[11] self.ir.append( InterfacialReactivity( Composition("Li2O2"), Composition("Li2O2"), self.gpd, norm=1, include_no_mixing_energy=1, pd_non_grand=self.pd, use_hull_energy=False, ) ) # ir[12] self.ir.append( InterfacialReactivity( Composition("Li2O2"), Composition("Li2O2"), self.pd, norm=1, include_no_mixing_energy=0, pd_non_grand=None, use_hull_energy=False, ) ) with self.assertRaises(Exception) as context1: self.ir.append( InterfacialReactivity( Composition("Li2O2"), Composition("Li"), self.pd, norm=1, include_no_mixing_energy=1, pd_non_grand=None, ) ) self.assertTrue("Please provide grand phase diagram to compute no_mixing_energy!" == str(context1.exception)) with self.assertRaises(Exception) as context2: self.ir.append( InterfacialReactivity( Composition("O2"), Composition("Mn"), self.gpd, norm=0, include_no_mixing_energy=1, pd_non_grand=None, ) ) self.assertTrue( "Please provide non-grand phase diagram to compute no_mixing_energy!" == str(context2.exception) )
def find_intermediate_rxns(self, intermediates, targets, chempots=None): """ Identifies thermodynamically predicted reactions from intermediate to one or more targets using interfacial reaction method. This method has the unique benefit ( compared to the find_crossover_rxns method) of identifying reactions open to a specfic element or producing 3 or more products. Args: intermediates ([ComputedEntry]): List of intermediate entries targets ([ComputedEntry]): List of target entries chempots ({Element: float}): Dictionary of chemical potentials used to create grand potential phase diagram by which interfacial reactions are predicted. Returns: [ComputedReaction]: List of intermediate reactions """ all_rxns = set() combos = list(generate_all_combos(intermediates, 2)) for entries in tqdm(combos): n = len(entries) r1 = entries[0].composition.reduced_composition chemsys = { str(el) for entry in entries for el in entry.composition.elements } elem = None if chempots: elem = str(list(chempots.keys())[0]) chemsys.update(elem) if chemsys == {elem}: continue if n == 1: r2 = entries[0].composition.reduced_composition elif n == 2: r2 = entries[1].composition.reduced_composition else: raise ValueError( "Can't have an interface that is not 1 to 2 entries!") if chempots: elem_comp = Composition(elem).reduced_composition if r1 == elem_comp or r2 == elem_comp: continue entry_subset = self.entry_set.get_subset_in_chemsys(list(chemsys)) pd = PhaseDiagram(entry_subset) grand_pd = None if chempots: grand_pd = GrandPotentialPhaseDiagram(entry_subset, chempots) rxns = react_interface(r1, r2, pd, self.num_entries, grand_pd) rxns_filtered = { r for r in rxns if set(r._product_entries) & targets } if rxns_filtered: most_favorable_rxn = min( rxns_filtered, key=lambda x: (x.calculated_reaction_energy / sum( [x.get_el_amount(elem) for elem in x.elements])), ) all_rxns.add(most_favorable_rxn) return all_rxns
def get_phase_diagram_data(self): """ Returns grand potential phase diagram data to external plot Assumes openelement specific element equals None :return: Data to external plot """ open_elements_specific = None open_element_all = Element(self.open_element) mpr = MPRester(settings.apiKey) drone = VaspToComputedEntryDrone() queen = BorgQueen(drone, rootpath=".") entries = queen.get_data() # Get data to make phase diagram mp_entries = mpr.get_entries_in_chemsys(self.system, compatible_only=True) entries.extend(mp_entries) compat = MaterialsProjectCompatibility() entries = compat.process_entries(entries) #explanation_output = open("explain.txt",'w') #entries_output = open("entries.txt", 'w') compat.explain(entries[0]) #print(entries, file=entries_output) if open_elements_specific: gcpd = GrandPotentialPhaseDiagram(entries, open_elements_specific) self.plot_phase_diagram(gcpd, False) self.analyze_phase_diagram(gcpd) if open_element_all: pd = PhaseDiagram(entries) chempots = pd.get_transition_chempots(open_element_all) # print(chempots) #all_gcpds = list() toplot = [] # dic = {} for idx in range(len(chempots)): if idx == len(chempots) - 1: avgchempot = chempots[idx] - 0.1 else: avgchempot = 0.5 * (chempots[idx] + chempots[idx + 1]) gcpd = GrandPotentialPhaseDiagram( entries, {open_element_all: avgchempot}, pd.elements) # min_chempot = None if idx == len( # chempots) - 1 else chempots[idx + 1] # max_chempot = chempots[idx] #gcpd = GrandPotentialPhaseDiagram(entries, {open_element_all: max_chempot}, pd.elements) toplot.append(self.get_grand_potential_phase_diagram(gcpd)) # toplot.append(max_chempot) #self.plot_phase_diagram(gcpd, False) #print({open_element_all: max_chempot}) all_phase_diagrams = toplot # print(all_phase_diagrams) number_of_phase_diagrams = len(all_phase_diagrams) #pd3 = PhaseDiagram(entries) chempot_list = pd.get_transition_chempots(open_element_all) pd_index = 0 chempots_range_of_each_phase = {} for particular_phase_diagram in all_phase_diagrams: chempot = chempot_list[pd_index] if pd_index is not number_of_phase_diagrams - 1: next_chempot = chempot_list[pd_index + 1] else: next_chempot = chempot_list[pd_index] - 2.0 chempot_range = [chempot, next_chempot] phases_list = particular_phase_diagram[0] for phase in phases_list: if phase in chempots_range_of_each_phase.keys(): chempots_range_of_each_phase[phase][1] = next_chempot.copy( ) else: chempots_range_of_each_phase[phase] = chempot_range.copy() pd_index = pd_index + 1 return chempots_range_of_each_phase
def _gppd(self): chempots = {Element(self.wi): self.mu_wi} return GrandPotentialPhaseDiagram(self._pd.all_entries, chempots)
def setUp(self): self.entries = EntrySet.from_csv(str(module_dir / "pdentries_test.csv")) self.pd = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -5}) self.pd6 = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -6})
elements = list(set(elements)) # Remove duplicates # Get all entries in the chemical system entries = mpr.get_entries_in_chemsys(elements) # Build a phase diagram using these entries. pd = PhaseDiagram(entries) # For an open system, include the grand potential phase diagram. if grand: # Get the chemical potential of the pure subtance. mu = pd.get_transition_chempots(Element(open_el))[0] # Set the chemical potential in the elemental reservoir. chempots = {open_el: relative_mu + mu} # Build the grand potential phase diagram gpd = GrandPotentialPhaseDiagram(entries, chempots) # Create InterfacialReactivity object. interface = InterfacialReactivity(comp1, comp2, gpd, norm=True, include_no_mixing_energy=True, pd_non_grand=pd, use_hull_energy=False) else: interface = InterfacialReactivity(comp1, comp2, pd, norm=True, include_no_mixing_energy=False, pd_non_grand=None,