Ejemplo n.º 1
0
    def test_multicomponent(self):
        # Assure no ions get filtered at high concentration
        ag_n = [e for e in self.test_data['Ag-Te-N']
                if not "Te" in e.composition]
        highconc = PourbaixDiagram(ag_n, filter_solids=True,
                                   conc_dict={"Ag": 1e-5, "N": 1})
        entry_sets = [set(e.entry_id) for e in highconc.stable_entries]
        self.assertIn({"mp-124", "ion-17"}, entry_sets)

        # Binary system
        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'], filter_solids=True,
                                    comp_dict={"Ag": 0.5, "Te": 0.5},
                                    conc_dict={"Ag": 1e-8, "Te": 1e-8})
        self.assertEqual(len(pd_binary.stable_entries), 30)
        test_entry = pd_binary.find_stable_entry(8, 2)
        self.assertTrue("mp-499" in test_entry.entry_id)

        # Find a specific multientry to test
        self.assertEqual(pd_binary.get_decomposition_energy(test_entry, 8, 2), 0)
        self.assertEqual(pd_binary.get_decomposition_energy(
            test_entry.entry_list[0], 8, 2), 0)

        pd_ternary = PourbaixDiagram(self.test_data['Ag-Te-N'], filter_solids=True)
        self.assertEqual(len(pd_ternary.stable_entries), 49)

        ag = self.test_data['Ag-Te-N'][30]
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 2, -1), 0)
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 10, -2), 0)

        # Test invocation of pourbaix diagram from ternary data
        new_ternary = PourbaixDiagram(pd_ternary.all_entries)
        self.assertEqual(len(new_ternary.stable_entries), 49)
        self.assertAlmostEqual(new_ternary.get_decomposition_energy(ag, 2, -1), 0)
        self.assertAlmostEqual(new_ternary.get_decomposition_energy(ag, 10, -2), 0)
Ejemplo n.º 2
0
 def setUpClass(cls):
     cls.test_data = loadfn(
         os.path.join(PymatgenTest.TEST_FILES_DIR,
                      "pourbaix_test_data.json"))
     cls.pbx = PourbaixDiagram(cls.test_data["Zn"], filter_solids=True)
     cls.pbx_nofilter = PourbaixDiagram(cls.test_data["Zn"],
                                        filter_solids=False)
Ejemplo n.º 3
0
    def test_mpr_pipeline(self):
        from pymatgen import MPRester
        mpr = MPRester()
        data = mpr.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = mpr.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(data,
                              filter_solids=True,
                              conc_dict={
                                  "Ag": 1e-8,
                                  "Te": 1e-8
                              })
        self.assertEqual(len(pbx.stable_entries), 30)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertAlmostEqual(test_entry.energy, 2.3936747835000016, 3)

        # Test custom ions
        entries = mpr.get_pourbaix_entries(["Sn", "C", "Na"])
        ion = IonEntry(Ion.from_formula("NaO28H80Sn12C24+"), -161.676)
        custom_ion_entry = PourbaixEntry(ion, entry_id='my_ion')
        pbx = PourbaixDiagram(entries + [custom_ion_entry],
                              filter_solids=True,
                              comp_dict={
                                  "Na": 1,
                                  "Sn": 12,
                                  "C": 24
                              })
        self.assertAlmostEqual(
            pbx.get_decomposition_energy(custom_ion_entry, 5, 2),
            8.31202738629504, 2)
Ejemplo n.º 4
0
def get_electrochemical_stability(mpid, pH, potential):
    '''
    A wrapper for pymatgen to construct Pourbaix amd calculate electrochemical
    stability under reaction condition (i.e. at a given pH and applied potential).

    Arg:
        mpid         Materials project ID of a bulk composition. e.g. Pt: 'mp-126'.
        pH:          pH at reaction condition. Commonly ones are: acidic: pH=0,
                     neutral: pH=7, and basic pH=14.
        potential:   Applied potential at reaction condition.

    Returns:
        stability    Electrochemical stability of a composition under reaction condition,
                     unit is eV/atom.
    '''
    mpr = MPRester(read_rc('matproj_api_key'))
    try:
        entry = mpr.get_entries(mpid)[0]
        composition = entry.composition
        comp_dict = {str(key): value for key, value in composition.items()
                     if key not in ELEMENTS_HO}
        entries = mpr.get_pourbaix_entries(list(comp_dict.keys()))
        entry = [entry for entry in entries if entry.entry_id == mpid][0]
        pbx = PourbaixDiagram(entries, comp_dict=comp_dict, filter_solids=False)
        stability = pbx.get_decomposition_energy(entry, pH=pH, V=potential)
        stability = round(stability, 3)
    # Some mpid's stability are not available
    except IndexError:
        stability = np.nan
    return stability
Ejemplo n.º 5
0
    def test_pourbaix_heavy(self):

        entries = self.rester.get_pourbaix_entries(["Li", "Mg", "Sn", "Pd"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = self.rester.get_pourbaix_entries(["Ba", "Ca", "V", "Cu", "F"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = self.rester.get_pourbaix_entries(["Ba", "Ca", "V", "Cu", "F", "Fe"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = self.rester.get_pourbaix_entries(["Na", "Ca", "Nd", "Y", "Ho", "F"])
        pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
Ejemplo n.º 6
0
    def test_get_pourbaix_entries(self):
        pbx_entries = self.rester.get_pourbaix_entries(["Fe"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))
        # Ensure entries are pourbaix compatible
        pbx = PourbaixDiagram(pbx_entries)

        # Try binary system
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        pbx = PourbaixDiagram(pbx_entries)
Ejemplo n.º 7
0
    def test_pourbaix_mpr_pipeline(self):

        data = self.rester.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = self.rester.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(data,
                              filter_solids=True,
                              conc_dict={
                                  "Ag": 1e-8,
                                  "Te": 1e-8
                              })
        self.assertEqual(len(pbx.stable_entries), 29)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertEqual(sorted(test_entry.entry_id), ["ion-10", "mp-499"])

        # Test against ion sets with multiple equivalent ions (Bi-V regression)
        entries = self.rester.get_pourbaix_entries(["Bi", "V"])
        pbx = PourbaixDiagram(entries,
                              filter_solids=True,
                              conc_dict={
                                  "Bi": 1e-8,
                                  "V": 1e-8
                              })
        self.assertTrue(
            all([
                "Bi" in entry.composition and "V" in entry.composition
                for entry in pbx.all_entries
            ]))
Ejemplo n.º 8
0
 def test_heavy(self):
     from pymatgen import MPRester
     mpr = MPRester()
     entries = mpr.get_pourbaix_entries(["Li", "Mg", "Sn", "Pd"])
     pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
     entries = mpr.get_pourbaix_entries(["Ba", "Ca", "V", "Cu", "F"])
     pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
     entries = mpr.get_pourbaix_entries(["Ba", "Ca", "V", "Cu", "F", "Fe"])
     pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
     entries = mpr.get_pourbaix_entries(["Na", "Ca", "Nd", "Y", "Ho", "F"])
     pbx = PourbaixDiagram(entries, nproc=4, filter_solids=False)
Ejemplo n.º 9
0
    def test_get_pourbaix_entries(self):
        pbx_entries = self.rester.get_pourbaix_entries(["Fe"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))
        # Ensure entries are pourbaix compatible
        pbx = PourbaixDiagram(pbx_entries)

        # Try binary system
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        pbx = PourbaixDiagram(pbx_entries)

        # Test Zn-S, which has Na in reference solids
        pbx_entries = self.rester.get_pourbaix_entries(["Zn", "S"])
Ejemplo n.º 10
0
    def test_get_pourbaix_entries(self, mpr):
        # test input chemsys as a list of elements
        pbx_entries = mpr.get_pourbaix_entries(["Fe", "Cr"])
        for pbx_entry in pbx_entries:
            assert isinstance(pbx_entry, PourbaixEntry)

        # test input chemsys as a string
        pbx_entries = mpr.get_pourbaix_entries("Fe-Cr")
        for pbx_entry in pbx_entries:
            assert isinstance(pbx_entry, PourbaixEntry)

        # test use_gibbs kwarg
        pbx_entries = mpr.get_pourbaix_entries("Li-O", use_gibbs=300)
        for pbx_entry in pbx_entries:
            assert isinstance(pbx_entry, PourbaixEntry)

        # test solid_compat kwarg
        with pytest.raises(ValueError,
                           match="Solid compatibility can only be"):
            mpr.get_pourbaix_entries("Ti-O", solid_compat=None)

        # test removal of extra elements from reference solids
        # Li-Zn-S has Na in reference solids
        pbx_entries = mpr.get_pourbaix_entries("Li-Zn-S")
        assert not any([e for e in pbx_entries if 'Na' in e.composition])

        # Ensure entries are pourbaix compatible
        PourbaixDiagram(pbx_entries)
Ejemplo n.º 11
0
 def setUp(self):
     warnings.simplefilter("ignore")
     self.test_data = loadfn(
         os.path.join(PymatgenTest.TEST_FILES_DIR,
                      "pourbaix_test_data.json"))
     self.pd = PourbaixDiagram(self.test_data["Zn"])
     self.plotter = PourbaixPlotter(self.pd)
Ejemplo n.º 12
0
    def test_pourbaix_diagram(self):
        self.assertEqual(
            {e.name
             for e in self.pbx.stable_entries},
            {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
            "List of stable entries does not match",
        )

        self.assertEqual(
            {e.name
             for e in self.pbx_nofilter.stable_entries},
            {
                "ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)",
                "ZnH(s)"
            },
            "List of stable entries for unfiltered pbx does not match",
        )

        pbx_lowconc = PourbaixDiagram(self.test_data["Zn"],
                                      conc_dict={"Zn": 1e-8},
                                      filter_solids=True)
        self.assertEqual(
            {e.name
             for e in pbx_lowconc.stable_entries},
            {"Zn(HO)2(aq)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
        )
Ejemplo n.º 13
0
    def test_get_pourbaix_entries(self):
        # test input chemsys as a list of elements
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        # test input chemsys as a string
        pbx_entries = self.rester.get_pourbaix_entries("Fe-Cr")
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        fe_two_plus = [e for e in pbx_entries if e.entry_id == "ion-0"][0]
        self.assertAlmostEqual(fe_two_plus.energy,
                               -1.6228450214319294,
                               places=2)

        feo2 = [e for e in pbx_entries if e.entry_id == "mp-25332"][0]
        self.assertAlmostEqual(feo2.energy, 2.5523680849999995, places=2)

        # Test S, which has Na in reference solids
        pbx_entries = self.rester.get_pourbaix_entries(["S"])
        so4_two_minus = pbx_entries[9]
        self.assertAlmostEqual(so4_two_minus.energy,
                               0.0644980568750011,
                               places=2)

        # Ensure entries are pourbaix compatible
        PourbaixDiagram(pbx_entries)
Ejemplo n.º 14
0
    def test_get_decomposition(self):
        # Test a stable entry to ensure that it's zero in the stable region
        entry = self.test_data["Zn"][12]  # Should correspond to mp-2133
        self.assertAlmostEqual(
            self.pbx.get_decomposition_energy(entry, 10, 1),
            0.0,
            5,
            "Decomposition energy of ZnO is not 0.",
        )

        # Test an unstable entry to ensure that it's never zero
        entry = self.test_data["Zn"][11]
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-2, 4))
        result = self.pbx_nofilter.get_decomposition_energy(entry, ph, v)
        self.assertTrue((result >= 0).all(),
                        "Unstable energy has hull energy of 0 or less")

        # Test an unstable hydride to ensure HER correction works
        self.assertAlmostEqual(
            self.pbx.get_decomposition_energy(entry, -3, -2), 3.6979147983333)
        # Test a list of pHs
        self.pbx.get_decomposition_energy(entry, np.linspace(0, 2, 5), 2)

        # Test a list of Vs
        self.pbx.get_decomposition_energy(entry, 4, np.linspace(-3, 3, 10))

        # Test a set of matching arrays
        ph, v = np.meshgrid(np.linspace(0, 14), np.linspace(-3, 3))
        self.pbx.get_decomposition_energy(entry, ph, v)

        # Test custom ions
        entries = self.test_data["C-Na-Sn"]
        ion = IonEntry(Ion.from_formula("NaO28H80Sn12C24+"), -161.676)
        custom_ion_entry = PourbaixEntry(ion, entry_id="my_ion")
        pbx = PourbaixDiagram(
            entries + [custom_ion_entry],
            filter_solids=True,
            comp_dict={
                "Na": 1,
                "Sn": 12,
                "C": 24
            },
        )
        self.assertAlmostEqual(
            pbx.get_decomposition_energy(custom_ion_entry, 5, 2), 2.1209002582,
            1)
Ejemplo n.º 15
0
    def test_multicomponent(self):
        # Assure no ions get filtered at high concentration
        ag_n = [
            e for e in self.test_data['Ag-Te-N'] if not "Te" in e.composition
        ]
        highconc = PourbaixDiagram(ag_n,
                                   filter_solids=True,
                                   conc_dict={
                                       "Ag": 1e-5,
                                       "N": 1
                                   })
        entry_sets = [set(e.entry_id) for e in highconc.stable_entries]
        self.assertIn({"mp-124", "ion-17"}, entry_sets)

        # Binary system
        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'],
                                    filter_solids=True,
                                    comp_dict={
                                        "Ag": 0.5,
                                        "Te": 0.5
                                    },
                                    conc_dict={
                                        "Ag": 1e-8,
                                        "Te": 1e-8
                                    })
        self.assertEqual(len(pd_binary.stable_entries), 30)
        test_entry = pd_binary.find_stable_entry(8, 2)
        self.assertTrue("mp-499" in test_entry.entry_id)

        # Find a specific multientry to test
        self.assertEqual(pd_binary.get_decomposition_energy(test_entry, 8, 2),
                         0)
        self.assertEqual(
            pd_binary.get_decomposition_energy(test_entry.entry_list[0], 8, 2),
            0)

        pd_ternary = PourbaixDiagram(self.test_data['Ag-Te-N'],
                                     filter_solids=True)
        self.assertEqual(len(pd_ternary.stable_entries), 49)

        ag = self.test_data['Ag-Te-N'][30]
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 2, -1),
                               0)
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 10, -2),
                               0)
Ejemplo n.º 16
0
    def test_plot_entry_stability(self):
        entry = self.pd.all_entries[0]
        self.plotter.plot_entry_stability(entry, limits=[[-2, 14], [-3, 3]])

        # binary system
        pd_binary = PourbaixDiagram(self.test_data["Ag-Te"], comp_dict={"Ag": 0.5, "Te": 0.5})
        binary_plotter = PourbaixPlotter(pd_binary)
        plt = binary_plotter.plot_entry_stability(self.test_data["Ag-Te"][53])
        plt.close()
Ejemplo n.º 17
0
    def test_serialization(self):
        d = self.pbx.as_dict()
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(set([e.name for e in new.stable_entries]),
                         {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
                         "List of stable entries does not match")

        # Test with unprocessed entries included, this should result in the
        # previously filtered entries being included
        d = self.pbx.as_dict(include_unprocessed_entries=True)
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(
            set([e.name for e in new.stable_entries]), {
                "ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)",
                "ZnH(s)"
            }, "List of stable entries for unfiltered pbx does not match")

        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'],
                                    filter_solids=True,
                                    comp_dict={
                                        "Ag": 0.5,
                                        "Te": 0.5
                                    },
                                    conc_dict={
                                        "Ag": 1e-8,
                                        "Te": 1e-8
                                    })
        new_binary = PourbaixDiagram.from_dict(pd_binary.as_dict())
        self.assertEqual(len(pd_binary.stable_entries),
                         len(new_binary.stable_entries))
Ejemplo n.º 18
0
    def test_serialization(self):
        d = self.pbx.as_dict()
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(set([e.name for e in new.stable_entries]),
                         {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
                         "List of stable entries does not match")

        # Test with unprocessed entries included, this should result in the
        # previously filtered entries being included
        d = self.pbx.as_dict(include_unprocessed_entries=True)
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(
            set([e.name for e in new.stable_entries]),
            {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)", "ZnH(s)"},
            "List of stable entries for unfiltered pbx does not match")

        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'], filter_solids=True,
                                    comp_dict={"Ag": 0.5, "Te": 0.5},
                                    conc_dict={"Ag": 1e-8, "Te": 1e-8})
        new_binary = PourbaixDiagram.from_dict(pd_binary.as_dict())
        self.assertEqual(len(pd_binary.stable_entries),
                         len(new_binary.stable_entries))
Ejemplo n.º 19
0
    def test_multicomponent(self):
        # Binary system
        pd_binary = PourbaixDiagram(self.test_data['Ag-Te'], filter_solids=True,
                                    comp_dict={"Ag": 0.5, "Te": 0.5},
                                    conc_dict={"Ag": 1e-8, "Te": 1e-8})
        self.assertEqual(len(pd_binary.stable_entries), 30)
        test_entry = pd_binary.find_stable_entry(8, 2)
        self.assertTrue("mp-499" in test_entry.entry_id)

        # Find a specific multientry to test
        self.assertEqual(pd_binary.get_decomposition_energy(test_entry, 8, 2), 0)
        self.assertEqual(pd_binary.get_decomposition_energy(
            test_entry.entry_list[0], 8, 2), 0)

        pd_ternary = PourbaixDiagram(self.test_data['Ag-Te-N'], filter_solids=True)
        self.assertEqual(len(pd_ternary.stable_entries), 49)

        ag = self.test_data['Ag-Te-N'][30]
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 2, -1), 0)
        self.assertAlmostEqual(pd_ternary.get_decomposition_energy(ag, 10, -2), 0)
Ejemplo n.º 20
0
    def test_solid_filter(self):
        entries = self.test_data["Zn"]
        pbx = PourbaixDiagram(entries, filter_solids=False)
        oxidized_phase = pbx.find_stable_entry(10, 2)
        self.assertEqual(oxidized_phase.name, "ZnO2(s)")

        entries = self.test_data["Zn"]
        pbx = PourbaixDiagram(entries, filter_solids=True)
        oxidized_phase = pbx.find_stable_entry(10, 2)
        self.assertEqual(oxidized_phase.name, "ZnO(s)")
Ejemplo n.º 21
0
    def test_get_pourbaix_entries(self):
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        fe_two_plus = [e for e in pbx_entries if e.entry_id == "ion-0"][0]
        self.assertAlmostEqual(fe_two_plus.energy, -1.6228450214319294)

        feo2 = [e for e in pbx_entries if e.entry_id == "mp-25332"][0]
        self.assertAlmostEqual(feo2.energy, 4.424365035000003)

        # Test S, which has Na in reference solids
        pbx_entries = self.rester.get_pourbaix_entries(["S"])
        so4_two_minus = pbx_entries[9]
        self.assertAlmostEqual(so4_two_minus.energy, 0.0644980568750011)

        # Ensure entries are pourbaix compatible
        pbx = PourbaixDiagram(pbx_entries)
Ejemplo n.º 22
0
    def test_get_pourbaix_entries(self):
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        fe_two_plus = [e for e in pbx_entries if e.entry_id == "ion-0"][0]
        self.assertAlmostEqual(fe_two_plus.energy, -1.580096075)

        feo2 = [e for e in pbx_entries if e.entry_id == "mp-25332"][0]
        self.assertAlmostEqual(feo2.energy, 2.51083231)

        # Test S, which has Na in reference solids
        pbx_entries = self.rester.get_pourbaix_entries(["S"])
        so4_two_minus = pbx_entries[9]
        self.assertAlmostEqual(so4_two_minus.energy, 0.047817821)

        # Ensure entries are pourbaix compatible
        pbx = PourbaixDiagram(pbx_entries)
Ejemplo n.º 23
0
        def create_pbx_object(
            pourbaix_entries, pourbaix_diagram_options, conc_dict, struct
        ):
            # Pass along element restriction
            if pourbaix_entries == "too_many_elements":
                return "too_many_elements"

            self.logger.debug("Updating entries")
            if pourbaix_entries is None or not pourbaix_entries:
                self.logger.debug("Preventing updating entries")
                raise PreventUpdate

            pourbaix_entries = self.from_data(pourbaix_entries)

            # filter_solids = True
            if pourbaix_diagram_options is not None:
                filter_solids = "filter_solids" in pourbaix_diagram_options
            else:
                filter_solids = True

            # Get composition from structure
            struct = self.from_data(struct)
            comp_dict = {
                str(elt): coeff
                for elt, coeff in struct.composition.items()
                if elt not in ELEMENTS_HO
            }
            if conc_dict is not None:
                conc_dict = self.from_data(conc_dict)

            pourbaix_diagram = PourbaixDiagram(
                pourbaix_entries,
                comp_dict=comp_dict,
                conc_dict=conc_dict,
                filter_solids=filter_solids,
            )
            self.logger.debug("Generated pourbaix diagram")
            return self.to_data(pourbaix_diagram)
Ejemplo n.º 24
0
def getentrystability(entry,
                      stabilitydata,
                      ehullmax,
                      newcomp,
                      plotterobj=None,
                      compdict=None,
                      all_entries=None):
    if newcomp == True:
        if compdict == None or all_entries == None:
            raise Exception(
                'Need to provide all_entries and compdict when using new composition!'
            )
        pbx = PourbaixDiagram(all_entries, comp_dict=compdict)
        plotterobj = PourbaixPlotter(pbx)
    elif plotterobj == None:
        raise Exception(
            'Need to provide plotter object if using previous composition!')

    stability, (pH, V) = plotterobj.get_entry_stability(entry,
                                                        e_hull_max=ehullmax)
    stability_metrics = stabilitymetrics(stability, pH, V)

    return (stability_metrics, plotterobj)
Ejemplo n.º 25
0
    def test_mpr_pipeline(self):
        from pymatgen import MPRester
        mpr = MPRester()
        data = mpr.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = mpr.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(data, filter_solids=True,
                              conc_dict={"Ag": 1e-8, "Te": 1e-8})
        self.assertEqual(len(pbx.stable_entries), 30)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertAlmostEqual(test_entry.energy, 2.393900378500001)

        # Test custom ions
        entries = mpr.get_pourbaix_entries(["Sn", "C", "Na"])
        ion = IonEntry(Ion.from_formula("NaO28H80Sn12C24+"), -161.676)
        custom_ion_entry = PourbaixEntry(ion, entry_id='my_ion')
        pbx = PourbaixDiagram(entries + [custom_ion_entry], filter_solids=True,
                              comp_dict={"Na": 1, "Sn": 12, "C": 24})
        self.assertAlmostEqual(pbx.get_decomposition_energy(custom_ion_entry, 5, 2),
                               8.31082110278154)
Ejemplo n.º 26
0
    def test_get_pourbaix_entries(self):
        # test input chemsys as a list of elements
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        # test input chemsys as a string
        pbx_entries = self.rester.get_pourbaix_entries("Fe-Cr")
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        # fe_two_plus = [e for e in pbx_entries if e.entry_id == "ion-0"][0]
        # self.assertAlmostEqual(fe_two_plus.energy, -1.12369, places=3)
        #
        # feo2 = [e for e in pbx_entries if e.entry_id == "mp-25332"][0]
        # self.assertAlmostEqual(feo2.energy, 3.56356, places=3)
        #
        # # Test S, which has Na in reference solids
        # pbx_entries = self.rester.get_pourbaix_entries(["S"])
        # so4_two_minus = pbx_entries[9]
        # self.assertAlmostEqual(so4_two_minus.energy, 0.301511, places=3)

        # Ensure entries are Pourbaix compatible
        PourbaixDiagram(pbx_entries)
Ejemplo n.º 27
0
    def test_serialization(self):
        d = self.pbx.as_dict()
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(
            {e.name
             for e in new.stable_entries},
            {"ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)"},
            "List of stable entries does not match",
        )

        # Test with unstable solid entries included (filter_solids=False), this should result in the
        # previously filtered entries being included
        with pytest.warns(
                DeprecationWarning,
                match="The include_unprocessed_entries kwarg is deprecated!"):
            d = self.pbx_nofilter.as_dict(include_unprocessed_entries=True)
        new = PourbaixDiagram.from_dict(d)
        self.assertEqual(
            {e.name
             for e in new.stable_entries},
            {
                "ZnO(s)", "Zn[2+]", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)", "ZnO2(s)",
                "ZnH(s)"
            },
            "List of stable entries for unfiltered pbx does not match",
        )

        pd_binary = PourbaixDiagram(
            self.test_data["Ag-Te"],
            filter_solids=True,
            comp_dict={
                "Ag": 0.5,
                "Te": 0.5
            },
            conc_dict={
                "Ag": 1e-8,
                "Te": 1e-8
            },
        )
        new_binary = PourbaixDiagram.from_dict(pd_binary.as_dict())
        self.assertEqual(len(pd_binary.stable_entries),
                         len(new_binary.stable_entries))
Ejemplo n.º 28
0
 def test_solid_filter(self):
     entries = self.test_data['Ag-Te-N']
     pbx = PourbaixDiagram(entries, filter_solids=True)
     pbx.get_decomposition_energy(entries[0], 0, 0)
Ejemplo n.º 29
0
 def test_nofilter(self):
     entries = self.test_data['Ag-Te']
     pbx = PourbaixDiagram(entries)
     pbx.get_decomposition_energy(entries[0], 0, 0)
Ejemplo n.º 30
0
    def test_mpr_pipeline(self):
        from pymatgen.ext.matproj import MPRester

        mpr = MPRester()
        data = mpr.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = mpr.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(data,
                              filter_solids=True,
                              conc_dict={
                                  "Ag": 1e-8,
                                  "Te": 1e-8
                              })
        self.assertEqual(len(pbx.stable_entries), 29)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertAlmostEqual(test_entry.energy, 2.3894017960000009, 1)

        # Test custom ions
        entries = mpr.get_pourbaix_entries(["Sn", "C", "Na"])
        ion = IonEntry(Ion.from_formula("NaO28H80Sn12C24+"), -161.676)
        custom_ion_entry = PourbaixEntry(ion, entry_id="my_ion")
        pbx = PourbaixDiagram(
            entries + [custom_ion_entry],
            filter_solids=True,
            comp_dict={
                "Na": 1,
                "Sn": 12,
                "C": 24
            },
        )
        self.assertAlmostEqual(
            pbx.get_decomposition_energy(custom_ion_entry, 5, 2), 2.1209002582,
            1)

        # Test against ion sets with multiple equivalent ions (Bi-V regression)
        entries = mpr.get_pourbaix_entries(["Bi", "V"])
        pbx = PourbaixDiagram(entries,
                              filter_solids=True,
                              conc_dict={
                                  "Bi": 1e-8,
                                  "V": 1e-8
                              })
        self.assertTrue(
            all([
                "Bi" in entry.composition and "V" in entry.composition
                for entry in pbx.all_entries
            ]))
Ejemplo n.º 31
0
 def test_get_pourbaix_domains(self):
     domains = PourbaixDiagram.get_pourbaix_domains(self.test_data['Zn'])
     self.assertEqual(len(domains[0]), 7)
Ejemplo n.º 32
0
 def test_multielement_parallel(self):
     # Simple test to ensure that multiprocessing is working
     test_entries = self.test_data["Ag-Te-N"]
     nproc = multiprocessing.cpu_count()
     pbx = PourbaixDiagram(test_entries, filter_solids=True, nproc=nproc)
     self.assertEqual(len(pbx.stable_entries), 49)
Ejemplo n.º 33
0
 def test_get_pourbaix_domains(self):
     domains = PourbaixDiagram.get_pourbaix_domains(self.test_data["Zn"])
     self.assertEqual(len(domains[0]), 7)
Ejemplo n.º 34
0
    def test_multicomponent(self):
        # Assure no ions get filtered at high concentration
        ag_n = [
            e for e in self.test_data["Ag-Te-N"] if "Te" not in e.composition
        ]
        highconc = PourbaixDiagram(ag_n,
                                   filter_solids=True,
                                   conc_dict={
                                       "Ag": 1e-5,
                                       "N": 1
                                   })
        entry_sets = [set(e.entry_id) for e in highconc.stable_entries]
        self.assertIn({"mp-124", "ion-17"}, entry_sets)

        # Binary system
        pd_binary = PourbaixDiagram(
            self.test_data["Ag-Te"],
            filter_solids=True,
            comp_dict={
                "Ag": 0.5,
                "Te": 0.5
            },
            conc_dict={
                "Ag": 1e-8,
                "Te": 1e-8
            },
        )
        self.assertEqual(len(pd_binary.stable_entries), 30)
        test_entry = pd_binary.find_stable_entry(8, 2)
        self.assertTrue("mp-499" in test_entry.entry_id)

        # Find a specific multientry to test
        self.assertEqual(pd_binary.get_decomposition_energy(test_entry, 8, 2),
                         0)

        pd_ternary = PourbaixDiagram(self.test_data["Ag-Te-N"],
                                     filter_solids=True)
        self.assertEqual(len(pd_ternary.stable_entries), 49)

        # Fetch a solid entry and a ground state entry mixture
        ag_te_n = self.test_data["Ag-Te-N"][-1]
        ground_state_ag_with_ions = MultiEntry(
            [self.test_data["Ag-Te-N"][i] for i in [4, 18, 30]],
            weights=[1 / 3, 1 / 3, 1 / 3],
        )
        self.assertAlmostEqual(
            pd_ternary.get_decomposition_energy(ag_te_n, 2, -1),
            2.767822855765)
        self.assertAlmostEqual(
            pd_ternary.get_decomposition_energy(ag_te_n, 10, -2),
            3.756840056890625)
        self.assertAlmostEqual(
            pd_ternary.get_decomposition_energy(ground_state_ag_with_ions, 2,
                                                -1), 0)

        # Test invocation of pourbaix diagram from ternary data
        new_ternary = PourbaixDiagram(pd_ternary.all_entries)
        self.assertEqual(len(new_ternary.stable_entries), 49)
        self.assertAlmostEqual(
            new_ternary.get_decomposition_energy(ag_te_n, 2, -1),
            2.767822855765)
        self.assertAlmostEqual(
            new_ternary.get_decomposition_energy(ag_te_n, 10, -2),
            3.756840056890625)
        self.assertAlmostEqual(
            new_ternary.get_decomposition_energy(ground_state_ag_with_ions, 2,
                                                 -1), 0)
Ejemplo n.º 35
0
 def setUpClass(cls):
     cls.test_data = loadfn(os.path.join(test_dir, 'pourbaix_test_data.json'))
     cls.pbx = PourbaixDiagram(cls.test_data['Zn'], filter_solids=True)
     cls.pbx_nofilter = PourbaixDiagram(cls.test_data['Zn'],
                                        filter_solids=False)
Ejemplo n.º 36
0
 def setUp(self):
     warnings.simplefilter("ignore")
     self.test_data = loadfn(os.path.join(test_dir, "pourbaix_test_data.json"))
     self.pd = PourbaixDiagram(self.test_data["Zn"])
     self.plotter = PourbaixPlotter(self.pd)