예제 #1
0
 def setUp(self):
     module_dir = os.path.dirname(os.path.abspath(__file__))
     (self.elements, self.entries) = PDEntryIO.from_csv(
         os.path.join(module_dir, "pdentries_test.csv"))
     self.pd = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -5},
                                          self.elements)
     self.pd6 = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -6})
예제 #2
0
 def setUp(self):
     module_dir = os.path.dirname(os.path.abspath(__file__))
     (self.elements, self.entries) = PDEntryIO.from_csv(
         os.path.join(module_dir, "pdentries_test.csv"))
     self.pd = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -5},
                                          self.elements)
     self.pd6 = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -6})
예제 #3
0
    def test_get_critical_compositions(self):
        c1 = Composition('Fe2O3')
        c2 = Composition('Li3FeO4')
        c3 = Composition('Li2O')

        comps = self.analyzer.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.analyzer.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.analyzer.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')])
        pda = PDAnalyzer(gppd)
        self.assertRaises(ValueError, pda.get_critical_compositions,
                          Composition('Fe2O3'), Composition('Li3FeO4Xe'))

        # check that the function still works though
        comps = pda.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.analyzer.get_critical_compositions(c1, c1 * 2),
                         [c1, c1 * 2])
예제 #4
0
class GrandPotentialPhaseDiagramTest(unittest.TestCase):
    def setUp(self):
        module_dir = os.path.dirname(os.path.abspath(__file__))
        (self.elements, self.entries) = PDEntryIO.from_csv(
            os.path.join(module_dir, "pdentries_test.csv"))
        self.pd = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -5},
                                             self.elements)
        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,
                            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,
                "Calculated formation for " + formula + " is not correct!")

    def test_str(self):
        self.assertIsNotNone(str(self.pd))
예제 #5
0
class GrandPotentialPhaseDiagramTest(unittest.TestCase):

    def setUp(self):
        module_dir = os.path.dirname(os.path.abspath(__file__))
        (self.elements, self.entries) = PDEntryIO.from_csv(
            os.path.join(module_dir, "pdentries_test.csv"))
        self.pd = GrandPotentialPhaseDiagram(self.entries, {Element("O"): -5},
                                             self.elements)
        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, 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, "Calculated formation for " +
                                   formula + " is not correct!")

    def test_str(self):
        self.assertIsNotNone(str(self.pd))
예제 #6
0
    def get_element_profile(self, element, comp, comp_tol=1e-5):
        """
        Provides the element evolution data for a composition.
        For example, can be used to analyze Li conversion voltages by varying
        uLi and looking at the phases formed. Also can be used to analyze O2
        evolution by varying uO2.

        Args:
            element: An element. Must be in the phase diagram.
            comp: A Composition
            comp_tol: The tolerance to use when calculating decompositions.
                Phases with amounts less than this tolerance are excluded.
                Defaults to 1e-5.

        Returns:
            Evolution data as a list of dictionaries of the following format:
            [ {'chempot': -10.487582010000001, 'evolution': -2.0,
            'reaction': Reaction Object], ...]
        """
        if element not in self._pd.elements:
            raise ValueError("get_transition_chempots can only be called with"
                             " elements in the phase diagram.")
        chempots = self.get_transition_chempots(element)
        stable_entries = self._pd.stable_entries
        gccomp = Composition(
            {el: amt
             for el, amt in comp.items() if el != element})
        elref = self._pd.el_refs[element]
        elcomp = Composition(element.symbol)
        prev_decomp = []
        evolution = []

        def are_same_decomp(decomp1, decomp2):
            for comp in decomp2:
                if comp not in decomp1:
                    return False
            return True

        for c in chempots:
            gcpd = GrandPotentialPhaseDiagram(stable_entries,
                                              {element: c - 1e-5},
                                              self._pd.elements)
            analyzer = PDAnalyzer(gcpd)
            gcdecomp = analyzer.get_decomposition(gccomp)
            decomp = [
                gcentry.original_entry.composition
                for gcentry, amt in gcdecomp.items() if amt > comp_tol
            ]
            decomp_entries = [
                gcentry.original_entry for gcentry, amt in gcdecomp.items()
                if amt > comp_tol
            ]

            if not are_same_decomp(prev_decomp, decomp):
                if elcomp not in decomp:
                    decomp.insert(0, elcomp)
                rxn = Reaction([comp], decomp)
                rxn.normalize_to(comp)
                prev_decomp = decomp
                amt = -rxn.coeffs[rxn.all_comp.index(elcomp)]
                evolution.append({
                    'chempot': c,
                    'evolution': amt,
                    'element_reference': elref,
                    'reaction': rxn,
                    'entries': decomp_entries
                })
        return evolution