Skip to content

Commit

Permalink
non_scf_job for vasp calculations (#1840)
Browse files Browse the repository at this point in the history
## Summary of Changes

\>> It aims to implement the non-SCF job for VASP. Closes
#1774 <<

### Checklist

- [x] I have read the ["Guidelines"
section](https://quantum-accelerators.github.io/quacc/dev/contributing.html#guidelines)
of the contributing guide. Don't lie! 😉
- - [x] Use NumPy-style docstrings.
- - [x] Address any relevant issues raised by the GitHub Actions test
suite.
- - [x] All Python code should be formatted with
[ruff](https://github.com/astral-sh/ruff) (ruff format . --fix).
- [x] My PR is on a custom branch and is _not_ named `main`.
- [x] I have added relevant, comprehensive [unit
tests](https://quantum-accelerators.github.io/quacc/dev/contributing.html#unit-tests).

### Notes

- Your PR will likely not be merged without proper and thorough tests.
- If you are an external contributor, you will see a comment from
[@buildbot-princeton](https://github.com/buildbot-princeton). This is
solely for the maintainers.
- When your code is ready for review, ping one of the [active
maintainers](https://quantum-accelerators.github.io/quacc/about/contributors.html#active-maintainers).

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Andrew Rosen <[email protected]>
  • Loading branch information
3 people authored Mar 12, 2024
1 parent de661e8 commit 6e362bf
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/about/contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Additional contributions were made by the individuals listed [here](https://gith
- [@tomdemeyere](https://github.com/tomdemeyere): Custom Espresso calculator, Espresso recipes.
- [@ViktoriiaBaib](https://github.com/ViktoriiaBaib): Initial testing of quacc.
- [@zulissimeta](https://github.com/zulissimeta): Dask support
- [@yw-fang](https://github.com/yw-fang): VASP Non-SCF recipe

## Inspiration

Expand Down
1 change: 1 addition & 0 deletions docs/user/recipes/recipes_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ The list of available quacc recipes is shown below. The "Req'd Extras" column sp
| VASP Static | `#!Python @job` | [quacc.recipes.vasp.core.static_job][] | |
| VASP Relax | `#!Python @job` | [quacc.recipes.vasp.core.relax_job][] | |
| VASP Double Relax | `#!Python @flow` | [quacc.recipes.vasp.core.double_relax_flow][] | |
| VASP Non-SCF | `#!Python @job` | [quacc.recipes.vasp.core.non_scf_job][] | |
| VASP Slab Static | `#!Python @job` | [quacc.recipes.vasp.slabs.static_job][] | |
| VASP Slab Relax | `#!Python @job` | [quacc.recipes.vasp.slabs.relax_job][] | |
| VASP Bulk to Slabs | `#!Python @flow` | [quacc.recipes.vasp.slabs.bulk_to_slabs_flow][] | |
Expand Down
105 changes: 103 additions & 2 deletions src/quacc/recipes/vasp/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

from __future__ import annotations

from typing import TYPE_CHECKING
from pathlib import Path
from typing import TYPE_CHECKING, Literal

import numpy as np
from monty.os.path import zpath
from pymatgen.io.vasp import Vasprun

from quacc import flow, job
from quacc.recipes.vasp._base import base_fn
Expand Down Expand Up @@ -52,7 +57,7 @@ def static_job(
"lcharg": True,
"lreal": False,
"lwave": True,
"nedos": 5001,
"nedos": 3001,
"nsw": 0,
}
return base_fn(
Expand Down Expand Up @@ -173,3 +178,99 @@ def double_relax_flow(
)

return {"relax1": summary1, "relax2": summary2}


@job
def non_scf_job(
atoms: Atoms,
prev_dir: SourceDirectory,
preset: str | None = "BulkSet",
nbands_factor: float = 1.2,
kpts_mode: Literal["uniform", "line"] = "uniform",
uniform_kppvol: float = 100,
line_kpt_density: float = 20,
calculate_optics: bool = False,
**calc_kwargs,
) -> VaspSchema:
"""
Carry out a non-self-consistent field (NSCF) calculation.
Parameters
----------
atoms
Atoms object.
prev_dir
Directory of the prior job. Must contain a CHGCAR and vasprun.xml file.
preset
Preset to use from `quacc.calculators.vasp.presets`.
nbands_factor
A multiplicative factor used to adjust NBANDS when vasprun.xml(.gz) exists in
prev_dir
kpts_mode
Type of k-points mode. Options are "uniform" or "line".
uniform_kppvol
The k-point per volume density for the uniform k-point mode.
line_kpt_density
The k-point density for the line k-point mode.
calculate_optics
Whether to calculate optical properties.
**calc_kwargs
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][].
Returns
-------
VaspSchema
Dictionary of results from [quacc.schemas.vasp.vasp_summarize_run][].
See the type-hint for the data structure.
"""

calc_defaults = {
"icharg": 11,
"isym": 0,
"kspacing": None,
"lcharg": False,
"lorbit": 11,
"lwave": False,
"nsw": 0,
}

vasprun_path = zpath(Path(prev_dir, "vasprun.xml"))
vasprun = Vasprun(vasprun_path)

prior_nbands = vasprun.parameters["NBANDS"]
calc_defaults["nbands"] = int(np.ceil(prior_nbands * nbands_factor))

if kpts_mode == "uniform":
calc_defaults.update(
{
"ismear": -5,
"isym": 2,
"pmg_kpts": {"kppvol": uniform_kppvol},
"nedos": 6001,
}
)
elif kpts_mode == "line":
is_metal = vasprun.get_band_structure().is_metal()
calc_defaults.update(
{
"ismear": 1 if is_metal else 0,
"pmg_kpts": {"line_density": line_kpt_density},
"sigma": 0.2 if is_metal else 0.01,
}
)
else:
raise ValueError("Supported kpoint modes are 'uniform' and 'line' at present")

if calculate_optics:
calc_defaults.update({"cshift": 1e-5, "loptics": True, "lreal": False})

return base_fn(
atoms,
preset=preset,
calc_defaults=calc_defaults,
calc_swaps=calc_kwargs,
additional_fields={"name": "VASP Non-SCF"},
copy_files={prev_dir: ["CHGCAR*", "WAVECAR*"]},
)
111 changes: 109 additions & 2 deletions tests/core/recipes/vasp_recipes/mocked/test_vasp_recipes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
from pathlib import Path
from shutil import copy

import numpy as np
import pytest
from ase.build import bulk, molecule

from quacc import SETTINGS
from quacc.recipes.vasp.core import double_relax_flow, relax_job, static_job
from quacc.recipes.vasp.core import (
double_relax_flow,
non_scf_job,
relax_job,
static_job,
)
from quacc.recipes.vasp.mp import (
mp_gga_relax_flow,
mp_gga_relax_job,
Expand All @@ -13,12 +22,16 @@
mp_metagga_static_job,
)
from quacc.recipes.vasp.qmof import qmof_relax_job
from quacc.recipes.vasp.slabs import bulk_to_slabs_flow, slab_to_ads_flow
from quacc.recipes.vasp.slabs import bulk_to_slabs_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()

FILE_DIR = Path(__file__).parent
MOCKED_DIR = FILE_DIR / "mocked_vasp_run"


def test_static_job(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
Expand Down Expand Up @@ -148,6 +161,100 @@ def test_doublerelax_flow(tmp_path, monkeypatch):
assert double_relax_flow(atoms, relax1_kwargs={"kpts": [1, 1, 1]})


def test_non_scf_job1(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
copy(MOCKED_DIR / "vasprun.xml.gz", tmp_path / "vasprun.xml.gz")

atoms = bulk("Al")

output = non_scf_job(atoms, tmp_path)

assert "nsites" in output
assert "parameters" in output
assert "results" in output

assert output["parameters"]["lorbit"] == 11
assert output["parameters"]["lwave"] is False
assert output["parameters"]["lcharg"] is False
assert output["parameters"]["nsw"] == 0
assert output["parameters"]["isym"] == 2
assert output["parameters"]["icharg"] == 11
assert output["parameters"].get("kspacing") is None
assert output["parameters"]["nedos"] == 6001
assert output["parameters"]["kpts"] == [11, 11, 11]
assert output["parameters"]["ismear"] == -5
assert output["parameters"]["nbands"] == 99


def test_non_scf_job2(tmp_path, monkeypatch, caplog):
monkeypatch.chdir(tmp_path)
copy(MOCKED_DIR / "vasprun.xml.gz", tmp_path / "vasprun.xml.gz")

atoms = bulk("Al")

output = non_scf_job(
atoms, tmp_path, preset="BulkSet", nbands_factor=1, calculate_optics=True
)

assert "nsites" in output
assert "parameters" in output
assert "results" in output

assert output["parameters"]["loptics"] is True
assert output["parameters"]["lreal"] is False
assert output["parameters"]["cshift"] == 1e-5
assert output["parameters"]["nbands"] == 82
assert output["parameters"]["ismear"] == -5
assert output["parameters"]["lorbit"] == 11
assert output["parameters"]["lwave"] is False
assert output["parameters"]["lcharg"] is False
assert output["parameters"]["nsw"] == 0
assert output["parameters"]["isym"] == 2
assert output["parameters"]["icharg"] == 11
assert output["parameters"].get("kspacing") is None


@pytest.mark.parametrize("_is_metal", [True, False])
def test_non_scf_job3(tmp_path, monkeypatch, _is_metal):
monkeypatch.chdir(tmp_path)

class DummyBandStructure:
def __init__(self):
pass

@staticmethod
def is_metal():
return _is_metal

monkeypatch.setattr(
"pymatgen.io.vasp.Vasprun.get_band_structure", DummyBandStructure
)
copy(MOCKED_DIR / "vasprun.xml.gz", tmp_path / "vasprun.xml.gz")

atoms = bulk("Al")

output = non_scf_job(atoms, tmp_path, preset="BulkSet", kpts_mode="line")
assert np.shape(output["parameters"]["kpts"]) == (250, 3)
if _is_metal:
assert output["parameters"]["sigma"] == 0.2
assert output["parameters"]["ismear"] == 1
else:
assert output["parameters"]["sigma"] == 0.01
assert output["parameters"]["ismear"] == 0


def test_non_scf_job4(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)

copy(MOCKED_DIR / "vasprun.xml.gz", tmp_path / "vasprun.xml.gz")
atoms = bulk("Al")

with pytest.raises(
ValueError, match="Supported kpoint modes are 'uniform' and 'line' at present"
):
non_scf_job(atoms, tmp_path, kpts_mode="dummy")


def test_slab_static_job(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)

Expand Down

0 comments on commit 6e362bf

Please sign in to comment.