diff --git a/emmet-api/emmet/api/routes/materials/electronic_structure/query_operators.py b/emmet-api/emmet/api/routes/materials/electronic_structure/query_operators.py index 9d39fb64b9..8264b22dab 100644 --- a/emmet-api/emmet/api/routes/materials/electronic_structure/query_operators.py +++ b/emmet-api/emmet/api/routes/materials/electronic_structure/query_operators.py @@ -10,7 +10,8 @@ from pymatgen.core.periodic_table import Element from pymatgen.electronic_structure.core import OrbitalType, Spin -from emmet.core.electronic_structure import BSPathType, DOSProjectionType +from emmet.core.band_theory import BSPathType +from emmet.core.electronic_structure import DOSProjectionType from emmet.core.mpid import MPID, AlphaID diff --git a/emmet-api/tests/materials/electronic_structure/test_query_operators.py b/emmet-api/tests/materials/electronic_structure/test_query_operators.py index 4f0fa134ea..f95f78a1a7 100644 --- a/emmet-api/tests/materials/electronic_structure/test_query_operators.py +++ b/emmet-api/tests/materials/electronic_structure/test_query_operators.py @@ -6,10 +6,9 @@ DOSDataQuery, ObjectQuery, ) -from emmet.core.electronic_structure import ( - BSPathType, - DOSProjectionType, -) + +from emmet.core.band_theory import BSPathType +from emmet.core.electronic_structure import DOSProjectionType from pymatgen.analysis.magnetism.analyzer import Ordering from pymatgen.core.periodic_table import Element diff --git a/emmet-builders/emmet/builders/materials/electronic_structure.py b/emmet-builders/emmet/builders/materials/electronic_structure.py index 522abf9a61..d0472f7124 100644 --- a/emmet-builders/emmet/builders/materials/electronic_structure.py +++ b/emmet-builders/emmet/builders/materials/electronic_structure.py @@ -19,7 +19,7 @@ from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from emmet.builders.utils import query_open_data -from emmet.core.band_theory import get_path_from_bandstructure, obtain_path_type +from emmet.core.band_theory import obtain_path_type from emmet.core.electronic_structure import ElectronicStructureDoc from emmet.core.utils import jsanitize @@ -466,11 +466,11 @@ def _update_materials_doc(self, mat_id): } try: - bs_type = next( + bs_type, _, _ = next( obtain_path_type( - labels_dict, bs.structure, - get_path_from_bandstructure(bs), + [kpt.frac_coords for kpt in bs.kpoints], + user_kpoint_labels=labels_dict, ) ) except Exception: diff --git a/emmet-core/emmet/core/band_theory.py b/emmet-core/emmet/core/band_theory.py index 50a7f5a032..364bafcd0f 100644 --- a/emmet-core/emmet/core/band_theory.py +++ b/emmet-core/emmet/core/band_theory.py @@ -18,23 +18,32 @@ from pymatgen.electronic_structure.dos import CompleteDos, Dos from pymatgen.symmetry.bandstructure import HighSymmKpath -from emmet.core.electronic_structure import BSPathType from emmet.core.math import Matrix3D, Vector3D from emmet.core.settings import EmmetSettings from emmet.core.types.pymatgen_types.structure_adapter import StructureType +from emmet.core.types.enums import ValueEnum if TYPE_CHECKING: from collections.abc import Callable, Generator, Sequence + from typing import Any from pymatgen.core.sites import PeriodicSite from pymatgen.core.structure import Structure - from pymatgen.electronic_structure.bandstructure import BandStructureSymmLine from typing_extensions import Self BAND_GAP_TOL = 1e-4 SETTINGS = EmmetSettings() # type: ignore[call-arg] +class BSPathType(ValueEnum): + """Define path conventions used in pymatgen.""" + + setyawan_curtarolo = "setyawan_curtarolo" + hinuma = "hinuma" + latimer_munro = "latimer_munro" + unknown = "unknown" + + class BandTheoryBase(BaseModel): identifier: str | None = Field(None, description="The identifier of this object.") @@ -42,6 +51,15 @@ class BandTheoryBase(BaseModel): None, description="The structure associated with this calculation." ) + def __str__(self) -> str: + return ( + f"{self.__class__.__name__}({self.identifier or ''}" + f"{': ' + self.structure.formula if self.structure else ''})" + ) + + def __repr__(self) -> str: + return self.__str__() + def _deser_lattice(lattice: Lattice | dict | Matrix3D) -> Matrix3D: """Ensure the lattice matrix is stored only.""" @@ -61,6 +79,17 @@ class BandStructure( electronic and phonon band structures. """ + path_convention: BSPathType = Field( # type: ignore[assignment] + BSPathType.unknown, + description="High symmetry path convention of the band structure", + ) + + kpath: list[str] | None = None + + labels_dict: dict[str, Vector3D] = Field( + {}, description="The high-symmetry labels of specific q-points." + ) + qpoints: list[Vector3D] = Field( description="The wave vectors (q-points) at which the band structure was sampled, in direct coordinates.", ) @@ -69,9 +98,30 @@ class BandStructure( description="The reciprocal lattice.", validation_alias="lattice_rec" ) - labels_dict: dict[str, Vector3D] = Field( - {}, description="The high-symmetry labels of specific q-points." - ) + def model_post_init(self, __context: Any) -> None: + if self.structure and self.path_convention == BSPathType.unknown: + + # Try the user-input labels if provided, as well as regenerating + # them on the fly if path determination fails + labels = [self.labels_dict, None] if self.labels_dict else [None] + for label_set in labels: + try: + self.path_convention, self.kpath, new_labels = next( + obtain_path_type( + self.structure, + self.qpoints, + user_kpoint_labels=label_set, + ) + ) + if self.path_convention != BSPathType.unknown: + self.labels_dict = new_labels.copy() + break + except StopIteration: + pass + + # Fallback, use antipatterns to intuit path type + if self.path_convention == BSPathType.unknown and self.labels_dict: + self.path_convention = _loose_path_match(list(self.labels_dict)) class ProjectedBS(BaseModel): @@ -129,10 +179,6 @@ def to_pmg_like(self) -> dict[Spin, np.ndarray]: class ElectronicBS(BandStructure): """Define an electronic band structure schema.""" - path_convention: str | None = Field( - None, description="High symmetry path convention of the band structure" - ) - efermi: float = Field( description="The Fermi level (highest occupied energy level.)" ) @@ -170,31 +216,18 @@ def is_metal(self) -> bool: def from_pmg(cls, ebs: PmgBandStructure, **kwargs) -> Self: """Construct from a pymatgen band structure object.""" band_gap_meta = ebs.get_band_gap() - labels_dict = { - label: kpoint.frac_coords for label, kpoint in ebs.labels_dict.items() - } - - try: - bs_type = next( - obtain_path_type( - labels_dict, ebs.structure, get_path_from_bandstructure(ebs) # type: ignore[arg-type] - ) - ) - except Exception: - bs_type = None config = { "qpoints": [qpt.frac_coords for qpt in ebs.kpoints], "lattice_rec": ebs.lattice_rec.matrix, "efermi": ebs.efermi, "labels_dict": { - label: qpt.frac_coords for label, qpt in ebs.labels_dict.items() + label: qpt.frac_coords for label, qpt in (ebs.labels_dict or {}).items() }, "structure": ebs.structure, "is_metal": ebs.is_metal(), "is_direct": band_gap_meta["direct"], "band_gap": band_gap_meta["energy"], - "path_convention": bs_type, } for spin in Spin: @@ -396,80 +429,166 @@ def to_pmg(self) -> Dos | CompleteDos: def obtain_path_type( - labels_dict: dict[str, Sequence[float]], structure: Structure, - kpoint_path: list[str], - symprecs: list[float] = [SETTINGS.SYMPREC, 0.01], + kpoints: list[Vector3D], + user_kpoint_labels: dict[str, Vector3D] | None = None, + symprecs: list[float] = [SETTINGS.SYMPREC], # , 0.01], angtols: list[float] = [SETTINGS.ANGLE_TOL], - atol: float = 1e-5, - kpoint_tol: float = 1e-5, + atol: float = 1e-3, + kpoint_tol: float = 1e-3, ) -> Generator: """Try to match a band structure path order to known path orders. Iterates over a list of `symprec` and `angle_tolerance` values to - match paths to one of the path orders in `BSPathType` by checking: - 1. Special high-symmetry k-point labels match - 2. High-symmetry k-points along the path have the same labels - 3. High-symmetry k-points along the path have the same coordinates + match paths to one of the path orders in `BSPathType` by checking + that the kpoints list contains a reference k-point path dictated + by the symmetry of the structure. + + Note that the k-points can be a superset of the high-symmetry path, + the full path must be a sequential sublist of the input k-points. + + Ex: If the reference k-path is ["X","M","K","U"], a valid superset + would be ["GAMMA", "X", "M", "K", "U", "X"], but an invalid superset + would be ["X", "M", "GAMMA", "K", "U"] (as this breaks the reference order). + + The original k-point labels can be input by the user in `user_kpoint_labels`. + This is often useful for older calculations because the high-symmetry + k-points are not unique, and the path generated thereof will differ + if the fractional coordinates of a given high-symmetry point represent + a periodic image. + + Important notes: + - pymatgen uses "\\Gamma" (BSPathType.setyawan_curtarolo), + "GAMMA" (BSPathType.hinuma), and "Γ" (BSPathType.latimer_munro) + to represent the Gamma point. + - Sometimes legacy electronic structure data includes both + the path set by a particular algorithm, plus a few extra + points. We only check that the path matches up to the + default high-symmetry path. Parameters ----------- - labels_dict : dict of str to Sequence[float] - Dict of high-symmetry points to their corresponding - fractional coordinates in k-space structure : pymatgen .Structure Structure associated with the bandstructure - kpoint_path : list of str - A list of high symmetry k-points visited by the bandstructure. + kpoints : list of tuple[float,float,float] + A list of (all) k-points included in the bandstructure. symprecs : list[float] = [SETTINGS.SYMPREC,0.01] List of `symprec` values to pass to `HighSymmKpath` angtols : list[float] = [SETTINGS.ANGLE_TOL] List `angle_tolerance` values to pass to `HighSymmKpath` atol : float = 1e-5 Absolute tolerance used by `HighSymmKpath` - kpoint_tol : float = 1e-5 + kpoint_tol : float = 1e-3 Absolute tolerance for matching fractional k-point coordiantes Yields ----------- BSPathType """ - for symprec, angtol in product(symprecs, angtols): - - for path_type in BSPathType: - hskp = HighSymmKpath( - structure, - has_magmoms=False, - magmom_axis=None, - path_type=path_type.value, - symprec=symprec, - angle_tolerance=angtol, - atol=atol, - ) + for path_type in (bspt for bspt in BSPathType if bspt.value != "unknown"): # type: ignore[attr-defined] + found_path_type = False + for symprec, angtol in product(symprecs, angtols): + if found_path_type: + break + + try: + hskp = HighSymmKpath( + structure, + # has_magmoms=False, + magmom_axis=None, + path_type=path_type.value, + # symprec=symprec, + # angle_tolerance=angtol, + # atol=atol, + ) + + kpoint_labels = user_kpoint_labels or { + k: tuple(v.tolist()) for k, v in hskp.kpath["kpoints"].items() + } + ref_path = [ + kpt for kpt_group in hskp.kpath["path"] for kpt in kpt_group + ] + inferred_kpath = _get_kpath(kpoint_labels, kpoints) + num_extra = len(inferred_kpath) - len(ref_path) + except Exception: + continue - ordered_kpts = list(hskp.kpath["kpoints"]) if ( - # check that the labels are the same - set(hskp.kpath["kpoints"]) == set(labels_dict) # check that the path orders are the same - and [label for label in hskp.get_kpoints()[1] if label] == kpoint_path - # check that the kpoints corresponding to each label are the same - and np.all( - np.linalg.norm( - np.array([hskp.kpath["kpoints"][k] for k in ordered_kpts]) - - np.array([labels_dict[k] for k in ordered_kpts]), - axis=1, - ) - < kpoint_tol - ) + ref_path == inferred_kpath + # or that the inferred path contains the reference one as a subset + or (num_extra > 0 and _coarse_list_superset(inferred_kpath, ref_path)) ): - yield path_type - - -def get_path_from_bandstructure(band_structure: BandStructureSymmLine) -> list[str]: - """Get the list of high-symmetry points in a band structure.""" - return [ - label - for branch in band_structure.branches - for label in branch["name"].split("-") - ] + found_path_type = True + yield path_type, inferred_kpath, kpoint_labels + + if not found_path_type: + yield BSPathType.unknown, None, {} + + +def _coarse_list_superset(test: list, ref: list) -> bool: + diff_len = len(test) - len(ref) + if test[: len(ref)] == ref or test[diff_len:] == ref: + return True + for i in range(1, diff_len): + if test[i : len(ref) + i] == ref: + return True + return False + + +def _get_kpath( + kpoints_labels: dict[str, Vector3D], kpoints: list[Vector3D] +) -> list[str]: + labels = sorted(kpoints_labels) + ref_kpoints = np.array([kpoints_labels[k] for k in labels]) + kpts = np.array(kpoints) + norms = np.array([np.linalg.norm(kpt - ref_kpoints, axis=1) for kpt in kpts]) + ordered_labels = [labels[np.argmin(norm)] for norm in norms if norm.min() < 1e-5] + processed_labels: list[str] = [] + for i, lbl in enumerate(ordered_labels): + if i > 0 and lbl == processed_labels[-1]: + continue + processed_labels.append(lbl) + return processed_labels + + +def _loose_path_match(labels: Sequence[str]) -> BSPathType: + """ANTIPATTERN: Use poor labelling to determine path convention. + + In pymatgen, the following are true: + + | BSPathType | Gamma-point symbol | Other characters | + | ---- | ---- | ---- | + | setyawan_curtarolo | "\\Gamma" | Uppercase letters + Q_1 | + | hinuma | "GAMMA" | Uppercase letters + Q_1 | + | latimer_munro | "Γ" | Lowercase letters + q_{1} | + + We abuse these (already anti-)patterns to coarsely determine the path type, + knowing a priori these were generated with pymatgen + """ + unique_labels = set(labels) + if ( + "\\Gamma" in unique_labels + and unique_labels.intersection({"GAMMA", "Γ"}) == set() + and set("".join(unique_labels)).intersection({r"{", r"}"}) == set() + and {symb.upper() for symb in unique_labels if symb != "\\Gamma"}.issubset( + unique_labels + ) + ): + return BSPathType.setyawan_curtarolo # type: ignore[return-value] + elif ( + "GAMMA" in unique_labels + and unique_labels.intersection({"\\Gamma", "Γ"}) == set() + and set("".join(unique_labels)).intersection({r"{", r"}"}) == set() + and {symb.upper() for symb in unique_labels} == unique_labels + ): + return BSPathType.hinuma # type: ignore[return-value] + elif ( + "Γ" in unique_labels + and unique_labels.intersection({"\\Gamma", "GAMMA"}) == set() + and {symb.lower() for symb in unique_labels if symb != "Γ"}.issubset( + unique_labels + ) + ): + return BSPathType.latimer_munro # type: ignore[return-value] + return BSPathType.unknown # type: ignore[return-value] diff --git a/emmet-core/emmet/core/electronic_structure.py b/emmet-core/emmet/core/electronic_structure.py index a4cb77a507..1dd5512c56 100644 --- a/emmet-core/emmet/core/electronic_structure.py +++ b/emmet-core/emmet/core/electronic_structure.py @@ -19,6 +19,9 @@ from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from pymatgen.symmetry.bandstructure import HighSymmKpath +# keeping this import here to avoid breaking changes, this enum was moved to `band_theory` +from emmet.core.band_theory import BSPathType # noqa: F401 + from emmet.core.material_property import PropertyDoc from emmet.core.mpid import AlphaID from emmet.core.settings import EmmetSettings @@ -43,12 +46,6 @@ ] -class BSPathType(ValueEnum): - setyawan_curtarolo = "setyawan_curtarolo" - hinuma = "hinuma" - latimer_munro = "latimer_munro" - - class DOSProjectionType(ValueEnum): total = "total" elemental = "elemental" diff --git a/emmet-core/emmet/core/vasp/calc_types/calc_types.yaml b/emmet-core/emmet/core/vasp/calc_types/calc_types.yaml index 6cf82c0587..48cac2d3f7 100644 --- a/emmet-core/emmet/core/vasp/calc_types/calc_types.yaml +++ b/emmet-core/emmet/core/vasp/calc_types/calc_types.yaml @@ -132,6 +132,7 @@ RUN_TYPES: ALGO: Gw0 TASK_TYPES: - NSCF Line + - SCF Line - NSCF Uniform - Dielectric - DFPT diff --git a/emmet-core/emmet/core/vasp/calc_types/enums.py b/emmet-core/emmet/core/vasp/calc_types/enums.py index 1c84371450..26eb5c7a71 100644 --- a/emmet-core/emmet/core/vasp/calc_types/enums.py +++ b/emmet-core/emmet/core/vasp/calc_types/enums.py @@ -97,6 +97,7 @@ class TaskType(ValueEnum): NSCF_Line = "NSCF Line" NSCF_Uniform = "NSCF Uniform" Optic = "Optic" + SCF_Line = "SCF Line" Static = "Static" Structure_Optimization = "Structure Optimization" Unrecognized = "Unrecognized" @@ -115,6 +116,7 @@ class CalcType(IgnoreCaseEnum): AM05_NSCF_Line = "AM05 NSCF Line" AM05_NSCF_Uniform = "AM05 NSCF Uniform" AM05_Optic = "AM05 Optic" + AM05_SCF_Line = "AM05 SCF Line" AM05_Static = "AM05 Static" AM05_Structure_Optimization = "AM05 Structure Optimization" AM05_U_DFPT = "AM05+U DFPT" @@ -127,6 +129,7 @@ class CalcType(IgnoreCaseEnum): AM05_U_NSCF_Line = "AM05+U NSCF Line" AM05_U_NSCF_Uniform = "AM05+U NSCF Uniform" AM05_U_Optic = "AM05+U Optic" + AM05_U_SCF_Line = "AM05+U SCF Line" AM05_U_Static = "AM05+U Static" AM05_U_Structure_Optimization = "AM05+U Structure Optimization" AM05_U_Unrecognized = "AM05+U Unrecognized" @@ -141,6 +144,7 @@ class CalcType(IgnoreCaseEnum): B3LYP_NSCF_Line = "B3LYP NSCF Line" B3LYP_NSCF_Uniform = "B3LYP NSCF Uniform" B3LYP_Optic = "B3LYP Optic" + B3LYP_SCF_Line = "B3LYP SCF Line" B3LYP_Static = "B3LYP Static" B3LYP_Structure_Optimization = "B3LYP Structure Optimization" B3LYP_U_DFPT = "B3LYP+U DFPT" @@ -153,6 +157,7 @@ class CalcType(IgnoreCaseEnum): B3LYP_U_NSCF_Line = "B3LYP+U NSCF Line" B3LYP_U_NSCF_Uniform = "B3LYP+U NSCF Uniform" B3LYP_U_Optic = "B3LYP+U Optic" + B3LYP_U_SCF_Line = "B3LYP+U SCF Line" B3LYP_U_Static = "B3LYP+U Static" B3LYP_U_Structure_Optimization = "B3LYP+U Structure Optimization" B3LYP_U_Unrecognized = "B3LYP+U Unrecognized" @@ -167,6 +172,7 @@ class CalcType(IgnoreCaseEnum): G0W0_NSCF_Line = "G0W0 NSCF Line" G0W0_NSCF_Uniform = "G0W0 NSCF Uniform" G0W0_Optic = "G0W0 Optic" + G0W0_SCF_Line = "G0W0 SCF Line" G0W0_Static = "G0W0 Static" G0W0_Structure_Optimization = "G0W0 Structure Optimization" G0W0_U_DFPT = "G0W0+U DFPT" @@ -179,6 +185,7 @@ class CalcType(IgnoreCaseEnum): G0W0_U_NSCF_Line = "G0W0+U NSCF Line" G0W0_U_NSCF_Uniform = "G0W0+U NSCF Uniform" G0W0_U_Optic = "G0W0+U Optic" + G0W0_U_SCF_Line = "G0W0+U SCF Line" G0W0_U_Static = "G0W0+U Static" G0W0_U_Structure_Optimization = "G0W0+U Structure Optimization" G0W0_U_Unrecognized = "G0W0+U Unrecognized" @@ -193,6 +200,7 @@ class CalcType(IgnoreCaseEnum): GGA_NSCF_Line = "GGA NSCF Line" GGA_NSCF_Uniform = "GGA NSCF Uniform" GGA_Optic = "GGA Optic" + GGA_SCF_Line = "GGA SCF Line" GGA_Static = "GGA Static" GGA_Structure_Optimization = "GGA Structure Optimization" GGA_U_DFPT = "GGA+U DFPT" @@ -205,6 +213,7 @@ class CalcType(IgnoreCaseEnum): GGA_U_NSCF_Line = "GGA+U NSCF Line" GGA_U_NSCF_Uniform = "GGA+U NSCF Uniform" GGA_U_Optic = "GGA+U Optic" + GGA_U_SCF_Line = "GGA+U SCF Line" GGA_U_Static = "GGA+U Static" GGA_U_Structure_Optimization = "GGA+U Structure Optimization" GGA_U_Unrecognized = "GGA+U Unrecognized" @@ -219,6 +228,7 @@ class CalcType(IgnoreCaseEnum): HFCus_NSCF_Line = "HFCus NSCF Line" HFCus_NSCF_Uniform = "HFCus NSCF Uniform" HFCus_Optic = "HFCus Optic" + HFCus_SCF_Line = "HFCus SCF Line" HFCus_Static = "HFCus Static" HFCus_Structure_Optimization = "HFCus Structure Optimization" HFCus_U_DFPT = "HFCus+U DFPT" @@ -231,6 +241,7 @@ class CalcType(IgnoreCaseEnum): HFCus_U_NSCF_Line = "HFCus+U NSCF Line" HFCus_U_NSCF_Uniform = "HFCus+U NSCF Uniform" HFCus_U_Optic = "HFCus+U Optic" + HFCus_U_SCF_Line = "HFCus+U SCF Line" HFCus_U_Static = "HFCus+U Static" HFCus_U_Structure_Optimization = "HFCus+U Structure Optimization" HFCus_U_Unrecognized = "HFCus+U Unrecognized" @@ -245,6 +256,7 @@ class CalcType(IgnoreCaseEnum): HF_NSCF_Line = "HF NSCF Line" HF_NSCF_Uniform = "HF NSCF Uniform" HF_Optic = "HF Optic" + HF_SCF_Line = "HF SCF Line" HF_Static = "HF Static" HF_Structure_Optimization = "HF Structure Optimization" HF_U_DFPT = "HF+U DFPT" @@ -257,6 +269,7 @@ class CalcType(IgnoreCaseEnum): HF_U_NSCF_Line = "HF+U NSCF Line" HF_U_NSCF_Uniform = "HF+U NSCF Uniform" HF_U_Optic = "HF+U Optic" + HF_U_SCF_Line = "HF+U SCF Line" HF_U_Static = "HF+U Static" HF_U_Structure_Optimization = "HF+U Structure Optimization" HF_U_Unrecognized = "HF+U Unrecognized" @@ -271,6 +284,7 @@ class CalcType(IgnoreCaseEnum): HSE03_NSCF_Line = "HSE03 NSCF Line" HSE03_NSCF_Uniform = "HSE03 NSCF Uniform" HSE03_Optic = "HSE03 Optic" + HSE03_SCF_Line = "HSE03 SCF Line" HSE03_Static = "HSE03 Static" HSE03_Structure_Optimization = "HSE03 Structure Optimization" HSE03_U_DFPT = "HSE03+U DFPT" @@ -283,6 +297,7 @@ class CalcType(IgnoreCaseEnum): HSE03_U_NSCF_Line = "HSE03+U NSCF Line" HSE03_U_NSCF_Uniform = "HSE03+U NSCF Uniform" HSE03_U_Optic = "HSE03+U Optic" + HSE03_U_SCF_Line = "HSE03+U SCF Line" HSE03_U_Static = "HSE03+U Static" HSE03_U_Structure_Optimization = "HSE03+U Structure Optimization" HSE03_U_Unrecognized = "HSE03+U Unrecognized" @@ -297,6 +312,7 @@ class CalcType(IgnoreCaseEnum): HSE06_NSCF_Line = "HSE06 NSCF Line" HSE06_NSCF_Uniform = "HSE06 NSCF Uniform" HSE06_Optic = "HSE06 Optic" + HSE06_SCF_Line = "HSE06 SCF Line" HSE06_Static = "HSE06 Static" HSE06_Structure_Optimization = "HSE06 Structure Optimization" HSE06_U_DFPT = "HSE06+U DFPT" @@ -309,6 +325,7 @@ class CalcType(IgnoreCaseEnum): HSE06_U_NSCF_Line = "HSE06+U NSCF Line" HSE06_U_NSCF_Uniform = "HSE06+U NSCF Uniform" HSE06_U_Optic = "HSE06+U Optic" + HSE06_U_SCF_Line = "HSE06+U SCF Line" HSE06_U_Static = "HSE06+U Static" HSE06_U_Structure_Optimization = "HSE06+U Structure Optimization" HSE06_U_Unrecognized = "HSE06+U Unrecognized" @@ -323,6 +340,7 @@ class CalcType(IgnoreCaseEnum): LDA_NSCF_Line = "LDA NSCF Line" LDA_NSCF_Uniform = "LDA NSCF Uniform" LDA_Optic = "LDA Optic" + LDA_SCF_Line = "LDA SCF Line" LDA_Static = "LDA Static" LDA_Structure_Optimization = "LDA Structure Optimization" LDA_U_DFPT = "LDA+U DFPT" @@ -335,6 +353,7 @@ class CalcType(IgnoreCaseEnum): LDA_U_NSCF_Line = "LDA+U NSCF Line" LDA_U_NSCF_Uniform = "LDA+U NSCF Uniform" LDA_U_Optic = "LDA+U Optic" + LDA_U_SCF_Line = "LDA+U SCF Line" LDA_U_Static = "LDA+U Static" LDA_U_Structure_Optimization = "LDA+U Structure Optimization" LDA_U_Unrecognized = "LDA+U Unrecognized" @@ -349,6 +368,7 @@ class CalcType(IgnoreCaseEnum): M06L_NSCF_Line = "M06L NSCF Line" M06L_NSCF_Uniform = "M06L NSCF Uniform" M06L_Optic = "M06L Optic" + M06L_SCF_Line = "M06L SCF Line" M06L_Static = "M06L Static" M06L_Structure_Optimization = "M06L Structure Optimization" M06L_U_DFPT = "M06L+U DFPT" @@ -361,6 +381,7 @@ class CalcType(IgnoreCaseEnum): M06L_U_NSCF_Line = "M06L+U NSCF Line" M06L_U_NSCF_Uniform = "M06L+U NSCF Uniform" M06L_U_Optic = "M06L+U Optic" + M06L_U_SCF_Line = "M06L+U SCF Line" M06L_U_Static = "M06L+U Static" M06L_U_Structure_Optimization = "M06L+U Structure Optimization" M06L_U_Unrecognized = "M06L+U Unrecognized" @@ -375,6 +396,7 @@ class CalcType(IgnoreCaseEnum): MBJL_NSCF_Line = "MBJL NSCF Line" MBJL_NSCF_Uniform = "MBJL NSCF Uniform" MBJL_Optic = "MBJL Optic" + MBJL_SCF_Line = "MBJL SCF Line" MBJL_Static = "MBJL Static" MBJL_Structure_Optimization = "MBJL Structure Optimization" MBJL_U_DFPT = "MBJL+U DFPT" @@ -387,6 +409,7 @@ class CalcType(IgnoreCaseEnum): MBJL_U_NSCF_Line = "MBJL+U NSCF Line" MBJL_U_NSCF_Uniform = "MBJL+U NSCF Uniform" MBJL_U_Optic = "MBJL+U Optic" + MBJL_U_SCF_Line = "MBJL+U SCF Line" MBJL_U_Static = "MBJL+U Static" MBJL_U_Structure_Optimization = "MBJL+U Structure Optimization" MBJL_U_Unrecognized = "MBJL+U Unrecognized" @@ -401,6 +424,7 @@ class CalcType(IgnoreCaseEnum): MS0_NSCF_Line = "MS0 NSCF Line" MS0_NSCF_Uniform = "MS0 NSCF Uniform" MS0_Optic = "MS0 Optic" + MS0_SCF_Line = "MS0 SCF Line" MS0_Static = "MS0 Static" MS0_Structure_Optimization = "MS0 Structure Optimization" MS0_U_DFPT = "MS0+U DFPT" @@ -413,6 +437,7 @@ class CalcType(IgnoreCaseEnum): MS0_U_NSCF_Line = "MS0+U NSCF Line" MS0_U_NSCF_Uniform = "MS0+U NSCF Uniform" MS0_U_Optic = "MS0+U Optic" + MS0_U_SCF_Line = "MS0+U SCF Line" MS0_U_Static = "MS0+U Static" MS0_U_Structure_Optimization = "MS0+U Structure Optimization" MS0_U_Unrecognized = "MS0+U Unrecognized" @@ -427,6 +452,7 @@ class CalcType(IgnoreCaseEnum): MS1_NSCF_Line = "MS1 NSCF Line" MS1_NSCF_Uniform = "MS1 NSCF Uniform" MS1_Optic = "MS1 Optic" + MS1_SCF_Line = "MS1 SCF Line" MS1_Static = "MS1 Static" MS1_Structure_Optimization = "MS1 Structure Optimization" MS1_U_DFPT = "MS1+U DFPT" @@ -439,6 +465,7 @@ class CalcType(IgnoreCaseEnum): MS1_U_NSCF_Line = "MS1+U NSCF Line" MS1_U_NSCF_Uniform = "MS1+U NSCF Uniform" MS1_U_Optic = "MS1+U Optic" + MS1_U_SCF_Line = "MS1+U SCF Line" MS1_U_Static = "MS1+U Static" MS1_U_Structure_Optimization = "MS1+U Structure Optimization" MS1_U_Unrecognized = "MS1+U Unrecognized" @@ -453,6 +480,7 @@ class CalcType(IgnoreCaseEnum): MS2_NSCF_Line = "MS2 NSCF Line" MS2_NSCF_Uniform = "MS2 NSCF Uniform" MS2_Optic = "MS2 Optic" + MS2_SCF_Line = "MS2 SCF Line" MS2_Static = "MS2 Static" MS2_Structure_Optimization = "MS2 Structure Optimization" MS2_U_DFPT = "MS2+U DFPT" @@ -465,6 +493,7 @@ class CalcType(IgnoreCaseEnum): MS2_U_NSCF_Line = "MS2+U NSCF Line" MS2_U_NSCF_Uniform = "MS2+U NSCF Uniform" MS2_U_Optic = "MS2+U Optic" + MS2_U_SCF_Line = "MS2+U SCF Line" MS2_U_Static = "MS2+U Static" MS2_U_Structure_Optimization = "MS2+U Structure Optimization" MS2_U_Unrecognized = "MS2+U Unrecognized" @@ -479,6 +508,7 @@ class CalcType(IgnoreCaseEnum): PBE0_NSCF_Line = "PBE0 NSCF Line" PBE0_NSCF_Uniform = "PBE0 NSCF Uniform" PBE0_Optic = "PBE0 Optic" + PBE0_SCF_Line = "PBE0 SCF Line" PBE0_Static = "PBE0 Static" PBE0_Structure_Optimization = "PBE0 Structure Optimization" PBE0_U_DFPT = "PBE0+U DFPT" @@ -491,6 +521,7 @@ class CalcType(IgnoreCaseEnum): PBE0_U_NSCF_Line = "PBE0+U NSCF Line" PBE0_U_NSCF_Uniform = "PBE0+U NSCF Uniform" PBE0_U_Optic = "PBE0+U Optic" + PBE0_U_SCF_Line = "PBE0+U SCF Line" PBE0_U_Static = "PBE0+U Static" PBE0_U_Structure_Optimization = "PBE0+U Structure Optimization" PBE0_U_Unrecognized = "PBE0+U Unrecognized" @@ -505,6 +536,7 @@ class CalcType(IgnoreCaseEnum): PBE_NSCF_Line = "PBE NSCF Line" PBE_NSCF_Uniform = "PBE NSCF Uniform" PBE_Optic = "PBE Optic" + PBE_SCF_Line = "PBE SCF Line" PBE_Static = "PBE Static" PBE_Structure_Optimization = "PBE Structure Optimization" PBE_U_DFPT = "PBE+U DFPT" @@ -517,6 +549,7 @@ class CalcType(IgnoreCaseEnum): PBE_U_NSCF_Line = "PBE+U NSCF Line" PBE_U_NSCF_Uniform = "PBE+U NSCF Uniform" PBE_U_Optic = "PBE+U Optic" + PBE_U_SCF_Line = "PBE+U SCF Line" PBE_U_Static = "PBE+U Static" PBE_U_Structure_Optimization = "PBE+U Structure Optimization" PBE_U_Unrecognized = "PBE+U Unrecognized" @@ -531,6 +564,7 @@ class CalcType(IgnoreCaseEnum): PBEsol_NSCF_Line = "PBEsol NSCF Line" PBEsol_NSCF_Uniform = "PBEsol NSCF Uniform" PBEsol_Optic = "PBEsol Optic" + PBEsol_SCF_Line = "PBEsol SCF Line" PBEsol_Static = "PBEsol Static" PBEsol_Structure_Optimization = "PBEsol Structure Optimization" PBEsol_U_DFPT = "PBEsol+U DFPT" @@ -543,6 +577,7 @@ class CalcType(IgnoreCaseEnum): PBEsol_U_NSCF_Line = "PBEsol+U NSCF Line" PBEsol_U_NSCF_Uniform = "PBEsol+U NSCF Uniform" PBEsol_U_Optic = "PBEsol+U Optic" + PBEsol_U_SCF_Line = "PBEsol+U SCF Line" PBEsol_U_Static = "PBEsol+U Static" PBEsol_U_Structure_Optimization = "PBEsol+U Structure Optimization" PBEsol_U_Unrecognized = "PBEsol+U Unrecognized" @@ -557,6 +592,7 @@ class CalcType(IgnoreCaseEnum): RTPSS_NSCF_Line = "RTPSS NSCF Line" RTPSS_NSCF_Uniform = "RTPSS NSCF Uniform" RTPSS_Optic = "RTPSS Optic" + RTPSS_SCF_Line = "RTPSS SCF Line" RTPSS_Static = "RTPSS Static" RTPSS_Structure_Optimization = "RTPSS Structure Optimization" RTPSS_U_DFPT = "RTPSS+U DFPT" @@ -569,6 +605,7 @@ class CalcType(IgnoreCaseEnum): RTPSS_U_NSCF_Line = "RTPSS+U NSCF Line" RTPSS_U_NSCF_Uniform = "RTPSS+U NSCF Uniform" RTPSS_U_Optic = "RTPSS+U Optic" + RTPSS_U_SCF_Line = "RTPSS+U SCF Line" RTPSS_U_Static = "RTPSS+U Static" RTPSS_U_Structure_Optimization = "RTPSS+U Structure Optimization" RTPSS_U_Unrecognized = "RTPSS+U Unrecognized" @@ -583,6 +620,7 @@ class CalcType(IgnoreCaseEnum): SCAN_NSCF_Line = "SCAN NSCF Line" SCAN_NSCF_Uniform = "SCAN NSCF Uniform" SCAN_Optic = "SCAN Optic" + SCAN_SCF_Line = "SCAN SCF Line" SCAN_Static = "SCAN Static" SCAN_Structure_Optimization = "SCAN Structure Optimization" SCAN_U_DFPT = "SCAN+U DFPT" @@ -595,6 +633,7 @@ class CalcType(IgnoreCaseEnum): SCAN_U_NSCF_Line = "SCAN+U NSCF Line" SCAN_U_NSCF_Uniform = "SCAN+U NSCF Uniform" SCAN_U_Optic = "SCAN+U Optic" + SCAN_U_SCF_Line = "SCAN+U SCF Line" SCAN_U_Static = "SCAN+U Static" SCAN_U_Structure_Optimization = "SCAN+U Structure Optimization" SCAN_U_Unrecognized = "SCAN+U Unrecognized" @@ -609,6 +648,7 @@ class CalcType(IgnoreCaseEnum): SCAN_rVV10_NSCF_Line = "SCAN-rVV10 NSCF Line" SCAN_rVV10_NSCF_Uniform = "SCAN-rVV10 NSCF Uniform" SCAN_rVV10_Optic = "SCAN-rVV10 Optic" + SCAN_rVV10_SCF_Line = "SCAN-rVV10 SCF Line" SCAN_rVV10_Static = "SCAN-rVV10 Static" SCAN_rVV10_Structure_Optimization = "SCAN-rVV10 Structure Optimization" SCAN_rVV10_U_DFPT = "SCAN-rVV10+U DFPT" @@ -623,6 +663,7 @@ class CalcType(IgnoreCaseEnum): SCAN_rVV10_U_NSCF_Line = "SCAN-rVV10+U NSCF Line" SCAN_rVV10_U_NSCF_Uniform = "SCAN-rVV10+U NSCF Uniform" SCAN_rVV10_U_Optic = "SCAN-rVV10+U Optic" + SCAN_rVV10_U_SCF_Line = "SCAN-rVV10+U SCF Line" SCAN_rVV10_U_Static = "SCAN-rVV10+U Static" SCAN_rVV10_U_Structure_Optimization = "SCAN-rVV10+U Structure Optimization" SCAN_rVV10_U_Unrecognized = "SCAN-rVV10+U Unrecognized" @@ -637,6 +678,7 @@ class CalcType(IgnoreCaseEnum): TPSS_NSCF_Line = "TPSS NSCF Line" TPSS_NSCF_Uniform = "TPSS NSCF Uniform" TPSS_Optic = "TPSS Optic" + TPSS_SCF_Line = "TPSS SCF Line" TPSS_Static = "TPSS Static" TPSS_Structure_Optimization = "TPSS Structure Optimization" TPSS_U_DFPT = "TPSS+U DFPT" @@ -649,6 +691,7 @@ class CalcType(IgnoreCaseEnum): TPSS_U_NSCF_Line = "TPSS+U NSCF Line" TPSS_U_NSCF_Uniform = "TPSS+U NSCF Uniform" TPSS_U_Optic = "TPSS+U Optic" + TPSS_U_SCF_Line = "TPSS+U SCF Line" TPSS_U_Static = "TPSS+U Static" TPSS_U_Structure_Optimization = "TPSS+U Structure Optimization" TPSS_U_Unrecognized = "TPSS+U Unrecognized" @@ -663,6 +706,7 @@ class CalcType(IgnoreCaseEnum): optB86b_NSCF_Line = "optB86b NSCF Line" optB86b_NSCF_Uniform = "optB86b NSCF Uniform" optB86b_Optic = "optB86b Optic" + optB86b_SCF_Line = "optB86b SCF Line" optB86b_Static = "optB86b Static" optB86b_Structure_Optimization = "optB86b Structure Optimization" optB86b_U_DFPT = "optB86b+U DFPT" @@ -675,6 +719,7 @@ class CalcType(IgnoreCaseEnum): optB86b_U_NSCF_Line = "optB86b+U NSCF Line" optB86b_U_NSCF_Uniform = "optB86b+U NSCF Uniform" optB86b_U_Optic = "optB86b+U Optic" + optB86b_U_SCF_Line = "optB86b+U SCF Line" optB86b_U_Static = "optB86b+U Static" optB86b_U_Structure_Optimization = "optB86b+U Structure Optimization" optB86b_U_Unrecognized = "optB86b+U Unrecognized" @@ -689,6 +734,7 @@ class CalcType(IgnoreCaseEnum): optB86b_vdW_NSCF_Line = "optB86b-vdW NSCF Line" optB86b_vdW_NSCF_Uniform = "optB86b-vdW NSCF Uniform" optB86b_vdW_Optic = "optB86b-vdW Optic" + optB86b_vdW_SCF_Line = "optB86b-vdW SCF Line" optB86b_vdW_Static = "optB86b-vdW Static" optB86b_vdW_Structure_Optimization = "optB86b-vdW Structure Optimization" optB86b_vdW_U_DFPT = "optB86b-vdW+U DFPT" @@ -703,6 +749,7 @@ class CalcType(IgnoreCaseEnum): optB86b_vdW_U_NSCF_Line = "optB86b-vdW+U NSCF Line" optB86b_vdW_U_NSCF_Uniform = "optB86b-vdW+U NSCF Uniform" optB86b_vdW_U_Optic = "optB86b-vdW+U Optic" + optB86b_vdW_U_SCF_Line = "optB86b-vdW+U SCF Line" optB86b_vdW_U_Static = "optB86b-vdW+U Static" optB86b_vdW_U_Structure_Optimization = "optB86b-vdW+U Structure Optimization" optB86b_vdW_U_Unrecognized = "optB86b-vdW+U Unrecognized" @@ -717,6 +764,7 @@ class CalcType(IgnoreCaseEnum): optB88_NSCF_Line = "optB88 NSCF Line" optB88_NSCF_Uniform = "optB88 NSCF Uniform" optB88_Optic = "optB88 Optic" + optB88_SCF_Line = "optB88 SCF Line" optB88_Static = "optB88 Static" optB88_Structure_Optimization = "optB88 Structure Optimization" optB88_U_DFPT = "optB88+U DFPT" @@ -729,6 +777,7 @@ class CalcType(IgnoreCaseEnum): optB88_U_NSCF_Line = "optB88+U NSCF Line" optB88_U_NSCF_Uniform = "optB88+U NSCF Uniform" optB88_U_Optic = "optB88+U Optic" + optB88_U_SCF_Line = "optB88+U SCF Line" optB88_U_Static = "optB88+U Static" optB88_U_Structure_Optimization = "optB88+U Structure Optimization" optB88_U_Unrecognized = "optB88+U Unrecognized" @@ -743,6 +792,7 @@ class CalcType(IgnoreCaseEnum): optB88_vdW_NSCF_Line = "optB88-vdW NSCF Line" optB88_vdW_NSCF_Uniform = "optB88-vdW NSCF Uniform" optB88_vdW_Optic = "optB88-vdW Optic" + optB88_vdW_SCF_Line = "optB88-vdW SCF Line" optB88_vdW_Static = "optB88-vdW Static" optB88_vdW_Structure_Optimization = "optB88-vdW Structure Optimization" optB88_vdW_U_DFPT = "optB88-vdW+U DFPT" @@ -757,6 +807,7 @@ class CalcType(IgnoreCaseEnum): optB88_vdW_U_NSCF_Line = "optB88-vdW+U NSCF Line" optB88_vdW_U_NSCF_Uniform = "optB88-vdW+U NSCF Uniform" optB88_vdW_U_Optic = "optB88-vdW+U Optic" + optB88_vdW_U_SCF_Line = "optB88-vdW+U SCF Line" optB88_vdW_U_Static = "optB88-vdW+U Static" optB88_vdW_U_Structure_Optimization = "optB88-vdW+U Structure Optimization" optB88_vdW_U_Unrecognized = "optB88-vdW+U Unrecognized" @@ -771,6 +822,7 @@ class CalcType(IgnoreCaseEnum): optPBE_NSCF_Line = "optPBE NSCF Line" optPBE_NSCF_Uniform = "optPBE NSCF Uniform" optPBE_Optic = "optPBE Optic" + optPBE_SCF_Line = "optPBE SCF Line" optPBE_Static = "optPBE Static" optPBE_Structure_Optimization = "optPBE Structure Optimization" optPBE_U_DFPT = "optPBE+U DFPT" @@ -783,6 +835,7 @@ class CalcType(IgnoreCaseEnum): optPBE_U_NSCF_Line = "optPBE+U NSCF Line" optPBE_U_NSCF_Uniform = "optPBE+U NSCF Uniform" optPBE_U_Optic = "optPBE+U Optic" + optPBE_U_SCF_Line = "optPBE+U SCF Line" optPBE_U_Static = "optPBE+U Static" optPBE_U_Structure_Optimization = "optPBE+U Structure Optimization" optPBE_U_Unrecognized = "optPBE+U Unrecognized" @@ -797,6 +850,7 @@ class CalcType(IgnoreCaseEnum): optPBE_vdW_NSCF_Line = "optPBE-vdW NSCF Line" optPBE_vdW_NSCF_Uniform = "optPBE-vdW NSCF Uniform" optPBE_vdW_Optic = "optPBE-vdW Optic" + optPBE_vdW_SCF_Line = "optPBE-vdW SCF Line" optPBE_vdW_Static = "optPBE-vdW Static" optPBE_vdW_Structure_Optimization = "optPBE-vdW Structure Optimization" optPBE_vdW_U_DFPT = "optPBE-vdW+U DFPT" @@ -811,6 +865,7 @@ class CalcType(IgnoreCaseEnum): optPBE_vdW_U_NSCF_Line = "optPBE-vdW+U NSCF Line" optPBE_vdW_U_NSCF_Uniform = "optPBE-vdW+U NSCF Uniform" optPBE_vdW_U_Optic = "optPBE-vdW+U Optic" + optPBE_vdW_U_SCF_Line = "optPBE-vdW+U SCF Line" optPBE_vdW_U_Static = "optPBE-vdW+U Static" optPBE_vdW_U_Structure_Optimization = "optPBE-vdW+U Structure Optimization" optPBE_vdW_U_Unrecognized = "optPBE-vdW+U Unrecognized" @@ -825,6 +880,7 @@ class CalcType(IgnoreCaseEnum): r2SCAN_NSCF_Line = "r2SCAN NSCF Line" r2SCAN_NSCF_Uniform = "r2SCAN NSCF Uniform" r2SCAN_Optic = "r2SCAN Optic" + r2SCAN_SCF_Line = "r2SCAN SCF Line" r2SCAN_Static = "r2SCAN Static" r2SCAN_Structure_Optimization = "r2SCAN Structure Optimization" r2SCAN_U_DFPT = "r2SCAN+U DFPT" @@ -837,6 +893,7 @@ class CalcType(IgnoreCaseEnum): r2SCAN_U_NSCF_Line = "r2SCAN+U NSCF Line" r2SCAN_U_NSCF_Uniform = "r2SCAN+U NSCF Uniform" r2SCAN_U_Optic = "r2SCAN+U Optic" + r2SCAN_U_SCF_Line = "r2SCAN+U SCF Line" r2SCAN_U_Static = "r2SCAN+U Static" r2SCAN_U_Structure_Optimization = "r2SCAN+U Structure Optimization" r2SCAN_U_Unrecognized = "r2SCAN+U Unrecognized" @@ -853,6 +910,7 @@ class CalcType(IgnoreCaseEnum): r2SCAN_rVV10_NSCF_Line = "r2SCAN-rVV10 NSCF Line" r2SCAN_rVV10_NSCF_Uniform = "r2SCAN-rVV10 NSCF Uniform" r2SCAN_rVV10_Optic = "r2SCAN-rVV10 Optic" + r2SCAN_rVV10_SCF_Line = "r2SCAN-rVV10 SCF Line" r2SCAN_rVV10_Static = "r2SCAN-rVV10 Static" r2SCAN_rVV10_Structure_Optimization = "r2SCAN-rVV10 Structure Optimization" r2SCAN_rVV10_U_DFPT = "r2SCAN-rVV10+U DFPT" @@ -867,6 +925,7 @@ class CalcType(IgnoreCaseEnum): r2SCAN_rVV10_U_NSCF_Line = "r2SCAN-rVV10+U NSCF Line" r2SCAN_rVV10_U_NSCF_Uniform = "r2SCAN-rVV10+U NSCF Uniform" r2SCAN_rVV10_U_Optic = "r2SCAN-rVV10+U Optic" + r2SCAN_rVV10_U_SCF_Line = "r2SCAN-rVV10+U SCF Line" r2SCAN_rVV10_U_Static = "r2SCAN-rVV10+U Static" r2SCAN_rVV10_U_Structure_Optimization = "r2SCAN-rVV10+U Structure Optimization" r2SCAN_rVV10_U_Unrecognized = "r2SCAN-rVV10+U Unrecognized" @@ -891,6 +950,7 @@ class CalcType(IgnoreCaseEnum): revPBE_PADE_NSCF_Line = "revPBE+PADE NSCF Line" revPBE_PADE_NSCF_Uniform = "revPBE+PADE NSCF Uniform" revPBE_PADE_Optic = "revPBE+PADE Optic" + revPBE_PADE_SCF_Line = "revPBE+PADE SCF Line" revPBE_PADE_Static = "revPBE+PADE Static" revPBE_PADE_Structure_Optimization = "revPBE+PADE Structure Optimization" revPBE_PADE_U_DFPT = "revPBE+PADE+U DFPT" @@ -905,10 +965,12 @@ class CalcType(IgnoreCaseEnum): revPBE_PADE_U_NSCF_Line = "revPBE+PADE+U NSCF Line" revPBE_PADE_U_NSCF_Uniform = "revPBE+PADE+U NSCF Uniform" revPBE_PADE_U_Optic = "revPBE+PADE+U Optic" + revPBE_PADE_U_SCF_Line = "revPBE+PADE+U SCF Line" revPBE_PADE_U_Static = "revPBE+PADE+U Static" revPBE_PADE_U_Structure_Optimization = "revPBE+PADE+U Structure Optimization" revPBE_PADE_U_Unrecognized = "revPBE+PADE+U Unrecognized" revPBE_PADE_Unrecognized = "revPBE+PADE Unrecognized" + revPBE_SCF_Line = "revPBE SCF Line" revPBE_Static = "revPBE Static" revPBE_Structure_Optimization = "revPBE Structure Optimization" revPBE_U_DFPT = "revPBE+U DFPT" @@ -921,6 +983,7 @@ class CalcType(IgnoreCaseEnum): revPBE_U_NSCF_Line = "revPBE+U NSCF Line" revPBE_U_NSCF_Uniform = "revPBE+U NSCF Uniform" revPBE_U_Optic = "revPBE+U Optic" + revPBE_U_SCF_Line = "revPBE+U SCF Line" revPBE_U_Static = "revPBE+U Static" revPBE_U_Structure_Optimization = "revPBE+U Structure Optimization" revPBE_U_Unrecognized = "revPBE+U Unrecognized" @@ -935,6 +998,7 @@ class CalcType(IgnoreCaseEnum): revPBE_vdW_NSCF_Line = "revPBE-vdW NSCF Line" revPBE_vdW_NSCF_Uniform = "revPBE-vdW NSCF Uniform" revPBE_vdW_Optic = "revPBE-vdW Optic" + revPBE_vdW_SCF_Line = "revPBE-vdW SCF Line" revPBE_vdW_Static = "revPBE-vdW Static" revPBE_vdW_Structure_Optimization = "revPBE-vdW Structure Optimization" revPBE_vdW_U_DFPT = "revPBE-vdW+U DFPT" @@ -949,6 +1013,7 @@ class CalcType(IgnoreCaseEnum): revPBE_vdW_U_NSCF_Line = "revPBE-vdW+U NSCF Line" revPBE_vdW_U_NSCF_Uniform = "revPBE-vdW+U NSCF Uniform" revPBE_vdW_U_Optic = "revPBE-vdW+U Optic" + revPBE_vdW_U_SCF_Line = "revPBE-vdW+U SCF Line" revPBE_vdW_U_Static = "revPBE-vdW+U Static" revPBE_vdW_U_Structure_Optimization = "revPBE-vdW+U Structure Optimization" revPBE_vdW_U_Unrecognized = "revPBE-vdW+U Unrecognized" @@ -963,6 +1028,7 @@ class CalcType(IgnoreCaseEnum): rev_vdW_DF2_NSCF_Line = "rev-vdW-DF2 NSCF Line" rev_vdW_DF2_NSCF_Uniform = "rev-vdW-DF2 NSCF Uniform" rev_vdW_DF2_Optic = "rev-vdW-DF2 Optic" + rev_vdW_DF2_SCF_Line = "rev-vdW-DF2 SCF Line" rev_vdW_DF2_Static = "rev-vdW-DF2 Static" rev_vdW_DF2_Structure_Optimization = "rev-vdW-DF2 Structure Optimization" rev_vdW_DF2_U_DFPT = "rev-vdW-DF2+U DFPT" @@ -977,6 +1043,7 @@ class CalcType(IgnoreCaseEnum): rev_vdW_DF2_U_NSCF_Line = "rev-vdW-DF2+U NSCF Line" rev_vdW_DF2_U_NSCF_Uniform = "rev-vdW-DF2+U NSCF Uniform" rev_vdW_DF2_U_Optic = "rev-vdW-DF2+U Optic" + rev_vdW_DF2_U_SCF_Line = "rev-vdW-DF2+U SCF Line" rev_vdW_DF2_U_Static = "rev-vdW-DF2+U Static" rev_vdW_DF2_U_Structure_Optimization = "rev-vdW-DF2+U Structure Optimization" rev_vdW_DF2_U_Unrecognized = "rev-vdW-DF2+U Unrecognized" @@ -991,6 +1058,7 @@ class CalcType(IgnoreCaseEnum): vdW_DF2_NSCF_Line = "vdW-DF2 NSCF Line" vdW_DF2_NSCF_Uniform = "vdW-DF2 NSCF Uniform" vdW_DF2_Optic = "vdW-DF2 Optic" + vdW_DF2_SCF_Line = "vdW-DF2 SCF Line" vdW_DF2_Static = "vdW-DF2 Static" vdW_DF2_Structure_Optimization = "vdW-DF2 Structure Optimization" vdW_DF2_U_DFPT = "vdW-DF2+U DFPT" @@ -1003,6 +1071,7 @@ class CalcType(IgnoreCaseEnum): vdW_DF2_U_NSCF_Line = "vdW-DF2+U NSCF Line" vdW_DF2_U_NSCF_Uniform = "vdW-DF2+U NSCF Uniform" vdW_DF2_U_Optic = "vdW-DF2+U Optic" + vdW_DF2_U_SCF_Line = "vdW-DF2+U SCF Line" vdW_DF2_U_Static = "vdW-DF2+U Static" vdW_DF2_U_Structure_Optimization = "vdW-DF2+U Structure Optimization" vdW_DF2_U_Unrecognized = "vdW-DF2+U Unrecognized" diff --git a/emmet-core/emmet/core/vasp/calc_types/utils.py b/emmet-core/emmet/core/vasp/calc_types/utils.py index 4aa1fa0953..bb0193cce4 100644 --- a/emmet-core/emmet/core/vasp/calc_types/utils.py +++ b/emmet-core/emmet/core/vasp/calc_types/utils.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING from monty.serialization import loadfn - +import numpy as np from pymatgen.io.vasp import Kpoints from emmet.core.vasp.calc_types.enums import CalcType, RunType, TaskType @@ -112,6 +112,12 @@ def task_type(inputs: dict[str, Any]) -> TaskType: calc_type.append("Optic") elif incar.get("ALGO", "").upper() == "CHI": calc_type.append("Optic") + elif np.any(np.abs(kpts.get("kpts_weights") or [1e20]) < 1e-6) and ( + incar.get("METAGGA") is not None or incar.get("LHFCALC", False) + ): + # Static meta-GGA or hybrid calculation with zero-weighted k-points + # Highly-likely to be a self-consistent line-mode calculation + calc_type.append("SCF Line") else: calc_type.append("Static") diff --git a/emmet-core/tests/test_band_theory.py b/emmet-core/tests/test_band_theory.py index 1f63b00fa7..3613d33a81 100644 --- a/emmet-core/tests/test_band_theory.py +++ b/emmet-core/tests/test_band_theory.py @@ -10,14 +10,15 @@ from emmet.core import ARROW_COMPATIBLE from emmet.core.band_theory import ( + BSPathType, ElectronicBS, ProjectedBS, ElectronicDos, ProjectedDos, obtain_path_type, - get_path_from_bandstructure, + _coarse_list_superset, + _loose_path_match, ) -from emmet.core.electronic_structure import BSPathType from emmet.core.testing_utils import DataArchive if ARROW_COMPATIBLE: @@ -35,7 +36,7 @@ def bs_fixture(test_dir): parse_projected_eigen=True, ) pmg_bs = vasprun.get_band_structure() - elec_bs = ElectronicBS.from_pmg(pmg_bs) + elec_bs = ElectronicBS.from_pmg(pmg_bs, identifier="mp-0") return (vasprun, pmg_bs, elec_bs) @@ -49,7 +50,7 @@ def dos_fixture(test_dir): parse_projected_eigen=True, ) pmg_dos = vasprun.complete_dos - edos = ElectronicDos.from_pmg(pmg_dos) + edos = ElectronicDos.from_pmg(pmg_dos, identifier="mp-0") return (vasprun, pmg_dos, edos) @@ -91,6 +92,12 @@ def test_elec_band_struct(bs_fixture): # round trip pymatgen assert pmg_bs.as_dict() == elec_bs.to_pmg().as_dict() + assert ( + str(elec_bs) + == f"ElectronicBS({elec_bs.identifier}: {elec_bs.structure.formula})" + ) + assert elec_bs.__repr__() == str(elec_bs) + def test_base_electronic_dos(): """Test base electronic DOS class for jellium.""" @@ -155,6 +162,9 @@ def test_electronic_dos(dos_fixture): ) assert isinstance(edos_incomplete.to_pmg(), Dos) + assert str(edos) == f"ElectronicDos({edos.identifier}: {edos.structure.formula})" + assert edos.__repr__() == str(edos) + @pytest.mark.skipif( not ARROW_COMPATIBLE, reason="pyarrow must be installed to run this test." @@ -180,32 +190,48 @@ def test_arrow(bs_fixture, dos_fixture): def test_obtain_path_type(test_dir): line_band_struct = loadfn(test_dir / "electronic_structure" / "Fe_bs.json.gz") - path_order = get_path_from_bandstructure(line_band_struct) - assert path_order == [ + + path_type, kpath, _ = next( + obtain_path_type( + line_band_struct.structure, + [x.frac_coords for x in line_band_struct.kpoints], + ) + ) + assert isinstance(path_type, BSPathType) + assert path_type == BSPathType.setyawan_curtarolo + assert kpath == [ "\\Gamma", "H", - "H", "N", - "N", - "\\Gamma", "\\Gamma", "P", - "P", "H", "P", "N", ] - assert all(k in line_band_struct.labels_dict for k in path_order) - path_type = next( - obtain_path_type( - { - label: kpt.frac_coords - for label, kpt in line_band_struct.labels_dict.items() - }, - line_band_struct.structure, - path_order, - ) + +def test_utilities(): + + assert _coarse_list_superset([1, 2, 3, 4, 5, 6, 7], [3, 4, 5]) + assert _coarse_list_superset([1, 2, 3, 4, 5, 6, 7], [3, 4, 5, 6, 7]) + assert _coarse_list_superset([1, 2, 3, 4, 5, 6, 7], [1, 2]) + assert not _coarse_list_superset(["a", "b", "c", "d", "e"], ["b", "d", "f"]) + + assert ( + _loose_path_match(["\\Gamma", "A", "B", "P_1"]) == BSPathType.setyawan_curtarolo ) - assert isinstance(path_type, BSPathType) - assert path_type == BSPathType.setyawan_curtarolo + assert _loose_path_match(["\\Gamma", "GAMMA", "B"]) == BSPathType.unknown + assert _loose_path_match(["\\Gamma", "Γ", "B"]) == BSPathType.unknown + assert _loose_path_match(["\\Gamma", "A", "B", r"P_{1}"]) == BSPathType.unknown + + assert _loose_path_match(["GAMMA", "A", "B", "P_1"]) == BSPathType.hinuma + assert _loose_path_match(["\\Gamma", "GAMMA", "B"]) == BSPathType.unknown + assert _loose_path_match(["GAMMA", "Γ", "B"]) == BSPathType.unknown + assert _loose_path_match(["GAMMA", "a", "B"]) == BSPathType.unknown + assert _loose_path_match(["GAMMA", "A", "B", r"P_{1}"]) == BSPathType.unknown + + assert _loose_path_match(["Γ", "a", "b", r"p_{1}"]) == BSPathType.latimer_munro + assert _loose_path_match(["Γ", "\\Gamma", "b"]) == BSPathType.unknown + assert _loose_path_match(["GAMMA", "Γ", "b"]) == BSPathType.unknown + assert _loose_path_match(["Γ", "a", "b", "P_1"]) == BSPathType.unknown