From d564566610d58713b12f17e8abf2ec6f7315fd00 Mon Sep 17 00:00:00 2001 From: Jason Munro Date: Fri, 21 Oct 2022 19:04:29 -0700 Subject: [PATCH] Fix use of `PatchedPhaseDiagram` in `ThermoBuilder` (#566) * FIx default value of pd_docs * Fix patched phase diagram build issue * Fix setup.py files * Flake8 linting * More linting --- emmet-api/setup.py | 13 +--- emmet-builders/emmet/builders/vasp/thermo.py | 24 ++----- emmet-builders/setup.py | 4 +- emmet-core/emmet/core/thermo.py | 69 +++++++++----------- emmet-core/setup.py | 15 ++--- 5 files changed, 45 insertions(+), 80 deletions(-) diff --git a/emmet-api/setup.py b/emmet-api/setup.py index 120137d9b0..4a34da1878 100644 --- a/emmet-api/setup.py +++ b/emmet-api/setup.py @@ -8,9 +8,9 @@ setup( name="emmet-api", use_scm_version={ - "root": ".", + "root": "..", "relative_to": __file__, - "write_to": "emmet/api/_version.py", + "write_to": "emmet-api/emmet/api/_version.py", "write_to_template": '__version__ = "{version}"', "fallback_version": fallback_version, }, @@ -20,14 +20,7 @@ author_email="feedback@materialsproject.org", url="https://github.com/materialsproject/emmet", packages=find_namespace_packages(include=["emmet.*"]), - install_requires=[ - "emmet-core[all]", - "fastapi", - "uvicorn", - "gunicorn", - "boto3", - "maggma", - ], + install_requires=["emmet-core[all]", "fastapi", "uvicorn", "gunicorn", "boto3", "maggma"], python_requires=">=3.8", license="modified BSD", zip_safe=False, diff --git a/emmet-builders/emmet/builders/vasp/thermo.py b/emmet-builders/emmet/builders/vasp/thermo.py index 14be71c0dc..1c0dc429cd 100644 --- a/emmet-builders/emmet/builders/vasp/thermo.py +++ b/emmet-builders/emmet/builders/vasp/thermo.py @@ -153,11 +153,7 @@ def get_items(self) -> Iterator[List[Dict]]: # Remove overlapping chemical systems processed = set() to_process_chemsys = [] - for chemsys in sorted( - updated_chemsys | new_chemsys | affected_chemsys, - key=lambda x: len(x), - reverse=True, - ): + for chemsys in sorted(updated_chemsys | new_chemsys | affected_chemsys, key=lambda x: len(x), reverse=True,): if chemsys not in processed: processed |= chemsys_permutations(chemsys) to_process_chemsys.append(chemsys) @@ -236,20 +232,17 @@ def _produce_pair(self, pd_entries, thermo_type, elements): try: docs, pds = ThermoDoc.from_entries(pd_entries, thermo_type, deprecated=False) - pd_data = None + pd_docs = [None] if self.phase_diagram: if self.num_phase_diagram_eles is None or len(elements) <= self.num_phase_diagram_eles: pd_docs = [] for pd in pds: - chemsys = '-'.join(sorted(set([e.symbol for e in pd.elements]))) + chemsys = "-".join(sorted(set([e.symbol for e in pd.elements]))) pd_id = "{}_{}".format(chemsys, str(thermo_type)) pd_doc = PhaseDiagramDoc( - phase_diagram_id=pd_id, - chemsys=chemsys, - phase_diagram=pd, - thermo_type=thermo_type, + phase_diagram_id=pd_id, chemsys=chemsys, phase_diagram=pd, thermo_type=thermo_type, ) pd_data = jsanitize(pd_doc.dict(), allow_bson=True) @@ -337,10 +330,7 @@ def get_entries(self, chemsys: str) -> List[Dict]: d["material_id"]: d.get("average_oxidation_states", {}) for d in self.oxidation_states.query( properties=["material_id", "average_oxidation_states"], - criteria={ - "material_id": {"$in": material_ids}, - "state": "successful", - }, + criteria={"material_id": {"$in": material_ids}, "state": "successful"}, ) } @@ -361,9 +351,7 @@ def get_entries(self, chemsys: str) -> List[Dict]: return all_entries - def get_updated_chemsys( - self, - ) -> Set: + def get_updated_chemsys(self,) -> Set: """Gets updated chemical system as defined by the updating of an existing material""" updated_mats = self.thermo.newer_in(self.materials, criteria=self.query) diff --git a/emmet-builders/setup.py b/emmet-builders/setup.py index cbd4c48a2c..28addc7d45 100644 --- a/emmet-builders/setup.py +++ b/emmet-builders/setup.py @@ -8,9 +8,9 @@ setup( name="emmet-builders", use_scm_version={ - "root": ".", + "root": "..", "relative_to": __file__, - "write_to": "emmet/builders/_version.py", + "write_to": "emmet-builders/emmet/builders/_version.py", "write_to_template": '__version__ = "{version}"', "fallback_version": fallback_version, }, diff --git a/emmet-core/emmet/core/thermo.py b/emmet-core/emmet/core/thermo.py index 6ccb274643..dde685b1a9 100644 --- a/emmet-core/emmet/core/thermo.py +++ b/emmet-core/emmet/core/thermo.py @@ -20,16 +20,13 @@ class DecompositionProduct(BaseModel): """ material_id: MPID = Field( - None, - description="The Materials Project ID for the material this decomposition points to.", + None, description="The Materials Project ID for the material this decomposition points to.", ) formula: str = Field( - None, - description="The formula of the decomposed material this material decomposes to.", + None, description="The formula of the decomposed material this material decomposes to.", ) amount: float = Field( - None, - description="The amount of the decomposed material by formula units this this material decomposes to.", + None, description="The amount of the decomposed material by formula units this this material decomposes to.", ) @@ -48,13 +45,11 @@ class ThermoDoc(PropertyDoc): property_name = "thermo" thermo_type: Union[ThermoType, RunType] = Field( - ..., - description="Functional types of calculations involved in the energy mixing scheme.", + ..., description="Functional types of calculations involved in the energy mixing scheme.", ) thermo_id: str = Field( - ..., - description="Unique document ID which is composed of the Material ID and thermo data type.", + ..., description="Unique document ID which is composed of the Material ID and thermo data type.", ) uncorrected_energy_per_atom: float = Field( @@ -62,8 +57,7 @@ class ThermoDoc(PropertyDoc): ) energy_per_atom: float = Field( - ..., - description="The total corrected DFT energy of this material per atom in eV/atom.", + ..., description="The total corrected DFT energy of this material per atom in eV/atom.", ) energy_uncertainy_per_atom: float = Field(None, description="") @@ -73,8 +67,7 @@ class ThermoDoc(PropertyDoc): energy_above_hull: float = Field(..., description="The energy above the hull in eV/Atom.") is_stable: bool = Field( - False, - description="Flag for whether this material is on the hull and therefore stable.", + False, description="Flag for whether this material is on the hull and therefore stable.", ) equilibrium_reaction_energy_per_atom: float = Field( @@ -89,18 +82,15 @@ class ThermoDoc(PropertyDoc): ) decomposition_enthalpy: float = Field( - None, - description="Decomposition enthalpy as defined by `get_decomp_and_phase_separation_energy` in pymatgen.", + None, description="Decomposition enthalpy as defined by `get_decomp_and_phase_separation_energy` in pymatgen.", ) decomposition_enthalpy_decomposes_to: List[DecompositionProduct] = Field( - None, - description="List of decomposition data associated with the decomposition_enthalpy quantity.", + None, description="List of decomposition data associated with the decomposition_enthalpy quantity.", ) energy_type: str = Field( - ..., - description="The type of calculation this energy evaluation comes from.", + ..., description="The type of calculation this energy evaluation comes from.", ) entry_types: List[str] = Field(description="List of available energy types computed for this material.") @@ -122,7 +112,20 @@ def from_entries( # lowest energy entries. patched_pd = PatchedPhaseDiagram(entries, keep_all_spaces=True) - pd = patched_pd.pds[frozenset(patched_pd.elements)] # Main PD of parent chemsys + # Main PD of parent chemsys + try: + pd = patched_pd.pds[frozenset(patched_pd.elements)] + except KeyError: + entries_by_comp = defaultdict(list) + for e in entries: + entries_by_comp[e.composition.reduced_formula].append(e) + + # Only use lowest entry per composition to speed up QHull in Phase Diagram + reduced_entries = [ + sorted(comp_entries, key=lambda e: e.energy_per_atom)[0] for comp_entries in entries_by_comp.values() + ] + pd = PhaseDiagram(reduced_entries) + patched_pd.pds = {frozenset(patched_pd.elements): pd} docs = [] @@ -173,11 +176,7 @@ def _energy_eval(entry: ComputedStructureEntry): d["equilibrium_reaction_energy_per_atom"] = pd.get_equilibrium_reaction_energy(blessed_entry) else: d["decomposes_to"] = [ - { - "material_id": de.data["material_id"], - "formula": de.composition.formula, - "amount": amt, - } + {"material_id": de.data["material_id"], "formula": de.composition.formula, "amount": amt} for de, amt in decomp.items() ] @@ -185,11 +184,7 @@ def _energy_eval(entry: ComputedStructureEntry): decomp, energy = pd.get_decomp_and_phase_separation_energy(blessed_entry) d["decomposition_enthalpy"] = energy d["decomposition_enthalpy_decomposes_to"] = [ - { - "material_id": de.data["material_id"], - "formula": de.composition.formula, - "amount": amt, - } + {"material_id": de.data["material_id"], "formula": de.composition.formula, "amount": amt} for de, amt in decomp.items() ] except ValueError: @@ -242,23 +237,19 @@ class PhaseDiagramDoc(BaseModel): property_name = "phase_diagram" phase_diagram_id: str = Field( - ..., - description="Phase diagram ID consisting of the chemical system and thermo type", + ..., description="Phase diagram ID consisting of the chemical system and thermo type", ) chemsys: str = Field( - ..., - description="Dash-delimited string of elements in the material", + ..., description="Dash-delimited string of elements in the material", ) thermo_type: Union[ThermoType, RunType] = Field( - ..., - description="Functional types of calculations involved in the energy mixing scheme.", + ..., description="Functional types of calculations involved in the energy mixing scheme.", ) phase_diagram: PhaseDiagram = Field( - ..., - description="Phase diagram for the chemical system.", + ..., description="Phase diagram for the chemical system.", ) last_updated: datetime = Field( diff --git a/emmet-core/setup.py b/emmet-core/setup.py index 35598625ab..fb92b1e0e1 100644 --- a/emmet-core/setup.py +++ b/emmet-core/setup.py @@ -9,9 +9,9 @@ setup( name="emmet-core", use_scm_version={ - "root": ".", + "root": "..", "relative_to": __file__, - "write_to": "emmet/core/_version.py", + "write_to": "emmet-core/emmet/core/_version.py", "write_to_template": '__version__ = "{version}"', "fallback_version": fallback_version, }, @@ -21,10 +21,7 @@ author_email="feedback@materialsproject.org", url="https://github.com/materialsproject/emmet", packages=find_namespace_packages(include=["emmet.*"]), - package_data={ - "emmet.core.vasp.calc_types": ["*.yaml"], - "emmet.core.subtrates": ["*.json"], - }, + package_data={"emmet.core.vasp.calc_types": ["*.yaml"], "emmet.core.subtrates": ["*.json"]}, include_package_data=True, install_requires=[ "pymatgen>=2021.3,<2023.0", @@ -35,11 +32,7 @@ "spglib<2.0.0", ], extras_require={ - "all": [ - "robocrys>=0.2.7", - "pymatgen-analysis-diffusion>=2022.1.15", - "pymatgen-analysis-alloys>=0.0.3", - ], + "all": ["robocrys>=0.2.7", "pymatgen-analysis-diffusion>=2022.1.15", "pymatgen-analysis-alloys>=0.0.3"], }, python_requires=">=3.8", license="modified BSD",