예제 #1
0
def e_above(formula, energy):


	#formula = 'Li6AsN'
	#energy = -27.53
	comp=Composition(formula)
	target = PDEntry(Composition(formula), energy)

	elements = list(comp.as_dict().keys())
	#print(elements)

	a = MPRester("API_KEY") #Go to materialsproject.org and create account to get API_KEY

	#Entries are the basic unit for thermodynamic and other analyses in pymatgen.
	#This gets all entries belonging to the Ca-C-O system.
	# entries = a.get_entries_in_chemsys(['Ca', 'C', 'O'])
	entries = a.get_entries_in_chemsys(elements)
	#print(entries)

	pd=PD(entries)

	# pd.get_decomposition(comp)

	ehull = pd.get_e_above_hull(target)

	#plotter = PDPlotter(pd)
	#plotter.show() 

	return ehull
예제 #2
0
 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"])
예제 #3
0
 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"])
예제 #4
0
def get_e_above_hull(formula, energy):
    atoms = Atoms(formula)
    full_symbols = atoms.get_chemical_symbols()
    symbols, counts = np.unique(full_symbols, return_counts=True)

    # list(set(atoms.get_chemical_symbols()))

    with MPRester() as m:
        data = m.get_entries_in_chemsys(symbols,
                                        compatible_only=True,
                                        property_data=[
                                            'energy_per_atom',
                                            'unit_cell_formula',
                                            'pretty_formula'
                                        ])
    PDentries = []

    for d in data:
        d = d.as_dict()
        PDentries += [PDEntry(d['data']['unit_cell_formula'], d['energy'])]
        print(d['data']['pretty_formula'], d['energy'])

    PD = PhaseDiagram(PDentries)

    # Need to apply MP corrections to +U calculations
    # MP advanced correction + anion correction

    #print(energy * 2, energy * 2 +  corr_energy * 2)

    PDE0 = PDEntry(formula, energy)
    e_hull = PD.get_e_above_hull(PDE0)

    return e_hull
예제 #5
0
    def get_precursor_library(self):
        phased = PhaseDiagram(self.entries)
        if self.confine_to_stables:
            precursor_library = list(phased.stable_entries)
        elif self.hull_distance is not None:
            precursor_library = [
                e for e in self.entries
                if phased.get_e_above_hull(e) <= self.hull_distance
            ]
        else:
            precursor_library = [e for e in self.entries]
        if self.confine_to_icsd:
            precursor_library = [
                i for i in precursor_library if i.data["icsd_ids"]
            ]

        if self.simple_precursors:
            precursor_library = [
                i for i in precursor_library if len(i.composition.elements) <
                len(self.target_entry.composition.elements) -
                self.simple_precursors + 1
            ]

        if self.target_entry in precursor_library:
            precursor_library.pop(precursor_library.index(self.target_entry))

        if self.explicit_includes:
            print("explicitly including: ", self.explicit_includes)
            for entry_id in self.explicit_includes:
                try:
                    entry = [
                        e for e in self.entries if e.entry_id == entry_id
                    ][0]
                except IndexError:
                    print("Could not find {} in entry list".format(entry_id))
                    continue
                if entry not in precursor_library:
                    precursor_library.append(entry)

        if self.exclude_compositions:
            precursor_library = [
                i for i in precursor_library if i.composition.reduced_formula
                not in self.exclude_compositions
            ]

        self.precursor_library = precursor_library

        print(
            "Total # of precursors materials obeying the provided filters: ",
            len(precursor_library),
        )
        return self.precursor_library
예제 #6
0
    def test_dim1(self):
        # Ensure that dim 1 PDs can be generated.
        for el in ["Li", "Fe", "O2"]:
            entries = [e for e in self.entries if e.composition.reduced_formula == el]
            pd = PhaseDiagram(entries)
            self.assertEqual(len(pd.stable_entries), 1)

            for e in entries:
                ehull = pd.get_e_above_hull(e)
                self.assertGreaterEqual(ehull, 0)

            plotter = PDPlotter(pd)
            lines, *_ = plotter.pd_plot_data
            self.assertEqual(lines[0][1], [0, 0])
def recheck_e_above_hull(material_id, key_element):
    with MPRester(api_key='') as mpr:
        entry = mpr.get_entry_by_material_id(material_id)
        pretty_formula = entry.name
        chemsys = Composition(
            pretty_formula).chemical_system + '-' + key_element
        # using GGA and GGA+U mixed scheme as default, namely compatible_only=True
        entries = mpr.get_entries_in_chemsys(chemsys)

    phase_diagram = PhaseDiagram(entries)
    e_above_hull = phase_diagram.get_e_above_hull(entry)
    # to avoid kind of values -1.77635683940025E-15, and -0.000 after rounded
    if 0 > e_above_hull >= -phase_diagram.numerical_tol:
        e_above_hull = 0.0

    return (e_above_hull)
예제 #8
0
class PhaseDiagramTest(unittest.TestCase):
    def setUp(self):
        self.entries = EntrySet.from_csv(str(module_dir /
                                             "pdentries_test.csv"))
        self.pd = PhaseDiagram(self.entries)
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.simplefilter("default")

    def test_init(self):
        # Ensure that a bad set of entries raises a PD error. Remove all Li
        # from self.entries.
        entries = filter(
            lambda e: (not e.composition.is_element) or e.composition.elements[
                0] != Element("Li"),
            self.entries,
        )
        self.assertRaises(PhaseDiagramError, PhaseDiagram, entries)

    def test_dim1(self):
        # Ensure that dim 1 PDs can eb generated.
        for el in ["Li", "Fe", "O2"]:
            entries = [
                e for e in self.entries if e.composition.reduced_formula == el
            ]
            pd = PhaseDiagram(entries)
            self.assertEqual(len(pd.stable_entries), 1)

            for e in entries:
                decomp, ehull = pd.get_decomp_and_e_above_hull(e)
                self.assertGreaterEqual(ehull, 0)
            plotter = PDPlotter(pd)
            lines, stable_entries, unstable_entries = plotter.pd_plot_data
            self.assertEqual(lines[0][1], [0, 0])

    def test_ordering(self):
        # Test sorting of elements
        entries = [
            ComputedEntry(Composition(formula), 0)
            for formula in ["O", "N", "Fe"]
        ]
        pd = PhaseDiagram(entries)
        sorted_elements = (Element("Fe"), Element("N"), Element("O"))
        self.assertEqual(tuple(pd.elements), sorted_elements)

        entries.reverse()
        pd = PhaseDiagram(entries)
        self.assertEqual(tuple(pd.elements), sorted_elements)

        # Test manual specification of order
        ordering = [Element(elt_string) for elt_string in ["O", "N", "Fe"]]
        pd = PhaseDiagram(entries, elements=ordering)
        self.assertEqual(tuple(pd.elements), tuple(ordering))

    def test_stable_entries(self):
        stable_formulas = [
            ent.composition.reduced_formula for ent in self.pd.stable_entries
        ]
        expected_stable = [
            "Fe2O3",
            "Li5FeO4",
            "LiFeO2",
            "Fe3O4",
            "Li",
            "Fe",
            "Li2O",
            "O2",
            "FeO",
        ]
        for formula in expected_stable:
            self.assertTrue(formula in stable_formulas,
                            formula + " not in stable entries!")

    def test_get_formation_energy(self):
        stable_formation_energies = {
            ent.composition.reduced_formula: self.pd.get_form_energy(ent)
            for ent in self.pd.stable_entries
        }
        expected_formation_energies = {
            "Li5FeO4": -164.8117344866667,
            "Li2O2": -14.119232793333332,
            "Fe2O3": -16.574164339999996,
            "FeO": -5.7141519966666685,
            "Li": 0.0,
            "LiFeO2": -7.732752316666666,
            "Li2O": -6.229303868333332,
            "Fe": 0.0,
            "Fe3O4": -22.565714456666683,
            "Li2FeO3": -45.67166036000002,
            "O2": 0.0,
        }
        for formula, energy in expected_formation_energies.items():
            self.assertAlmostEqual(energy, stable_formation_energies[formula],
                                   7)

    def test_all_entries_hulldata(self):
        self.assertEqual(len(self.pd.all_entries_hulldata), 492)

    def test_planar_inputs(self):
        e1 = PDEntry("H", 0)
        e2 = PDEntry("He", 0)
        e3 = PDEntry("Li", 0)
        e4 = PDEntry("Be", 0)
        e5 = PDEntry("B", 0)
        e6 = PDEntry("Rb", 0)

        pd = PhaseDiagram([e1, e2, e3, e4, e5, e6],
                          map(Element, ["Rb", "He", "B", "Be", "Li", "H"]))

        self.assertEqual(len(pd.facets), 1)

    def test_str(self):
        self.assertIsNotNone(str(self.pd))

    def test_get_e_above_hull(self):
        for entry in self.pd.stable_entries:
            self.assertLess(
                self.pd.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.pd.get_e_above_hull(entry)
                self.assertTrue(isinstance(e_ah, Number))
                self.assertGreaterEqual(e_ah, 0)

    def test_get_equilibrium_reaction_energy(self):
        for entry in self.pd.stable_entries:
            self.assertLessEqual(
                self.pd.get_equilibrium_reaction_energy(entry),
                0,
                "Stable entries should have negative equilibrium reaction energy!",
            )

    def test_get_quasi_e_to_hull(self):
        for entry in self.pd.unstable_entries:
            # catch duplicated stable entries
            if entry.normalize(
                    inplace=False) in self.pd.get_stable_entries_normed():
                self.assertLessEqual(
                    self.pd.get_quasi_e_to_hull(entry),
                    0,
                    "Duplicated stable entries should have negative decomposition energy!",
                )
            else:
                self.assertGreaterEqual(
                    self.pd.get_quasi_e_to_hull(entry),
                    0,
                    "Unstable entries should have positive decomposition energy!",
                )

        for entry in self.pd.stable_entries:
            if entry.composition.is_element:
                self.assertEqual(
                    self.pd.get_quasi_e_to_hull(entry),
                    0,
                    "Stable elemental entries should have decomposition energy of zero!",
                )
            else:
                self.assertLessEqual(
                    self.pd.get_quasi_e_to_hull(entry),
                    0,
                    "Stable entries should have negative decomposition energy!",
                )

        novel_stable_entry = PDEntry("Li5FeO4", -999)
        self.assertLess(
            self.pd.get_quasi_e_to_hull(novel_stable_entry),
            0,
            "Novel stable entries should have negative decomposition energy!",
        )

        novel_unstable_entry = PDEntry("Li5FeO4", 999)
        self.assertGreater(
            self.pd.get_quasi_e_to_hull(novel_unstable_entry),
            0,
            "Novel unstable entries should have positive decomposition energy!",
        )

        duplicate_entry = PDEntry("Li2O", -14.31361175)
        scaled_dup_entry = PDEntry("Li4O2", -14.31361175 * 2)
        stable_entry = [e for e in self.pd.stable_entries
                        if e.name == "Li2O"][0]

        self.assertEqual(
            self.pd.get_quasi_e_to_hull(duplicate_entry),
            self.pd.get_quasi_e_to_hull(stable_entry),
            "Novel duplicates of stable entries should have same decomposition energy!",
        )

        self.assertEqual(
            self.pd.get_quasi_e_to_hull(scaled_dup_entry),
            self.pd.get_quasi_e_to_hull(stable_entry),
            "Novel scaled duplicates of stable entries should have same decomposition energy!",
        )

    def test_get_decomposition(self):
        for entry in self.pd.stable_entries:
            self.assertEqual(
                len(self.pd.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.pd.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.pd.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.pd.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.pd.get_element_profile(el,
                                                        entry.composition)),
                        len(self.pd.facets),
                    )

        expected = [
            {
                "evolution": 1.0,
                "chempot": -4.2582781416666666,
                "reaction": "Li2O + 0.5 O2 -> Li2O2",
            },
            {
                "evolution": 0,
                "chempot": -5.0885906699999968,
                "reaction": "Li2O -> Li2O",
            },
            {
                "evolution": -1.0,
                "chempot": -10.487582010000001,
                "reaction": "Li2O -> 2 Li + 0.5 O2",
            },
        ]
        result = self.pd.get_element_profile(Element("O"), Composition("Li2O"))
        for d1, d2 in zip(expected, result):
            self.assertAlmostEqual(d1["evolution"], d2["evolution"])
            self.assertAlmostEqual(d1["chempot"], d2["chempot"])
            self.assertEqual(d1["reaction"], str(d2["reaction"]))

    def test_get_get_chempot_range_map(self):
        elements = [el for el in self.pd.elements if el.symbol != "Fe"]
        self.assertEqual(len(self.pd.get_chempot_range_map(elements)), 10)

    def test_getmu_vertices_stability_phase(self):
        results = self.pd.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.pd.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.pd.get_hull_energy(entry.composition)
            self.assertAlmostEqual(h_e, entry.energy)
            n_h_e = self.pd.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])
        decomp, e = pd.get_decomp_and_e_above_hull(PDEntry("H", 1))
        self.assertAlmostEqual(e, 1)
        self.assertAlmostEqual(decomp[entry], 1.0)

    def test_get_critical_compositions_fractional(self):
        c1 = Composition("Fe2O3").fractional_composition
        c2 = Composition("Li3FeO4").fractional_composition
        c3 = Composition("Li2O").fractional_composition

        comps = self.pd.get_critical_compositions(c1, c2)
        expected = [
            Composition("Fe2O3").fractional_composition,
            Composition("Li0.3243244Fe0.1621621O0.51351349"),
            Composition("Li3FeO4").fractional_composition,
        ]
        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("Fe0.4O0.6"),
            Composition("LiFeO2").fractional_composition,
            Composition("Li5FeO4").fractional_composition,
            Composition("Li2O").fractional_composition,
        ]
        for crit, exp in zip(comps, expected):
            self.assertTrue(crit.almost_equals(exp, rtol=0, atol=1e-5))

    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 test_get_composition_chempots(self):
        c1 = Composition("Fe3.1O4")
        c2 = Composition("Fe3.2O4.1Li0.01")

        e1 = self.pd.get_hull_energy(c1)
        e2 = self.pd.get_hull_energy(c2)

        cp = self.pd.get_composition_chempots(c1)
        calc_e2 = e1 + sum(cp[k] * v for k, v in (c2 - c1).items())
        self.assertAlmostEqual(e2, calc_e2)

    def test_get_all_chempots(self):
        c1 = Composition("Fe3.1O4")
        c2 = Composition("FeO")

        cp1 = self.pd.get_all_chempots(c1)
        cpresult = {
            Element("Li"): -4.077061954999998,
            Element("Fe"): -6.741593864999999,
            Element("O"): -6.969907375000003,
        }

        for elem, energy in cpresult.items():
            self.assertAlmostEqual(cp1["Fe3O4-FeO-LiFeO2"][elem], energy)

        cp2 = self.pd.get_all_chempots(c2)
        cpresult = {
            Element("O"): -7.115354140000001,
            Element("Fe"): -6.5961471,
            Element("Li"): -3.9316151899999987,
        }

        for elem, energy in cpresult.items():
            self.assertAlmostEqual(cp2["FeO-LiFeO2-Fe"][elem], energy)

    def test_to_from_dict(self):

        # test round-trip for other entry types such as ComputedEntry
        entry = ComputedEntry("H", 0.0, 0.0, entry_id="test")
        pd = PhaseDiagram([entry])
        d = pd.as_dict()
        pd_roundtrip = PhaseDiagram.from_dict(d)
        self.assertEqual(pd.all_entries[0].entry_id,
                         pd_roundtrip.all_entries[0].entry_id)
예제 #9
0
    def process_item(self, item):
        """
        Read the entries from the thermo database and group them based on the reduced composition
        of the framework material (without working ion).
        Args:
            chemsys(string): the chemical system string to be queried
        returns:
            (chemsys, [group]): entry contains a list of entries the materials together by composition
        """
        # sort the entries intro subgroups
        # then perform PD analysis
        all_entries = item['all_entries']
        pd_ents = item['pd_ents']
        phdi = PhaseDiagram(pd_ents)

        # The working ion entries
        ents_wion = list(
            filter(
                lambda x: x.composition.get_integer_formula_and_factor()[0] ==
                self.working_ion, pd_ents))
        self.working_ion_entry = min(ents_wion,
                                     key=lambda e: e.energy_per_atom)
        assert (self.working_ion_entry != None)

        grouped_entries = list(self.get_sorted_subgroups(all_entries))
        docs = []  # results

        for group in grouped_entries:
            self.logger.debug(
                f"Grouped entries in all sandboxes {', '.join([en.name for en in group])}"
            )
            for en in group:
                # skip this d_muO2 stuff if you do note have oxygen
                if Element('O') in en.composition.elements:
                    d_muO2 = [{
                        'reaction': str(itr['reaction']),
                        'chempot': itr['chempot'],
                        'evolution': itr['evolution']
                    } for itr in phdi.get_element_profile('O', en.composition)]
                else:
                    d_muO2 = None
                en.data['muO2'] = d_muO2
                en.data['decomposition_energy'] = phdi.get_e_above_hull(en)

            # sort out the sandboxes
            # for each sandbox core+sandbox will both contribute entries
            all_sbx = [ent.data['sbxn'] for ent in group]
            all_sbx = set(chain.from_iterable(all_sbx))
            self.logger.debug(f"All sandboxes {', '.join(list(all_sbx))}")

            for isbx in all_sbx:
                group_sbx = list(
                    filter(
                        lambda ent: (isbx in ent.data['sbxn']) or (ent.data[
                            'sbxn'] == ['core']), group))
                # Need more than one level of lithiation to define a electrode material
                if len(group_sbx) == 1:
                    continue
                self.logger.debug(
                    f"Grouped entries in sandbox {isbx} -- {', '.join([en.name for en in group_sbx])}"
                )
                try:
                    result = InsertionElectrode(group_sbx,
                                                self.working_ion_entry)
                    assert (len(result._stable_entries) > 1)
                except:
                    self.logger.warn(
                        f"Not able to generate a  entries in sandbox {isbx} using the following entires-- {', '.join([en.entry_id for en in group_sbx])}"
                    )
                    continue

                spacegroup = SpacegroupAnalyzer(
                    result.get_stable_entries(
                        charge_to_discharge=True)[0].structure)
                d = result.as_dict_summary()
                ids = [entry.entry_id for entry in result.get_all_entries()]
                lowest_id = sorted(ids, key=lambda x: x.split('-')[-1])[0]
                d['spacegroup'] = {
                    k: spacegroup._space_group_data[k]
                    for k in sg_fields
                }

                if isbx == 'core':
                    d['battid'] = lowest_id + '_' + self.working_ion
                else:
                    d['battid'] = lowest_id + '_' + self.working_ion + '_' + isbx
                # Only allow one sandbox value for each electrode
                d['sbxn'] = [isbx]

                docs.append(d)

        return docs
    # getting Composition Object
    comp = Composition(phase)
    # getting entry for PD Object
    entry = PDEntry(comp, computed_phases[phase])
    # building list of entries
    entries.append(entry)

# getting PD from list of entries
pd = PhaseDiagram(entries)

# get distance from convex hull for cubic phase
comp = Composition('NaNbO3')
energy = -38.26346361
entry = PDEntry(comp, energy)
cubic_instability = pd.get_e_above_hull(entry)

pd_dict = pd.as_dict()

# Getting Plot
plt = PDPlotter(pd, show_unstable=False)  # you can also try show_unstable=True

#plt_data = plt.pd_plot_data
# getting plot for chem potential - variables 'fontsize' for labels size and 'plotsize' for fig size have been added (not present in original pymatgen) to get_chempot_range_map_plot function
chem_pot_plot = plt.get_chempot_range_map_plot(
    [Element("Na"), Element("Nb")], fontsize=14, plotsize=1.5)
#plt.write_image("chem_pot_{}.png".format('-'.join(system)), "png")
chem_pot_plot.savefig(f'chem_pot_{system_name}.png')  # save figure
# getting plot for PD - variables 'fontsize' for labels size and plotsize for fig size have been added (not present in original pymatgen) to get_plot function
pd_plot = plt.get_plot(label_stable=True, fontsize=24, plotsize=3)
예제 #11
0
    def process_item(self, item):
        """
        Read the entries from the thermo database and group them based on the reduced composition
        of the framework material (without working ion).
        Args:
            chemsys(string): the chemical system string to be queried
        returns:
            (chemsys, [group]): entry contains a list of entries the materials together by composition
        """
        # sort the entries intro subgroups
        # then perform PD analysis
        all_entries = item["all_entries"]
        pd_ents = item["pd_ents"]
        phdi = PhaseDiagram(pd_ents)

        # The working ion entries
        ents_wion = list(
            filter(
                lambda x: x.composition.get_integer_formula_and_factor()[0]
                == self.working_ion,
                pd_ents,
            )
        )
        self.working_ion_entry = min(ents_wion, key=lambda e: e.energy_per_atom)
        assert self.working_ion_entry != None

        grouped_entries = list(self.get_sorted_subgroups(all_entries))

        docs = []  # results

        for group in grouped_entries:
            self.logger.debug(
                f"Grouped entries in all sandboxes {', '.join([en.name for en in group])}"
            )
            for en in group:
                # skip this d_muO2 stuff if you do note have oxygen
                if Element("O") in en.composition.elements:
                    d_muO2 = [
                        {
                            "reaction": str(itr["reaction"]),
                            "chempot": itr["chempot"],
                            "evolution": itr["evolution"],
                        }
                        for itr in phdi.get_element_profile("O", en.composition)
                    ]
                else:
                    d_muO2 = None
                en.data["muO2"] = d_muO2
                en.data["decomposition_energy"] = phdi.get_e_above_hull(en)

            # sort out the sandboxes
            # for each sandbox core+sandbox will both contribute entries
            all_sbx = [ent.data["_sbxn"] for ent in group]
            all_sbx = set(chain.from_iterable(all_sbx))
            self.logger.debug(f"All sandboxes {', '.join(list(all_sbx))}")

            for isbx in all_sbx:
                group_sbx = list(
                    filter(
                        lambda ent: (isbx in ent.data["_sbxn"])
                        or (ent.data["_sbxn"] == ["core"]),
                        group,
                    )
                )
                self.logger.debug(
                    f"Grouped entries in sandbox {', '.join([en.name for en in group_sbx])}"
                )

                result = InsertionElectrode(group_sbx, self.working_ion_entry)

                spacegroup = SpacegroupAnalyzer(
                    result.get_stable_entries(charge_to_discharge=True)[0].structure
                )

                d = result.as_dict_summary()

                # d['stable_material_ids'] = [entry.entry_id
                #                        for entry in result.get_stable_entries()]
                # d['unstable_material_ids'] = [entry.entry_id
                #                             for entry in result.get_unstable_entries()]
                # d['stability_data'] = {entry.entry_id : entry.data['decomposition_energy']
                #                               for entry in result.get_all_entries()}
                # d['muO2_data'] = {entry.entry_id : entry.data['muO2']
                #                        for entry in result.get_all_entries()}

                # sort the ids based on value
                ids = [entry.entry_id for entry in result.get_all_entries()]
                lowest_id = sorted(ids, key=lambda x: x.split("-")[-1])[0]
                d["spacegroup"] = {
                    k: spacegroup._space_group_data[k] for k in sg_fields
                }

                if isbx == "core":
                    d["battid"] = lowest_id + "_" + self.working_ion
                else:
                    d["battid"] = lowest_id + "_" + self.working_ion + "_" + isbx
                # Only allow one sandbox value for each electrode
                d["_sbxn"] = [isbx]

                docs.append(d)

        return docs
예제 #12
0
    mpr = MPRester('9RTlN5ZOXst6PAdS')
    strucs = []
    if options.id is None:
        system = parse_system(options.element)
        if type(system) is not list:
            mp_entries = mpr.get_entries(system)
        else:
            mp_entries = mpr.get_entries_in_chemsys(system)
            pd = PhaseDiagram(mp_entries)
            if options.dimension is None:
                options.dimension = len(system)
        for entry in mp_entries:
            accept = False
            if type(system) is list:
                if len(entry.composition) >= options.dimension:
                    eng = pd.get_e_above_hull(entry)
                    if eng <= options.cutoff:
                        accept = True
            else:
                eng = entry.energy_per_atom
                accept = True
            if accept:
                struc = output_struc(entry, eng, tol=1e-2)
                strucs.append(struc)
    else:
        strucs.append(mpr.get_structure_by_material_id(options.id))

    if options.format == 'poscar':
        filename = 'MPR.vasp'
    else:
        filename = 'MPR.cif'