Skip to content

Commit

Permalink
Apply MP corrections in MP recipes (#1820)
Browse files Browse the repository at this point in the history
Closes #1747.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
Andrew-S-Rosen and pre-commit-ci[bot] committed Mar 3, 2024
1 parent 924329d commit 56d828a
Show file tree
Hide file tree
Showing 35 changed files with 88 additions and 26 deletions.
9 changes: 8 additions & 1 deletion src/quacc/recipes/vasp/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def base_fn(
preset: str | None = None,
calc_defaults: dict[str, Any] | None = None,
calc_swaps: dict[str, Any] | None = None,
report_mp_corrections: bool = False,
additional_fields: dict[str, Any] | None = None,
copy_files: SourceDirectory | dict[SourceDirectory, Filenames] | None = None,
) -> VaspSchema:
Expand All @@ -41,6 +42,8 @@ def base_fn(
Dictionary of custom kwargs for the Vasp calculator. Set a value to
`None` to remove a pre-existing key entirely. For a list of available
keys, refer to [quacc.calculators.vasp.vasp.Vasp][].
report_mp_corrections
Whether to report the Materials Project corrections in the results.
additional_fields
Additional fields to supply to the summarizer.
copy_files
Expand All @@ -56,4 +59,8 @@ def base_fn(
atoms.calc = Vasp(atoms, preset=preset, **calc_flags)
final_atoms = run_calc(atoms, copy_files=copy_files)

return vasp_summarize_run(final_atoms, additional_fields=additional_fields)
return vasp_summarize_run(
final_atoms,
report_mp_corrections=report_mp_corrections,
additional_fields=additional_fields,
)
5 changes: 5 additions & 0 deletions src/quacc/recipes/vasp/mp.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def mp_gga_relax_job(
atoms,
calc_defaults=calc_defaults,
calc_swaps=calc_kwargs,
report_mp_corrections=True,
additional_fields={"name": "MP GGA Relax"},
copy_files=copy_files,
)
Expand Down Expand Up @@ -120,6 +121,7 @@ def mp_gga_static_job(
atoms,
calc_defaults=calc_defaults,
calc_swaps=calc_kwargs,
report_mp_corrections=True,
additional_fields={"name": "MP GGA Static"},
copy_files=copy_files,
)
Expand Down Expand Up @@ -173,6 +175,7 @@ def mp_metagga_prerelax_job(
atoms,
calc_defaults=calc_defaults,
calc_swaps=calc_kwargs,
report_mp_corrections=True,
additional_fields={"name": "MP Meta-GGA Pre-Relax"},
copy_files=copy_files,
)
Expand Down Expand Up @@ -222,6 +225,7 @@ def mp_metagga_relax_job(
atoms,
calc_defaults=calc_defaults,
calc_swaps=calc_kwargs,
report_mp_corrections=True,
additional_fields={"name": "MP Meta-GGA Relax"},
copy_files=copy_files,
)
Expand Down Expand Up @@ -272,6 +276,7 @@ def mp_metagga_static_job(
atoms,
calc_defaults=calc_defaults,
calc_swaps=calc_kwargs,
report_mp_corrections=True,
additional_fields={"name": "MP Meta-GGA Static"},
copy_files=copy_files,
)
Expand Down
23 changes: 22 additions & 1 deletion src/quacc/schemas/vasp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from monty.os.path import zpath
from pymatgen.command_line.bader_caller import bader_analysis_from_path
from pymatgen.command_line.chargemol_caller import ChargemolAnalysis
from pymatgen.entries.compatibility import (
CompatibilityError,
MaterialsProject2020Compatibility,
)

from quacc import SETTINGS
from quacc.schemas.ase import summarize_run
Expand All @@ -36,6 +40,7 @@ def vasp_summarize_run(
run_bader: bool | None = None,
run_chargemol: bool | None = None,
check_convergence: bool | None = None,
report_mp_corrections: bool = False,
additional_fields: dict[str, Any] | None = None,
store: Store | None = None,
) -> VaspSchema:
Expand All @@ -62,6 +67,8 @@ def vasp_summarize_run(
check_convergence
Whether to throw an error if convergence is not reached. Defaults to True in
settings.
report_mp_corrections
Whether to apply the MP corrections to the task document. Defaults to False.
additional_fields
Additional fields to add to the task document.
store
Expand All @@ -85,7 +92,21 @@ def vasp_summarize_run(

# Fetch all tabulated results from VASP outputs files. Fortunately, emmet
# already has a handy function for this
vasp_task_doc = TaskDoc.from_directory(dir_path).model_dump()
vasp_task_model = TaskDoc.from_directory(dir_path)

# Get MP corrections
if report_mp_corrections:
mp_compat = MaterialsProject2020Compatibility()
try:
corrected_entry = mp_compat.process_entry(
vasp_task_model.structure_entry, on_error="raise"
)
vasp_task_model.entry = corrected_entry
except CompatibilityError as err:
logger.warning(err)

# Convert the VASP task model to a dictionary
vasp_task_doc = vasp_task_model.model_dump()

# Check for calculation convergence
if check_convergence and vasp_task_doc["state"] != "successful":
Expand Down
1 change: 0 additions & 1 deletion tests/core/atoms/test_atoms_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import numpy as np
import pytest
from ase import Atoms
from ase.atoms import Atoms
from ase.build import bulk, molecule
from ase.io import read

Expand Down
2 changes: 1 addition & 1 deletion tests/core/recipes/espresso_recipes/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest


@pytest.fixture
@pytest.fixture()
def ESPRESSO_PARALLEL_INFO():
from shutil import which

Expand Down
8 changes: 6 additions & 2 deletions tests/core/recipes/espresso_recipes/test_phonons.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ def test_phonon_job(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
)

ph_results = phonon_job(
pw_results["dir_name"], input_data=ph_loose, parallel_info=ESPRESSO_PARALLEL_INFO,
pw_results["dir_name"],
input_data=ph_loose,
parallel_info=ESPRESSO_PARALLEL_INFO,
)

assert_allclose(
Expand Down Expand Up @@ -171,7 +173,9 @@ def test_q2r_job(tmp_path, monkeypatch, ESPRESSO_PARALLEL_INFO):
additional_cards = ["1 1 1", "1", "matdyn"]

q2r_results = q2r_job(
tmp_path, additional_cards=additional_cards, parallel_info=ESPRESSO_PARALLEL_INFO
tmp_path,
additional_cards=additional_cards,
parallel_info=ESPRESSO_PARALLEL_INFO,
)

assert Path(q2r_results["dir_name"], "q2r.fc.gz").exists()
Expand Down
2 changes: 2 additions & 0 deletions tests/core/recipes/gulp_recipes/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def mock_settings_env_vars():

def mock_execute(self, *args, **kwargs):
from shutil import copy

copy(GULP_DIR / "gulp.got.gz", Path(self.directory, "gulp.got.gz"))
copy(GULP_DIR / "gulp.cif.gz", Path(self.directory, "gulp.cif.gz"))
copy(GULP_DIR / "gulp.xyz.gz", Path(self.directory, "gulp.xyz.gz"))
Expand All @@ -31,6 +32,7 @@ def patch_execute(monkeypatch):
def mock_read_results(self, *args, **kwargs):
from ase.calculators.lj import LennardJones
from ase.io import read

atoms = read(Path(self.directory, "gulp.xyz.gz"))
atoms.calc = LennardJones()
atoms.get_potential_energy()
Expand Down
1 change: 0 additions & 1 deletion tests/core/recipes/vasp_recipes/mocked/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,4 @@ def mock_taskdoc(*args, **kwargs):

@pytest.fixture(autouse=True)
def patch_taskdoc(monkeypatch):

monkeypatch.setattr("quacc.schemas.vasp.TaskDoc.from_directory", mock_taskdoc)
3 changes: 1 addition & 2 deletions tests/core/recipes/vasp_recipes/mocked/test_vasp_recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
mp_metagga_static_job,
)
from quacc.recipes.vasp.qmof import qmof_relax_job
from quacc.recipes.vasp.slabs import bulk_to_slabs_flow
from quacc.recipes.vasp.slabs import bulk_to_slabs_flow, slab_to_ads_flow
from quacc.recipes.vasp.slabs import relax_job as slab_relax_job
from quacc.recipes.vasp.slabs import slab_to_ads_flow
from quacc.recipes.vasp.slabs import static_job as slab_static_job

DEFAULT_SETTINGS = SETTINGS.model_copy()
Expand Down
2 changes: 1 addition & 1 deletion tests/core/schemas/test_ase.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

FILE_DIR = Path(__file__).parent

RUN1 = FILE_DIR / "vasp_run1"
RUN1 = FILE_DIR / "test_files" / "vasp_run1"


def test_summarize_run():
Expand Down
26 changes: 14 additions & 12 deletions tests/core/schemas/test_cclib_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@

FILE_DIR = Path(__file__).parent

run1 = FILE_DIR / "gaussian_run1"
run1 = FILE_DIR / "test_files" / "gaussian_run1"
log1 = run1 / "Gaussian.log"
run2 = FILE_DIR / "cclib_data"
run2 = FILE_DIR / "test_files" / "cclib_data"
log2 = run2 / "gau_testopt.log.gz"


Expand All @@ -35,7 +35,7 @@ def cclib_obj():


def setup_module():
p = FILE_DIR / "cclib_data"
p = FILE_DIR / "test_files" / "cclib_data"

with (
gzip.open(p / "psi_test.cube.gz", "r") as f_in,
Expand All @@ -45,7 +45,7 @@ def setup_module():


def teardown_module():
p = FILE_DIR / "cclib_data"
p = FILE_DIR / "test_files" / "cclib_data"

if os.path.exists(p / "psi_test.cube"):
os.remove(p / "psi_test.cube")
Expand Down Expand Up @@ -143,7 +143,7 @@ def test_errors():
def test_cclib_taskdoc(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)

p = FILE_DIR / "cclib_data"
p = FILE_DIR / "test_files" / "cclib_data"

# Now we will try two possible extensions, but we will make sure that
# it fails because the newest log file (.txt) is not valid
Expand Down Expand Up @@ -196,34 +196,36 @@ def test_cclib_calculate(tmp_path, monkeypatch, cclib_obj):
_cclib_calculate(
cclib_obj,
method="ddec6",
cube_file=FILE_DIR / "cclib_data" / "psi_test.cube",
cube_file=FILE_DIR / "test_files" / "cclib_data" / "psi_test.cube",
proatom_dir="does_not_exists",
)

with pytest.raises(OSError):
_cclib_calculate(
cclib_obj,
method="ddec6",
cube_file=FILE_DIR / "cclib_data" / "psi_test.cube",
cube_file=FILE_DIR / "test_files" / "cclib_data" / "psi_test.cube",
)

with pytest.raises(Exception):
_cclib_calculate(
cclib_obj,
method="ddec6",
cube_file=FILE_DIR / "cclib_data" / "psi_test.cube",
proatom_dir=FILE_DIR / "cclib_data" / "psi_test.cube",
cube_file=FILE_DIR / "test_files" / "cclib_data" / "psi_test.cube",
proatom_dir=FILE_DIR / "test_files" / "cclib_data" / "psi_test.cube",
)


def test_monkeypatches(tmp_path, monkeypatch, cclib_obj, caplog):
monkeypatch.chdir(tmp_path)
monkeypatch.setenv("PROATOM_DIR", str(FILE_DIR / "cclib_data" / "proatomdata"))
monkeypatch.setenv(
"PROATOM_DIR", str(FILE_DIR / "test_files" / "cclib_data" / "proatomdata")
)
with pytest.raises(FileNotFoundError):
_cclib_calculate(
cclib_obj,
method="ddec6",
cube_file=FILE_DIR / "cclib_data" / "psi_test.cube",
cube_file=FILE_DIR / "test_files" / "cclib_data" / "psi_test.cube",
)

monkeypatch.setattr("cclib.method.Bader.calculate", bad_mock_cclib_calculate)
Expand All @@ -232,7 +234,7 @@ def test_monkeypatches(tmp_path, monkeypatch, cclib_obj, caplog):
_cclib_calculate(
cclib_obj,
method="bader",
cube_file=FILE_DIR / "cclib_data" / "psi_test.cube",
cube_file=FILE_DIR / "test_files" / "cclib_data" / "psi_test.cube",
)
is None
)
Binary file not shown.
Binary file added tests/core/schemas/test_files/vasp_mp_run1/INCAR.gz
Binary file not shown.
Binary file not shown.
Binary file added tests/core/schemas/test_files/vasp_mp_run1/POSCAR.gz
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
28 changes: 26 additions & 2 deletions tests/core/schemas/test_vasp_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@

@pytest.fixture()
def run1():
from pathlib import Path
FILE_DIR = Path(__file__).parent

return FILE_DIR / "test_files" / "vasp_run1"


@pytest.fixture()
def mp_run1():
FILE_DIR = Path(__file__).parent

return FILE_DIR / "vasp_run1"
return FILE_DIR / "test_files" / "vasp_mp_run1"


def mock_bader_analysis(*args, **kwargs):
Expand Down Expand Up @@ -196,6 +201,25 @@ def test_summarize_bader_and_chargemol_run(monkeypatch, run1, tmp_path):
assert results["bader"]["spin_moments"] == [0.0] * len(atoms)


def test_summarize_mp(monkeypatch, mp_run1, tmp_path):
monkeypatch.chdir(tmp_path)
p = tmp_path / "vasp_run"
copytree(mp_run1, p)
atoms = read(p / "OUTCAR.gz")
results = vasp_summarize_run(atoms, dir_path=p, report_mp_corrections=True)
assert results["entry"].correction == pytest.approx(-3.2279999999999998)


def test_summarize_mp_bad(monkeypatch, run1, tmp_path, caplog):
monkeypatch.chdir(tmp_path)
p = tmp_path / "vasp_run"
copytree(run1, p)
atoms = read(p / "OUTCAR.gz")
with caplog.at_level(logging.WARNING):
vasp_summarize_run(atoms, dir_path=p, report_mp_corrections=True)
assert "invalid run type" in caplog.text


def test_no_bader(tmp_path, monkeypatch, run1, caplog):
monkeypatch.chdir(tmp_path)

Expand Down
Binary file removed tests/core/schemas/vasp_run_bad/CONTCAR.gz
Binary file not shown.
Binary file removed tests/core/schemas/vasp_run_bad/INCAR.gz
Binary file not shown.
Binary file removed tests/core/schemas/vasp_run_bad/OUTCAR.gz
Binary file not shown.
Binary file removed tests/core/schemas/vasp_run_bad/POSCAR.gz
Binary file not shown.
Binary file removed tests/core/schemas/vasp_run_bad/vasprun.xml.gz
Binary file not shown.
4 changes: 2 additions & 2 deletions tests/core/settings/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_results_dir(tmp_path, monkeypatch):
def test_env_var(monkeypatch, tmp_path):
p = tmp_path / "my/scratch/dir"
monkeypatch.setenv("QUACC_SCRATCH_DIR", p)
assert QuaccSettings().SCRATCH_DIR == p.expanduser().resolve()
assert p.expanduser().resolve() == QuaccSettings().SCRATCH_DIR


def test_env_var2(monkeypatch, tmp_path):
Expand Down Expand Up @@ -80,4 +80,4 @@ def test_yaml(tmp_path, monkeypatch):
with open(tmp_path / "quacc_test.yaml", "w") as f:
f.write(f"SCRATCH_DIR: {p}")
monkeypatch.setenv("QUACC_CONFIG_FILE", os.path.join(tmp_path, "quacc_test.yaml"))
assert QuaccSettings().SCRATCH_DIR == p.expanduser().resolve()
assert p.expanduser().resolve() == QuaccSettings().SCRATCH_DIR

0 comments on commit 56d828a

Please sign in to comment.