diff --git a/src/quacc/calculators/presets/vasp/BulkSet.yaml b/src/quacc/calculators/presets/vasp/BulkSet.yaml index 3ded35151d..cb45d5e38c 100644 --- a/src/quacc/calculators/presets/vasp/BulkSet.yaml +++ b/src/quacc/calculators/presets/vasp/BulkSet.yaml @@ -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 diff --git a/src/quacc/calculators/presets/vasp/MPScanSet.yaml b/src/quacc/calculators/presets/vasp/MPScanSet.yaml index b9511d4875..b2aaee4ba5 100644 --- a/src/quacc/calculators/presets/vasp/MPScanSet.yaml +++ b/src/quacc/calculators/presets/vasp/MPScanSet.yaml @@ -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 diff --git a/src/quacc/calculators/presets/vasp/magmoms_MP.yaml b/src/quacc/calculators/presets/vasp/magmoms_MP.yaml index 2f7c6b51ec..ab15bd5dc7 100644 --- a/src/quacc/calculators/presets/vasp/magmoms_MP.yaml +++ b/src/quacc/calculators/presets/vasp/magmoms_MP.yaml @@ -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: diff --git a/src/quacc/calculators/presets/vasp/setups_pbe54_MP.yaml b/src/quacc/calculators/presets/vasp/setups_pbe54_MP.yaml index ffcf28c687..7d1b0ecca2 100644 --- a/src/quacc/calculators/presets/vasp/setups_pbe54_MP.yaml +++ b/src/quacc/calculators/presets/vasp/setups_pbe54_MP.yaml @@ -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: diff --git a/src/quacc/recipes/vasp/mp.py b/src/quacc/recipes/vasp/mp.py index 4cb8898565..4ed4394ec0 100644 --- a/src/quacc/recipes/vasp/mp.py +++ b/src/quacc/recipes/vasp/mp.py @@ -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: @@ -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 @@ -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. @@ -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, @@ -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: @@ -96,7 +106,7 @@ def mp_relax_job( Calculator Defaults: ```python - {} + {"lcharg": True, "lwave": True} | _get_bandgap_swaps(bandgap) ``` Parameters @@ -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. @@ -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, @@ -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 diff --git a/tests/recipes/vasp_recipes/test_vasp_recipes.py b/tests/recipes/vasp_recipes/test_vasp_recipes.py index 2b44bac0eb..86cd502957 100644 --- a/tests/recipes/vasp_recipes/test_vasp_recipes.py +++ b/tests/recipes/vasp_recipes/test_vasp_recipes.py @@ -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 @@ -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() @@ -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) @@ -384,6 +437,33 @@ 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) @@ -391,10 +471,11 @@ def test_mp(tmpdir): 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" @@ -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