class PDAnalyzerTest(unittest.TestCase): def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PDEntryIO.from_csv(os.path.join(module_dir, "pdentries_test.csv")) self.pd = PhaseDiagram(entries) self.analyzer = PDAnalyzer(self.pd) def test_get_e_above_hull(self): for entry in self.pd.stable_entries: self.assertLess(self.analyzer.get_e_above_hull(entry), 1e-11, "Stable entries should have e above hull of zero!") for entry in self.pd.all_entries: if entry not in self.pd.stable_entries: e_ah = self.analyzer.get_e_above_hull(entry) self.assertGreaterEqual(e_ah, 0) self.assertTrue(isinstance(e_ah, Number)) def test_get_equilibrium_reaction_energy(self): for entry in self.pd.stable_entries: self.assertLessEqual( self.analyzer.get_equilibrium_reaction_energy(entry), 0, "Stable entries should have negative equilibrium reaction energy!") def test_get_decomposition(self): for entry in self.pd.stable_entries: self.assertEquals(len(self.analyzer.get_decomposition(entry.composition)), 1, "Stable composition should have only 1 decomposition!") dim = len(self.pd.elements) for entry in self.pd.all_entries: ndecomp = len(self.analyzer.get_decomposition(entry.composition)) self.assertTrue(ndecomp > 0 and ndecomp <= dim, "The number of decomposition phases can at most be equal to the number of components.") #Just to test decomp for a ficitious composition ansdict = {entry.composition.formula: amt for entry, amt in self.analyzer.get_decomposition(Composition("Li3Fe7O11")).items()} expected_ans = {"Fe2 O2": 0.0952380952380949, "Li1 Fe1 O2": 0.5714285714285714, "Fe6 O8": 0.33333333333333393} for k, v in expected_ans.items(): self.assertAlmostEqual(ansdict[k], v) def test_get_transition_chempots(self): for el in self.pd.elements: self.assertLessEqual(len(self.analyzer.get_transition_chempots(el)), len(self.pd.facets)) def test_get_element_profile(self): for el in self.pd.elements: for entry in self.pd.stable_entries: if not (entry.composition.is_element): self.assertLessEqual(len(self.analyzer.get_element_profile(el, entry.composition)), len(self.pd.facets)) def test_get_get_chempot_range_map(self): elements = [el for el in self.pd.elements if el.symbol != "Fe"] self.assertEqual(len(self.analyzer.get_chempot_range_map(elements)), 10)
def get_decomp(o_chem_pot, mycomp, verbose=1): """Get decomposition from open phase diagram Args: o_chem_pot <float>: Oxygen chemical potential mycomp <pymatgen Composition>: Composition verbose <int>: 1 - verbose (default) 0 - silent Returns: decomposition string """ a = MPRester("<YOUR_MPREST_API_KEY_HERE>") elements = mycomp.elements ellist = map(str, elements) entries = a.get_entries_in_chemsys(ellist) #entries = a.get_entries_in_chemsys(['La', 'Mn', 'O', 'Fe']) pd = PhaseDiagram(entries) gppd = GrandPotentialPhaseDiagram(entries, {Element('O'): float(o_chem_pot)}) print gppd #plotter = PDPlotter(gppd) #plotter.show() gppda = PDAnalyzer(gppd) #mychempots = gppda.get_composition_chempots(mycomp) #print "My chem pots:" #print mychempots mydecompgppd = gppda.get_decomposition(mycomp) #pdentry = PDEntry(mycomp, 0) #print "Decomp and energy:" #decompandenergy = gppda.get_decomp_and_e_above_hull(pdentry) #print decompandenergy #mydecomppd = pda.get_decomposition(mycomp) #print "Mn profile:" #mnprof= gppda.get_element_profile(Element('Mn'),mycomp) #print mnprof if verbose: for (entry, amount) in mydecompgppd.iteritems(): print "%s: %3.3f" % (entry.name, amount) #mymurangegppd = gppda.getmu_range_stability_phase(Composition(entry.name),Element('O')) #print mymurangegppd #for (entry,amount) in mydecomppd.iteritems(): # print "%s: %3.3f" % (entry.name, amount) print "" return mydecompgppd
def get_decomp(o_chem_pot, mycomp, verbose=1): """Get decomposition from open phase diagram Args: o_chem_pot <float>: Oxygen chemical potential mycomp <pymatgen Composition>: Composition verbose <int>: 1 - verbose (default) 0 - silent Returns: decomposition string """ a = MPRester("<YOUR_MPREST_API_KEY_HERE>") elements = mycomp.elements ellist = map(str, elements) entries = a.get_entries_in_chemsys(ellist) #entries = a.get_entries_in_chemsys(['La', 'Mn', 'O', 'Fe']) pd = PhaseDiagram(entries) gppd = GrandPotentialPhaseDiagram(entries,{Element('O'): float(o_chem_pot)}) print gppd #plotter = PDPlotter(gppd) #plotter.show() gppda = PDAnalyzer(gppd) #mychempots = gppda.get_composition_chempots(mycomp) #print "My chem pots:" #print mychempots mydecompgppd = gppda.get_decomposition(mycomp) #pdentry = PDEntry(mycomp, 0) #print "Decomp and energy:" #decompandenergy = gppda.get_decomp_and_e_above_hull(pdentry) #print decompandenergy #mydecomppd = pda.get_decomposition(mycomp) #print "Mn profile:" #mnprof= gppda.get_element_profile(Element('Mn'),mycomp) #print mnprof if verbose: for (entry,amount) in mydecompgppd.iteritems(): print "%s: %3.3f" % (entry.name, amount) #mymurangegppd = gppda.getmu_range_stability_phase(Composition(entry.name),Element('O')) #print mymurangegppd #for (entry,amount) in mydecomppd.iteritems(): # print "%s: %3.3f" % (entry.name, amount) print "" return mydecompgppd
class PDAnalyzerTest(unittest.TestCase): def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PDEntryIO.from_csv(os.path.join(module_dir, "pdentries_test.csv")) self.pd = PhaseDiagram(entries) self.analyzer = PDAnalyzer(self.pd) def test_get_e_above_hull(self): for entry in self.pd.stable_entries: self.assertLess(self.analyzer.get_e_above_hull(entry), 1e-11, "Stable entries should have e above hull of zero!") for entry in self.pd.all_entries: if entry not in self.pd.stable_entries: e_ah = self.analyzer.get_e_above_hull(entry) self.assertGreaterEqual(e_ah, 0) self.assertTrue(isinstance(e_ah, Number)) def test_get_equilibrium_reaction_energy(self): for entry in self.pd.stable_entries: self.assertLessEqual( self.analyzer.get_equilibrium_reaction_energy(entry), 0, "Stable entries should have negative equilibrium reaction energy!") def test_get_decomposition(self): for entry in self.pd.stable_entries: self.assertEquals(len(self.analyzer.get_decomposition(entry.composition)), 1, "Stable composition should have only 1 decomposition!") dim = len(self.pd.elements) for entry in self.pd.all_entries: ndecomp = len(self.analyzer.get_decomposition(entry.composition)) self.assertTrue(ndecomp > 0 and ndecomp <= dim, "The number of decomposition phases can at most be equal to the number of components.") #Just to test decomp for a ficitious composition ansdict = {entry.composition.formula: amt for entry, amt in self.analyzer.get_decomposition(Composition("Li3Fe7O11")).items()} expected_ans = {"Fe2 O2": 0.0952380952380949, "Li1 Fe1 O2": 0.5714285714285714, "Fe6 O8": 0.33333333333333393} for k, v in expected_ans.items(): self.assertAlmostEqual(ansdict[k], v) def test_get_transition_chempots(self): for el in self.pd.elements: self.assertLessEqual(len(self.analyzer.get_transition_chempots(el)), len(self.pd.facets)) def test_get_element_profile(self): for el in self.pd.elements: for entry in self.pd.stable_entries: if not (entry.composition.is_element): self.assertLessEqual(len(self.analyzer.get_element_profile(el, entry.composition)), len(self.pd.facets)) def test_get_get_chempot_range_map(self): elements = [el for el in self.pd.elements if el.symbol != "Fe"] self.assertEqual(len(self.analyzer.get_chempot_range_map(elements)), 10) def test_getmu_vertices_stability_phase(self): results = self.analyzer.getmu_vertices_stability_phase(Composition.from_formula("LiFeO2"), Element("O")) self.assertAlmostEqual(len(results), 6) test_equality = False for c in results: if abs(c[Element("O")]+7.115) < 1e-2 and abs(c[Element("Fe")]+6.596) < 1e-2 and \ abs(c[Element("Li")]+3.931) < 1e-2: test_equality = True self.assertTrue(test_equality,"there is an expected vertex missing in the list") def test_getmu_range_stability_phase(self): results = self.analyzer.get_chempot_range_stability_phase( Composition("LiFeO2"), Element("O")) self.assertAlmostEqual(results[Element("O")][1], -4.4501812249999997) self.assertAlmostEqual(results[Element("Fe")][0], -6.5961470999999996) self.assertAlmostEqual(results[Element("Li")][0], -3.6250022625000007)
class PDAnalyzerTest(unittest.TestCase): def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PDEntryIO.from_csv( os.path.join(module_dir, "pdentries_test.csv")) self.pd = PhaseDiagram(entries) self.analyzer = PDAnalyzer(self.pd) def test_get_e_above_hull(self): for entry in self.pd.stable_entries: self.assertLess( self.analyzer.get_e_above_hull(entry), 1e-11, "Stable entries should have e above hull of zero!") for entry in self.pd.all_entries: if entry not in self.pd.stable_entries: e_ah = self.analyzer.get_e_above_hull(entry) self.assertGreaterEqual(e_ah, 0) self.assertTrue(isinstance(e_ah, Number)) def test_get_equilibrium_reaction_energy(self): for entry in self.pd.stable_entries: self.assertLessEqual( self.analyzer.get_equilibrium_reaction_energy(entry), 0, "Stable entries should have negative equilibrium reaction energy!" ) def test_get_decomposition(self): for entry in self.pd.stable_entries: self.assertEqual( len(self.analyzer.get_decomposition(entry.composition)), 1, "Stable composition should have only 1 decomposition!") dim = len(self.pd.elements) for entry in self.pd.all_entries: ndecomp = len(self.analyzer.get_decomposition(entry.composition)) self.assertTrue( ndecomp > 0 and ndecomp <= dim, "The number of decomposition phases can at most be equal to the number of components." ) #Just to test decomp for a ficitious composition ansdict = { entry.composition.formula: amt for entry, amt in self.analyzer.get_decomposition( Composition("Li3Fe7O11")).items() } expected_ans = { "Fe2 O2": 0.0952380952380949, "Li1 Fe1 O2": 0.5714285714285714, "Fe6 O8": 0.33333333333333393 } for k, v in expected_ans.items(): self.assertAlmostEqual(ansdict[k], v) def test_get_transition_chempots(self): for el in self.pd.elements: self.assertLessEqual( len(self.analyzer.get_transition_chempots(el)), len(self.pd.facets)) def test_get_element_profile(self): for el in self.pd.elements: for entry in self.pd.stable_entries: if not (entry.composition.is_element): self.assertLessEqual( len( self.analyzer.get_element_profile( el, entry.composition)), len(self.pd.facets)) def test_get_get_chempot_range_map(self): elements = [el for el in self.pd.elements if el.symbol != "Fe"] self.assertEqual(len(self.analyzer.get_chempot_range_map(elements)), 10) def test_getmu_vertices_stability_phase(self): results = self.analyzer.getmu_vertices_stability_phase( Composition("LiFeO2"), Element("O")) self.assertAlmostEqual(len(results), 6) test_equality = False for c in results: if abs(c[Element("O")]+7.115) < 1e-2 and abs(c[Element("Fe")]+6.596) < 1e-2 and \ abs(c[Element("Li")]+3.931) < 1e-2: test_equality = True self.assertTrue(test_equality, "there is an expected vertex missing in the list") def test_getmu_range_stability_phase(self): results = self.analyzer.get_chempot_range_stability_phase( Composition("LiFeO2"), Element("O")) self.assertAlmostEqual(results[Element("O")][1], -4.4501812249999997) self.assertAlmostEqual(results[Element("Fe")][0], -6.5961470999999996) self.assertAlmostEqual(results[Element("Li")][0], -3.6250022625000007) def test_get_hull_energy(self): for entry in self.pd.stable_entries: h_e = self.analyzer.get_hull_energy(entry.composition) self.assertAlmostEqual(h_e, entry.energy) n_h_e = self.analyzer.get_hull_energy( entry.composition.fractional_composition) self.assertAlmostEqual(n_h_e, entry.energy_per_atom) def test_1d_pd(self): entry = PDEntry('H', 0) pd = PhaseDiagram([entry]) pda = PDAnalyzer(pd) decomp, e = pda.get_decomp_and_e_above_hull(PDEntry('H', 1)) self.assertAlmostEqual(e, 1) self.assertAlmostEqual(decomp[entry], 1.0)
print "Run contains formula {} with corrected energy {:.3f} eV.".format( entry.composition, entry.energy ) print "Energy above convex hull = {:.1f} meV".format(ehull) if ehull < 1: print "Entry is stable." elif ehull < 30: print "Entry is metastable and could be stable at finite temperatures." elif ehull < 50: print "Entry has a low probability of being stable." else: print "Entry is very unlikely to be stable." if ehull > 0: decomp = analyzer.get_decomposition(entry.composition) print {e.composition.formula: k for e, k in decomp.items()} if __name__ == "__main__": parser = argparse.ArgumentParser(description=""" This is a simple phase stability estimation script which utilizes the Materials API and pymatgen to calculate the phase stability of a single material.""", epilog=""" Author: Shyue Ping Ong Version: {} Last updated: {}""".format(__version__, __date__)) parser.add_argument("directory", metavar="dir", type=str, help="directory containing vasp run to process") parser.add_argument("-k", "--key", dest="api_key", type=str, required=True,
class PDAnalyzerTest(unittest.TestCase): def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PDEntryIO.from_csv( os.path.join(module_dir, "pdentries_test.csv")) self.pd = PhaseDiagram(entries) self.analyzer = PDAnalyzer(self.pd) def test_get_e_above_hull(self): for entry in self.pd.stable_entries: self.assertLess( self.analyzer.get_e_above_hull(entry), 1e-11, "Stable entries should have e above hull of zero!") for entry in self.pd.all_entries: if entry not in self.pd.stable_entries: self.assertGreaterEqual(self.analyzer.get_e_above_hull(entry), 0) def test_get_equilibrium_reaction_energy(self): for entry in self.pd.stable_entries: self.assertLessEqual( self.analyzer.get_equilibrium_reaction_energy(entry), 0, "Stable entries should have negative equilibrium reaction energy!" ) def test_get_decomposition(self): for entry in self.pd.stable_entries: self.assertEquals( len(self.analyzer.get_decomposition(entry.composition)), 1, "Stable composition should have only 1 decomposition!") dim = len(self.pd.elements) for entry in self.pd.all_entries: ndecomp = len(self.analyzer.get_decomposition(entry.composition)) self.assertTrue( ndecomp > 0 and ndecomp <= dim, "The number of decomposition phases can at most be equal to the number of components." ) #Just to test decomp for a ficitious composition ansdict = { entry.composition.formula: amt for entry, amt in self.analyzer.get_decomposition( Composition("Li3Fe7O11")).items() } expected_ans = { "Fe2 O2": 0.0952380952380949, "Li1 Fe1 O2": 0.5714285714285714, "Fe6 O8": 0.33333333333333393 } for k, v in expected_ans.items(): self.assertAlmostEqual(ansdict[k], v) def test_get_transition_chempots(self): for el in self.pd.elements: self.assertLessEqual( len(self.analyzer.get_transition_chempots(el)), len(self.pd.facets)) def test_get_element_profile(self): for el in self.pd.elements: for entry in self.pd.stable_entries: if not (entry.composition.is_element): self.assertLessEqual( len( self.analyzer.get_element_profile( el, entry.composition)), len(self.pd.facets)) def test_get_get_chempot_range_map(self): elements = [el for el in self.pd.elements if el.symbol != "Fe"] self.assertEqual(len(self.analyzer.get_chempot_range_map(elements)), 10)