Esempio n. 1
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=f"mod_{entry.entry_id}",
                 ))
     rest_ehulls = self.rester.get_stability(modified_entries)
     all_entries = entries + modified_entries
     compat = MaterialsProject2020Compatibility()
     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"])
Esempio n. 2
0
    def __init__(
        self,
        structure_matcher: StructureMatcher = StructureMatcher(),
        run_type_1: str = "GGA(+U)",
        run_type_2: str = "R2SCAN",
        compat_1: Optional[Compatibility] = MaterialsProject2020Compatibility(
        ),
        compat_2: Optional[Compatibility] = None,
        fuzzy_matching: bool = True,
    ):
        """
        Instantiate the mixing scheme. The init method creates a generator class that
        contains relevant settings (e.g., StrutureMatcher instance, Compatibility settings
        for each functional) for processing groups of entries.

        Args:
            structure_matcher (StructureMatcher): StructureMatcher object used to determine
                whether calculations from different functionals describe the same material.
            run_type_1: The first DFT run_type. Typically this is the majority or run type or
                the "base case" onto which the other calculations are referenced. Valid choices
                are any run_type recognized by Vasprun.run_type, such as "LDA", "GGA", "GGA+U",
                "PBEsol", "SCAN", or "R2SCAN". The class will ignore any entries that have a
                run_type different than run_type_1 or run_type_2.

                The list of run_type_1 entries provided to process_entries MUST form a complete
                Phase Diagram in order for the mixing scheme to work. If this condition is not
                satisfied, processing the entries will fail.

                Note that the special string "GGA(+U)" (default) will treat both GGA and GGA+U
                calculations as a single type. This option exists because GGA/GGA+U mixing is
                already handled by MaterialsProject2020Compatibility.
            run_type_2: The second DFT run_type. Typically this is the run_type that is 'preferred'
                but has fewer calculations. If run_type_1 and run_type_2 calculations exist for all
                materials, run_type_2 energies will be used (hence the 'preferred' status). The class
                will ignore any entries that have a run_type different than run_type_1 or run_type_2.
            compat_1: Compatibility class used to pre-process entries of run_type_1.
                Defaults to MaterialsProjectCompatibility2020.
            compat_2: Compatibility class used to pre-process entries of run_type_2.
                Defaults to None.
            fuzzy_matching: Whether to use less strict structure matching logic for
                diatomic elements O2, N2, F2, H2, and Cl2 as well as I and Br. Outputs of DFT
                relaxations using
                different functionals frequently fail to structure match for these elements
                even though they come from the same original material. Fuzzy structure matching
                considers the materials equivalent if the formula, number of sites, and
                space group are all identical. If there are multiple materials of run_type_2
                that satisfy these criteria, the one with lowest energy is considered to
                match.
        """
        self.name = "MP DFT mixing scheme"
        self.structure_matcher = structure_matcher
        if run_type_1 == run_type_2:
            raise ValueError(
                f"You specified the same run_type {run_type_1} for both run_type_1 and run_type_2. "
                "The mixing scheme is meaningless unless run_type_1 and run_type_2 are different"
            )
        self.run_type_1 = run_type_1
        self.run_type_2 = run_type_2
        if self.run_type_1 == "GGA(+U)":
            self.valid_rtypes_1 = ["GGA", "GGA+U"]
        else:
            self.valid_rtypes_1 = [self.run_type_1]

        if self.run_type_2 == "GGA(+U)":
            self.valid_rtypes_2 = ["GGA", "GGA+U"]
        else:
            self.valid_rtypes_2 = [self.run_type_2]

        self.compat_1 = compat_1
        self.compat_2 = compat_2
        self.fuzzy_matching = fuzzy_matching
Esempio n. 3
0
 def __init__ (self, vasprunpath) :
     mpr = MPRester()
     self.vasprunpath = vasprunpath
     self.compatibility = MaterialsProject2020Compatibility()
Esempio n. 4
0
    def get_pourbaix_entries(
        self,
        chemsys: Union[str, List],
        solid_compat="MaterialsProject2020Compatibility",
        use_gibbs: Optional[Literal[300]] = None,
    ):
        """
        A helper function to get all entries necessary to generate
        a Pourbaix diagram from the rest interface.

        Args:
            chemsys (str or [str]): Chemical system string comprising element
                symbols separated by dashes, e.g., "Li-Fe-O" or List of element
                symbols, e.g., ["Li", "Fe", "O"].
            solid_compat: Compatiblity scheme used to pre-process solid DFT energies prior
                to applying aqueous energy adjustments. May be passed as a class (e.g.
                MaterialsProject2020Compatibility) or an instance
                (e.g., MaterialsProject2020Compatibility()). If None, solid DFT energies
                are used as-is. Default: MaterialsProject2020Compatibility
            use_gibbs: Set to 300 (for 300 Kelvin) to use a machine learning model to
                estimate solid free energy from DFT energy (see GibbsComputedStructureEntry).
                This can slightly improve the accuracy of the Pourbaix diagram in some
                cases. Default: None. Note that temperatures other than 300K are not
                permitted here, because MaterialsProjectAqueousCompatibility corrections,
                used in Pourbaix diagram construction, are calculated based on 300 K data.
        """
        # imports are not top-level due to expense
        from pymatgen.analysis.pourbaix_diagram import PourbaixEntry
        from pymatgen.entries.compatibility import (
            Compatibility,
            MaterialsProject2020Compatibility,
            MaterialsProjectAqueousCompatibility,
            MaterialsProjectCompatibility,
        )
        from pymatgen.entries.computed_entries import ComputedEntry

        if solid_compat == "MaterialsProjectCompatibility":
            solid_compat = MaterialsProjectCompatibility()
        elif solid_compat == "MaterialsProject2020Compatibility":
            solid_compat = MaterialsProject2020Compatibility()
        elif isinstance(solid_compat, Compatibility):
            solid_compat = solid_compat
        else:
            raise ValueError(
                "Solid compatibility can only be 'MaterialsProjectCompatibility', "
                "'MaterialsProject2020Compatibility', or an instance of a Compatability class"
            )

        pbx_entries = []

        if isinstance(chemsys, str):
            chemsys = chemsys.split("-")
        # capitalize and sort the elements
        chemsys = sorted(e.capitalize() for e in chemsys)

        # Get ion entries first, because certain ions have reference
        # solids that aren't necessarily in the chemsys (Na2SO4)

        # download the ion reference data from MPContribs
        ion_data = self.get_ion_reference_data_for_chemsys(chemsys)

        # build the PhaseDiagram for get_ion_entries
        ion_ref_comps = [
            Ion.from_formula(d["data"]["RefSolid"]).composition
            for d in ion_data
        ]
        ion_ref_elts = set(
            itertools.chain.from_iterable(i.elements for i in ion_ref_comps))
        # TODO - would be great if the commented line below would work
        # However for some reason you cannot process GibbsComputedStructureEntry with
        # MaterialsProjectAqueousCompatibility
        ion_ref_entries = self.get_entries_in_chemsys(
            list([str(e) for e in ion_ref_elts] + ["O", "H"]),
            # use_gibbs=use_gibbs
        )

        # suppress the warning about supplying the required energies; they will be calculated from the
        # entries we get from MPRester
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message="You did not provide the required O2 and H2O energies.",
            )
            compat = MaterialsProjectAqueousCompatibility(
                solid_compat=solid_compat)
        # suppress the warning about missing oxidation states
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore", message="Failed to guess oxidation states.*")
            ion_ref_entries = compat.process_entries(ion_ref_entries)
        # TODO - if the commented line above would work, this conditional block
        # could be removed
        if use_gibbs:
            # replace the entries with GibbsComputedStructureEntry
            from pymatgen.entries.computed_entries import GibbsComputedStructureEntry

            ion_ref_entries = GibbsComputedStructureEntry.from_entries(
                ion_ref_entries, temp=use_gibbs)
        ion_ref_pd = PhaseDiagram(ion_ref_entries)

        ion_entries = self.get_ion_entries(ion_ref_pd, ion_ref_data=ion_data)
        pbx_entries = [
            PourbaixEntry(e, f"ion-{n}") for n, e in enumerate(ion_entries)
        ]

        # Construct the solid pourbaix entries from filtered ion_ref entries
        extra_elts = (set(ion_ref_elts) - {Element(s)
                                           for s in chemsys} -
                      {Element("H"), Element("O")})
        for entry in ion_ref_entries:
            entry_elts = set(entry.composition.elements)
            # Ensure no OH chemsys or extraneous elements from ion references
            if not (entry_elts <= {Element("H"), Element("O")}
                    or extra_elts.intersection(entry_elts)):
                # Create new computed entry
                form_e = ion_ref_pd.get_form_energy(entry)
                new_entry = ComputedEntry(entry.composition,
                                          form_e,
                                          entry_id=entry.entry_id)
                pbx_entry = PourbaixEntry(new_entry)
                pbx_entries.append(pbx_entry)

        return pbx_entries