Skip to content

Commit

Permalink
Modify MP workflow to match that in atomate2 (#1033)
Browse files Browse the repository at this point in the history
Question to answer: Is ISMEAR = 0 or 2 in the pre-relax step? It could
be 0 because of the input set but 0 because default bandgap is 2 if not
known?

---------

Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com>
  • Loading branch information
Andrew-S-Rosen and deepsource-autofix[bot] authored Oct 11, 2023
1 parent f593298 commit 609705a
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 28 deletions.
3 changes: 1 addition & 2 deletions src/quacc/calculators/presets/vasp/BulkSet.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Last modified: 09-01-2023
# Last modified: 10-07-2023
inputs:
algo: fast
auto_kpts:
kppa: 1000
kppvol: 100
ediff: 1.0e-5
efermi: midgap
Expand Down
2 changes: 1 addition & 1 deletion src/quacc/calculators/presets/vasp/MPScanSet.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Default VASP settings for calculations in the Materials Project
# using the r2SCAN functional.
# Caution: The pseudopotentials should be used with the .54 PAW PBE set
# Source: https://github.com/materialsproject/pymatgen/blob/master/pymatgen/io/vasp/MPSCANRelaxSet.yaml
# Source: https://github.com/materialsproject/atomate2/blob/main/src/atomate2/vasp/sets/BaseMPR2SCANRelaxSet.yaml
# Last modified: 08-07-2023
inputs:
algo: all
Expand Down
2 changes: 1 addition & 1 deletion src/quacc/calculators/presets/vasp/magmoms_MP.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Magmoms used in the Materials Project
# Source: https://github.com/materialsproject/pymatgen/blob/master/pymatgen/io/vasp/VASPIncarBase.yaml
# Source: https://github.com/materialsproject/atomate2/blob/main/src/atomate2/vasp/sets/BaseMPR2SCANRelaxSet.yaml
# Last modified: 08-01-2023
inputs:
elemental_magmoms:
Expand Down
2 changes: 1 addition & 1 deletion src/quacc/calculators/presets/vasp/setups_pbe54_MP.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Materials Project pseudopotentials (r2SCAN workflow)
# Note: These are specifically the .54 PAW PBE potentials
# Source: https://github.com/materialsproject/pymatgen/blob/master/pymatgen/io/vasp/MPSCANRelaxSet.yaml
# Source: https://github.com/materialsproject/atomate2/blob/main/src/atomate2/vasp/sets/BaseMPR2SCANRelaxSet.yaml
# Last modified: 08-01-2023
inputs:
setups:
Expand Down
70 changes: 52 additions & 18 deletions src/quacc/recipes/vasp/mp.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class MPRelaxFlowSchema(VaspSchema):
def mp_prerelax_job(
atoms: Atoms | dict,
preset: str | None = "MPScanSet",
bandgap: float = None,
calc_swaps: dict | None = None,
copy_files: list[str] | None = None,
) -> VaspSchema:
Expand All @@ -47,7 +48,7 @@ def mp_prerelax_job(
Calculator Defaults:
```python
{"ediffg": -0.05, "xc": "pbesol"}
{"ediffg": -0.05, "xc": "pbesol", "lwave": True, "lcharg": True} | _get_bandgap_swaps(bandgap)
```
Parameters
Expand All @@ -57,6 +58,8 @@ def mp_prerelax_job(
the value
preset
Preset to use from `quacc.calculators.presets.vasp`.
bandgap
Estimate for the bandgap in eV.
calc_swaps
Dictionary of custom kwargs for the calculator. Set a value to `None` to remove
a pre-existing key entirely. Set a value to `None` to remove a pre-existing key entirely.
Expand All @@ -69,7 +72,13 @@ def mp_prerelax_job(
Dictionary of results from [quacc.schemas.vasp.vasp_summarize_run][]
"""

defaults = {"ediffg": -0.05, "xc": "pbesol"}
defaults = {
"ediffg": -0.05,
"xc": "pbesol",
"lwave": True,
"lcharg": True,
} | _get_bandgap_swaps(bandgap)

return _base_job(
atoms,
preset=preset,
Expand All @@ -84,6 +93,7 @@ def mp_prerelax_job(
def mp_relax_job(
atoms: Atoms | dict,
preset: str | None = "MPScanSet",
bandgap: float = None,
calc_swaps: dict | None = None,
copy_files: list[str] | None = None,
) -> VaspSchema:
Expand All @@ -96,7 +106,7 @@ def mp_relax_job(
Calculator Defaults:
```python
{}
{"lcharg": True, "lwave": True} | _get_bandgap_swaps(bandgap)
```
Parameters
Expand All @@ -106,6 +116,8 @@ def mp_relax_job(
the value
preset
Preset to use from `quacc.calculators.presets.vasp`.
bandgap
Estimate for the bandgap in eV.
calc_swaps
Dictionary of custom kwargs for the calculator. Set a value to `None` to remove
a pre-existing key entirely. Set a value to `None` to remove a pre-existing key entirely.
Expand All @@ -118,10 +130,11 @@ def mp_relax_job(
Dictionary of results from [quacc.schemas.vasp.vasp_summarize_run][]
"""

defaults = {"lcharg": True, "lwave": True} | _get_bandgap_swaps(bandgap)
return _base_job(
atoms,
preset=preset,
defaults={},
defaults=defaults,
calc_swaps=calc_swaps,
additional_fields={"name": "MP Relax"},
copy_files=copy_files,
Expand Down Expand Up @@ -161,23 +174,44 @@ def mp_relax_flow(
# Run the prerelax
prerelax_results = mp_prerelax_job(atoms, **prerelax_job_kwargs)

# Update KSPACING arguments
bandgap = prerelax_results["output"].get("bandgap", 0)
if bandgap < 1e-4:
kspacing_swaps = {"kspacing": 0.22, "sigma": 0.2, "ismear": 2}
else:
rmin = 25.22 - 2.87 * bandgap
kspacing = 2 * np.pi * 1.0265 / (rmin - 1.0183)
kspacing_swaps = {"kspacing": min(kspacing, 0.44), "ismear": 0, "sigma": 0.05}

relax_job_kwargs["calc_swaps"] = kspacing_swaps | relax_job_kwargs.get(
"calc_swaps", {}
)

# Run the relax
relax_results = mp_relax_job(
prerelax_results, copy_files=["WAVECAR"], **relax_job_kwargs
prerelax_results,
bandgap=prerelax_results["output"]["bandgap"],
copy_files=["CHGCAR", "WAVECAR"],
**relax_job_kwargs,
)
relax_results["prerelax"] = prerelax_results

return relax_results


def _get_bandgap_swaps(bandgap: float | None = None) -> dict:
"""
Get bandgap-related swaps.
Paramters
---------
bandgap
The bandgap, in units of eV.
Returns
-------
dict
Dictionary of swaps.
"""

if bandgap is None:
smearing_swaps = {"kspacing": 0.22, "ismear": 0, "sigma": 0.05}
elif bandgap <= 1e-4:
smearing_swaps = {"kspacing": 0.22, "ismear": 2, "sigma": 0.2}
else:
rmin = max(1.5, 25.22 - 2.87 * bandgap)
kspacing = 2 * np.pi * 1.0265 / (rmin - 1.0183)
smearing_swaps = {
"kspacing": min(kspacing, 0.44),
"ismear": 0,
"sigma": 0.05,
}

return smearing_swaps
91 changes: 86 additions & 5 deletions tests/recipes/vasp_recipes/test_vasp_recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,33 @@ def test_static_job(tmpdir):
assert "efermi" not in output["parameters"]


def test_static_job_force_copilot(tmpdir):
from quacc import SETTINGS
from quacc.recipes.vasp.core import static_job

tmpdir.chdir()

atoms = bulk("Cu") * (2, 2, 2)

SETTINGS.VASP_FORCE_COPILOT = True
output = static_job(
atoms,
calc_swaps={
"ivdw": 13,
"lasph": False,
"prec": None,
"lwave": None,
"efermi": None,
},
)
assert output["parameters"]["ivdw"] == 13
assert output["parameters"]["lasph"] is False
assert "prec" not in output["parameters"]
assert "lwave" not in output["parameters"]
assert output["parameters"]["efermi"] == "midgap"
SETTINGS.VASP_FORCE_COPILOT = False


def test_relax_job(tmpdir):
from quacc.recipes.vasp.core import relax_job

Expand Down Expand Up @@ -363,8 +390,8 @@ def test_qmof(tmpdir):
output = qmof_relax_job(atoms)


def test_mp(tmpdir):
from quacc.recipes.vasp.mp import mp_prerelax_job, mp_relax_flow, mp_relax_job
def test_mp_prerelax_job(tmpdir):
from quacc.recipes.vasp.mp import mp_prerelax_job

tmpdir.chdir()

Expand All @@ -376,6 +403,32 @@ def test_mp(tmpdir):
assert output["parameters"]["encut"] == 680
assert output["parameters"]["kspacing"] == 0.22
assert output["parameters"]["ismear"] == 0
assert output["parameters"]["sigma"] == 0.05

output = mp_prerelax_job(atoms, bandgap=0)
assert output["nsites"] == len(atoms)
assert output["parameters"]["xc"] == "pbesol"
assert output["parameters"]["ediffg"] == -0.05
assert output["parameters"]["encut"] == 680
assert output["parameters"]["kspacing"] == 0.22
assert output["parameters"]["ismear"] == 2
assert output["parameters"]["sigma"] == 0.2

output = mp_prerelax_job(atoms, bandgap=100)
assert output["nsites"] == len(atoms)
assert output["parameters"]["xc"] == "pbesol"
assert output["parameters"]["ediffg"] == -0.05
assert output["parameters"]["encut"] == 680
assert output["parameters"]["kspacing"] == 0.44
assert output["parameters"]["ismear"] == 0
assert output["parameters"]["sigma"] == 0.05


def test_mp_relax_job(tmpdir):
tmpdir.chdir()
from quacc.recipes.vasp.mp import mp_relax_job

atoms = bulk("Cu")

output = mp_relax_job(atoms)
assert output["nsites"] == len(atoms)
Expand All @@ -384,17 +437,45 @@ def test_mp(tmpdir):
assert output["parameters"]["encut"] == 680
assert output["parameters"]["kspacing"] == 0.22
assert output["parameters"]["ismear"] == 0
assert output["parameters"]["sigma"] == 0.05

output = mp_relax_job(atoms, bandgap=0)
assert output["nsites"] == len(atoms)
assert output["parameters"]["xc"] == "r2scan"
assert output["parameters"]["ediffg"] == -0.02
assert output["parameters"]["encut"] == 680
assert output["parameters"]["kspacing"] == 0.22
assert output["parameters"]["ismear"] == 2
assert output["parameters"]["sigma"] == 0.2

output = mp_relax_job(atoms, bandgap=100)
assert output["nsites"] == len(atoms)
assert output["parameters"]["xc"] == "r2scan"
assert output["parameters"]["ediffg"] == -0.02
assert output["parameters"]["encut"] == 680
assert output["parameters"]["kspacing"] == 0.44
assert output["parameters"]["ismear"] == 0
assert output["parameters"]["sigma"] == 0.05


def test_mp_relax_flow(tmpdir):
from quacc.recipes.vasp.mp import mp_relax_flow

tmpdir.chdir()

atoms = bulk("Cu")

output = mp_relax_flow(atoms)
assert output["nsites"] == len(atoms)
assert output["parameters"]["xc"] == "r2scan"
assert output["parameters"]["ediffg"] == -0.02
assert output["parameters"]["encut"] == 680
assert output["parameters"]["ismear"] == 2
assert output["parameters"]["sigma"] == 0.2
assert output["parameters"]["kspacing"] == 0.22
assert output["prerelax"]["parameters"]["xc"] == "pbesol"

atoms = bulk("Fe")
atoms = bulk("C")
output = mp_relax_flow(atoms)
assert output["nsites"] == len(atoms)
assert output["parameters"]["xc"] == "r2scan"
Expand Down Expand Up @@ -426,6 +507,6 @@ def test_vasp_version(tmpdir):

atoms = bulk("Cu") * (2, 2, 2)

output = static_job(atoms, calc_swaps={"efermi": None})
assert "efermi" not in output["parameters"]
output = static_job(atoms, preset=None)
assert output["parameters"].get("efermi") is None
SETTINGS.VASP_MIN_VERSION = DEFAULT_SETTINGS.VASP_MIN_VERSION

0 comments on commit 609705a

Please sign in to comment.