Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Molecular dynamics job #134

Merged
merged 45 commits into from Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
bbe9b26
Add MDSetGenerator based on pymatgen MPMDSet
mjwen May 5, 2022
a44480d
Add MDMaker job
mjwen May 5, 2022
4a677f5
Attempt to add test
mjwen May 5, 2022
ff79d52
Allow different ensembles for MDSetGenerator, default to nvt
mjwen May 6, 2022
b4352a4
Add checking user incar setting
mjwen May 6, 2022
b552ca3
Merge branch 'main' into md
mjwen May 6, 2022
37e469c
Set custodian handler for MD run
mjwen May 6, 2022
d5b7a1f
Correct custodian handler for MD run
mjwen May 6, 2022
6edfdaa
Store trajectory as in additional data store
mjwen May 10, 2022
47a2101
Add MD to CalcType
mjwen May 10, 2022
cf6ece7
Add MD to get calc type function
mjwen May 10, 2022
7b02f67
Fix OutputSummary that uses info from ionic steps
mjwen May 10, 2022
6883d97
Remove incomplete test
mjwen May 10, 2022
57e164e
Fix annotation
mjwen May 10, 2022
e9fa8ab
Merge branch 'main' into md
mjwen Jun 29, 2022
e87b1b5
Add flag to store ionic_steps as pymatgen Trajectory
mjwen Jun 30, 2022
62abb2b
Use Trajectory object
mjwen Jun 30, 2022
31ee4df
Fix Trajectory as ionic steps
mjwen Jul 1, 2022
1e5d5ef
Store Trajectory in vasp_objects dict and let ionic_steps if not stor…
mjwen Jul 1, 2022
53da989
Make traj optional
mjwen Jul 1, 2022
675034f
Remove ionic step convergence check for MD run
mjwen Jul 1, 2022
d32fe25
Let MDset to match MPMDset params
mjwen Jul 1, 2022
7538108
Fix example code in test
mjwen Jul 2, 2022
6467e6c
Fix mock_vasp_run to accept kwargs
mjwen Jul 2, 2022
ac2a0dc
Update generating test doc such that the created si structure matches…
mjwen Jul 2, 2022
5bd060c
Add test for MD maker
mjwen Jul 3, 2022
0e0308e
Update test generating doc
mjwen Jul 3, 2022
ff083e8
Linting
mjwen Jul 3, 2022
48686be
Update test for task
mjwen Jul 3, 2022
c42cf11
Add trajectory checking test for MD maker
mjwen Jul 3, 2022
137af78
Merge branch 'main' into md
mjwen Jul 4, 2022
b7f4e89
Remove force POTIM=0.5 for H containing structure
mjwen Jul 4, 2022
84fa505
Minor tweak docs
mjwen Jul 5, 2022
00d7dbd
Change store_ionic_steps to store_trajectory
mjwen Jul 8, 2022
6bc888d
Restore func name to from_vasp_calc_doc
mjwen Jul 8, 2022
b9709c0
Make trajectory arg optional
mjwen Jul 8, 2022
b2a6c5d
Remove redundant docstring
mjwen Jul 8, 2022
0288471
Remove EDIFF_PER_ATOM, which could lead to large EDIFF, especially fo…
mjwen Jul 8, 2022
8adf37c
Fix MDMaker to store trajectory by default
mjwen Jul 8, 2022
02accd2
Regenerate enums.py
mjwen Jul 8, 2022
07df203
Merge branch 'main' into md
mjwen Jul 8, 2022
bde7f1c
Set ENCUT=520 and remove params that's the default in vasp
mjwen Jul 14, 2022
b9b8754
Add more default params for npt and remove support of nph
mjwen Jul 14, 2022
37becfb
Check incar settings
mjwen Jul 14, 2022
5c3d39c
Remove setting LAVE and LPLANE
mjwen Jul 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/atomate2/vasp/jobs/core.py
Expand Up @@ -21,6 +21,7 @@
RelaxSetGenerator,
StaticSetGenerator,
TightRelaxSetGenerator,
MDSetGenerator,
)

logger = logging.getLogger(__name__)
Expand All @@ -36,6 +37,7 @@
"TightRelaxMaker",
"HSETightRelaxMaker",
"TransmuterMaker",
"MDMaker",
]


Expand Down Expand Up @@ -529,6 +531,40 @@ def make(
return super().make.original(self, structure, prev_vasp_dir)


@dataclass
class MDMaker(BaseVaspMaker):
"""
Maker to create VASP molecular dynamics jobs.

Parameters
----------
name : str
The job name.
input_set_generator : .VaspInputSetGenerator
A generator used to make the input set.
write_input_set_kwargs : dict
Keyword arguments that will get passed to :obj:`.write_vasp_input_set`.
copy_vasp_kwargs : dict
Keyword arguments that will get passed to :obj:`.copy_vasp_outputs`.
run_vasp_kwargs : dict
Keyword arguments that will get passed to :obj:`.run_vasp`.
task_document_kwargs : dict
Keyword arguments that will get passed to :obj:`.TaskDocument.from_directory`.
stop_children_kwargs : dict
Keyword arguments that will get passed to :obj:`.should_stop_children`.
write_additional_data : dict
Additional data to write to the current directory. Given as a dict of
{filename: data}. Note that if using FireWorks, dictionary keys cannot contain
the "." character which is typically used to denote file extensions. To avoid
this, use the ":" character, which will automatically be converted to ".". E.g.
``{"my_file:txt": "contents of the file"}``.
"""

# TODO expose basic setting of INCAR parameters to user
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't put these controls in the job maker, instead put them in the input set generator to be consistent with the other input sets.

Also, I'd advise against exposing the basic incar settings as those are easily overriden using user_incar_settings. Instead you could add a several "presets", specified by a string, e.g., "nvt", "npt", "long" or whatever you think is useful

name: str = "molecular dynamics"
input_set_generator: VaspInputSetGenerator = field(default_factory=MDSetGenerator)


def _get_transformations(
transformations: tuple[str, ...], params: tuple[dict, ...] | None
):
Expand Down
82 changes: 82 additions & 0 deletions src/atomate2/vasp/sets/core.py
Expand Up @@ -6,6 +6,7 @@

import numpy as np
from pymatgen.core import Structure
from pymatgen.core.periodic_table import Element
from pymatgen.io.vasp import Outcar, Vasprun

from atomate2.common.schemas.math import Vector3D
Expand All @@ -21,6 +22,7 @@
"HSEBSSetGenerator",
"HSETightRelaxSetGenerator",
"ElectronPhononSetGenerator",
"MDSetGenerator",
]


Expand Down Expand Up @@ -775,6 +777,86 @@ def get_kpoints_updates(
return {"reciprocal_density": self.reciprocal_density}


@dataclass
class MDSetGenerator(VaspInputSetGenerator):
"""Class to generate VASP molecular dynamics input sets."""

def get_incar_updates(
self,
structure: Structure,
prev_incar: dict = None,
bandgap: float = 0,
vasprun: Vasprun = None,
outcar: Outcar = None,
) -> dict:
"""
Get updates to the INCAR for a molecular dynamics job.

Parameters
----------
structure
A structure.
prev_incar
An incar from a previous calculation.
bandgap
The band gap.
vasprun
A vasprun from a previous calculation.
outcar
An outcar from a previous calculation.

Returns
-------
dict
A dictionary of updates to apply.
"""
# TODO is is copied and changed based on pymatgen.io.vasp.sets.MPMDSet,
# dobule check and discuss with others
updates = {
# expect to be changed by user
"NSW": 1000,
"ISIF": 0,
"MDALGO": 0,
"SMASS": 0,
"TEBEG": 300,
"TEEND": 300,
"POTIM": 2,
# exepct to be fixed
"PREC": "Normal",
"IBRION": 0,
"LREAL": "Auto",
"NELM": 500,
"NELMIN": 4,
"ISYM": 0,
"NBLOCK": 1,
"KBLOCK": 100,
"LSCALU": False,
"LCHARG": False,
"LPLANE": False,
"LWAVE": True,
"LDAU": False,
# "ISMEAR": 0,
# "EDIFF_PER_ATOM": 0.00001, # TODO deprecated?
# "MAXMIX": 20,
# "BMIX": 1,
# "NSIM": 4,
# "ADDGRID": True,
}

# use VASP default ENCUT
update["ENCUT"] = None

if defaults["ISPIN"] == 1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what defaults is here?

Instead of this, you might want to set auto_ispin: bool = True in this dataclass. See the docstring for that setting here:

And this is an example of where I've turned it on:

auto_ispin: bool = True

update["MAGMOM"] = None

# smaller steps for H containing structrue
if Element("H") in structure.species:
updates["POTIM"] = 0.5
# updates["NSW"] = defaults["NSW"] * 4 # TODO not a big deal

return updates


def _get_nedos(vasprun: Optional[Vasprun], dedos: float):
"""Automatic setting of nedos using the energy range and the energy step."""
if vasprun is None:
Expand Down
23 changes: 23 additions & 0 deletions tests/test_data/vasp/Si_md/inputs/INCAR
@@ -0,0 +1,23 @@
ALGO = Normal
EDIFF = 1e-07
EDIFFG = -0.001
ENAUG = 1360.0
IBRION = 0
ISIF = 2
ISMEAR = -5
ISPIN = 2
KSPACING = 0.2925287784072645
LAECHG = False
LASPH = True
LCHARG = True
LELF = True
LMIXTAU = True
LORBIT = 11
LREAL = False
LVTOT = True
LWAVE = False
MAGMOM = 2*-0.0
NELM = 200
NSW = 99
PREC = Normal
SIGMA = 0.05
4 changes: 4 additions & 0 deletions tests/test_data/vasp/Si_md/inputs/KPOINTS
@@ -0,0 +1,4 @@
pymatgen with grid density = 100 / number of atoms
0
Gamma
3 3 3
10 changes: 10 additions & 0 deletions tests/test_data/vasp/Si_md/inputs/POSCAR
@@ -0,0 +1,10 @@
Si2
1.0
0.000000 2.752777 2.752777
2.725110 0.000000 2.752777
2.725110 2.752777 0.000000
Si
2
direct
0.750000 0.750000 0.750000 Si
0.500000 0.500000 0.500000 Si
1 change: 1 addition & 0 deletions tests/test_data/vasp/Si_md/inputs/POTCAR.spec
@@ -0,0 +1 @@
Si
26 changes: 26 additions & 0 deletions tests/vasp/jobs/test_core.py
Expand Up @@ -193,3 +193,29 @@ def test_transmuter(mock_vasp, clean_dir, si_structure):
np.testing.assert_allclose(
output1.structure.lattice.abc, [3.866974, 3.866975, 7.733949]
)


def test_md(mock_vasp, clean_dir, si_structure):
from jobflow import run_locally

from atomate2.vasp.jobs.core import MDMaker
from atomate2.vasp.schemas.task import TaskDocument

# mapping from job name to directory containing test files
ref_paths = {"molecular dynamics": "Si_md"}

# settings passed to fake_run_vasp; adjust these to check for certain INCAR settings
fake_run_vasp_kwargs = {"transmuter": {"incar_settings": ["ISMEAR", "NSW"]}}

# automatically use fake VASP and write POTCAR.spec during the test
mock_vasp(ref_paths, fake_run_vasp_kwargs)

# generate transmuter job
job = MDMaker(
transformations=["SupercellTransformation"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you don't need these options?

transformation_params=[{"scaling_matrix": ((1, 0, 0), (0, 1, 0), (0, 0, 2))}],
).make(si_structure)
job.maker.input_set_generator.user_incar_settings["KSPACING"] = 0.5

# run the job and ensure that it finished running successfully
responses = run_locally(job, create_folders=True, ensure_success=True)