Skip to content

Commit

Permalink
Merge pull request #174 from materialsproject/settings_update
Browse files Browse the repository at this point in the history
Fix serialization and update validation
  • Loading branch information
shyamd committed Mar 10, 2021
2 parents ed03f2b + f51232a commit 9a082bc
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 18 deletions.
2 changes: 1 addition & 1 deletion emmet-builders/emmet/builders/vasp/materials.py
Expand Up @@ -62,7 +62,7 @@ def __init__(
self.materials = materials
self.task_validation = task_validation
self.query = query if query else {}
self.settings = settings or SETTINGS
self.settings = EmmetBuildSettings.autoload(settings)
self.kwargs = kwargs

sources = [tasks]
Expand Down
6 changes: 2 additions & 4 deletions emmet-builders/emmet/builders/vasp/task_validator.py
Expand Up @@ -11,9 +11,6 @@
from emmet.core.vasp.validation import DeprecationMessage, ValidationDoc
from emmet.builders.settings import EmmetBuildSettings

__author__ = "Shyam Dwaraknath"
__email__ = "shyamd@lbl.gov"


class TaskValidator(MapBuilder):
def __init__(
Expand All @@ -32,7 +29,7 @@ def __init__(
"""
self.tasks = tasks
self.task_validation = task_validation
self.settings = settings or SETTINGS
self.settings = EmmetBuildSettings.autoload(settings)
self.kwargs = kwargs

super().__init__(
Expand All @@ -59,6 +56,7 @@ def unary_function(self, item):
validation_doc = ValidationDoc.from_task_doc(
task_doc=task_doc,
kpts_tolerance=self.settings.VASP_KPTS_TOLERANCE,
kspacing_tolerance=self.settings.VASP_KSPACING_TOLERANCE,
input_sets=self.settings.VASP_DEFAULT_INPUT_SETS,
LDAU_fields=self.settings.VASP_CHECKED_LDAU_FIELDS,
max_allowed_scf_gradient=self.settings.VASP_MAX_SCF_GRADIENT,
Expand Down
31 changes: 30 additions & 1 deletion emmet-core/emmet/core/settings.py
Expand Up @@ -3,7 +3,7 @@
"""
import importlib
import json
from typing import Dict, List, Optional
from typing import Dict, List, Optional, Type, TypeVar, Union

import requests
from pydantic import BaseSettings, Field, root_validator, validator
Expand All @@ -12,6 +12,9 @@
DEFAULT_CONFIG_FILE_PATH = str(Path.home().joinpath(".emmet.json"))


S = TypeVar("S", bound="EmmetSettings")


class EmmetSettings(BaseSettings):
"""
Settings for the emmet- packages
Expand Down Expand Up @@ -54,6 +57,11 @@ class EmmetSettings(BaseSettings):
description="Relative tolerance for kpt density to still be a valid task document",
)

VASP_KSPACING_TOLERANCE: float = Field(
0.05,
description="Relative tolerance for kspacing to still be a valid task document",
)

VASP_DEFAULT_INPUT_SETS: Dict[str, PyObject] = Field(
{
"GGA Structure Optimization": "pymatgen.io.vasp.sets.MPRelaxSet",
Expand Down Expand Up @@ -94,3 +102,24 @@ def load_default_settings(cls, values):
new_values.update(values)

return new_values

@classmethod
def autoload(cls: Type[S], settings: Union[None, dict, S]) -> S:
if settings is None:
return cls()
elif isinstance(settings, dict):
return cls(**settings)
return settings

def as_dict(self):
"""
HotPatch to enable serializing EmmetSettings via Monty
"""
return self.dict(exclude_unset=True, exclude_defaults=True)

@classmethod
def from_dict(cls: Type[S], settings: Dict) -> S:
"""
HotPatch to enable serializing EmmetSettings via Monty
"""
return cls(**settings)
41 changes: 29 additions & 12 deletions emmet-core/emmet/core/vasp/validation.py
Expand Up @@ -14,6 +14,7 @@
class DeprecationMessage(DocEnum):
MANUAL = "M", "manual deprecation"
KPTS = "C001", "Too few KPoints"
KSPACING = "C002", "KSpacing not high enough"
ENCUT = "C002", "ENCUT too low"
FORCES = "C003", "Forces too large"
CONVERGENCE = "E001", "Calculation did not converge"
Expand Down Expand Up @@ -53,6 +54,7 @@ def from_task_doc(
cls,
task_doc: TaskDocument,
kpts_tolerance: float = SETTINGS.VASP_KPTS_TOLERANCE,
kspacing_tolerance: float = SETTINGS.VASP_KSPACING_TOLERANCE,
input_sets: Dict[str, PyObject] = SETTINGS.VASP_DEFAULT_INPUT_SETS,
LDAU_fields: List[str] = SETTINGS.VASP_CHECKED_LDAU_FIELDS,
max_allowed_scf_gradient: float = SETTINGS.VASP_MAX_SCF_GRADIENT,
Expand All @@ -62,9 +64,12 @@ def from_task_doc(
Args:
task_doc: the task document to process
input_sets (dict): a dictionary of task_types -> pymatgen input set for validation
kpts_tolerance (float): the tolerance to allow kpts to lag behind the input set settings
LDAU_fields (list(String)): LDAU fields to check for consistency
kpts_tolerance: the tolerance to allow kpts to lag behind the input set settings
kspacing_tolerance: the tolerance to allow kspacing to lag behind the input set settings
input_sets: a dictionary of task_types -> pymatgen input set for validation
LDAU_fields: LDAU fields to check for consistency
max_allowed_scf_gradient: maximum uphill gradient allowed for SCF steps after the
initial equillibriation period
"""

structure = task_doc.output.structure
Expand All @@ -78,15 +83,27 @@ def from_task_doc(
valid_input_set = input_sets[task_type](structure)

# Checking K-Points
valid_num_kpts = valid_input_set.kpoints.num_kpts or np.prod(
valid_input_set.kpoints.kpts[0]
)
num_kpts = inputs.get("kpoints", {}).get("nkpoints", 0) or np.prod(
inputs.get("kpoints", {}).get("kpoints", [1, 1, 1])
)
data["kpts_ratio"] = num_kpts / valid_num_kpts
if data["kpts_ratio"] < kpts_tolerance:
reasons.append(DeprecationMessage.KPTS)
# Calculations that use KSPACING will not have a .kpoints attr
if valid_input_set.kpoints is not None:
valid_num_kpts = valid_input_set.kpoints.num_kpts or np.prod(
valid_input_set.kpoints.kpts[0]
)
num_kpts = inputs.get("kpoints", {}).get("nkpoints", 0) or np.prod(
inputs.get("kpoints", {}).get("kpoints", [1, 1, 1])
)
data["kpts_ratio"] = num_kpts / valid_num_kpts
if data["kpts_ratio"] < kpts_tolerance:
reasons.append(DeprecationMessage.KPTS)

else:
valid_kspacing = valid_input_set.incar.get("KSPACING", 0)
if inputs.get("incar", {}).get("KSPACING"):
data["kspacing_delta"] = (
inputs["incar"].get("KSPACING") - valid_kspacing
)
# larger KSPACING means fewer k-points
if data["kspacing_delta"] > kspacing_tolerance:
reasons.append(DeprecationMessage.KSPACING)

# Checking ENCUT
encut = inputs.get("incar", {}).get("ENCUT")
Expand Down
14 changes: 14 additions & 0 deletions tests/emmet-core/test_settings.py
Expand Up @@ -3,6 +3,9 @@
from pathlib import PosixPath
from random import random

from monty.serialization import dumpfn, loadfn
from monty.tempfile import ScratchDir

from emmet.core.settings import EmmetSettings


Expand Down Expand Up @@ -40,3 +43,14 @@ def test_from_url():
test_config = EmmetSettings()

assert test_config.ANGLE_TOL == 1.0


def test_seriallization():

test_config = EmmetSettings()

with ScratchDir("."):
dumpfn(test_config, "test.json")
reload_config = loadfn("test.json")

assert isinstance(reload_config, EmmetSettings)

0 comments on commit 9a082bc

Please sign in to comment.