Skip to content

Commit

Permalink
Transition to pymatgen VASP input sets (#854)
Browse files Browse the repository at this point in the history
* complete refactor to PMG input sets for vasp

* bug fixes for input set change

* linting

* move type import to type_checking block

* remove duplicated MP yaml files

* drop dict.get(key, None) -> dict.get(key)

* change inheritance slightly, install pmg from pr

* linting

* revert vis["INCAR"] --> vis.incar

* fix lobster interface

* remove lobster test file

* revert pymatgen testing install now that separate pr is merged

* try to force pip install of pymatgen in testing

* force pmg to install from git

* improve check_poscar method to account for reordering of sites in POSCAR

* linting

* remove POTCARs and replace with spec where appropriate; remove unused vaspout.h5 files which contain full POTCARs

* restore missing test file, but only header of POTCAR

* remove POTCAR.orig.spec files

* gzip test input files

* linting

* slightly refactor MP sets

* precommit

* slight matpes modification

* precommit

* revert gh workflow dependency install

* update changelog

* fix pymatgen pip version install for strict

* bump pymatgen to v2024.6.4

* refactor MP and MatPES VASP input sets to inherit directly from pymatgen equivalents

* linting

* further cleanup matpes r2scan set

* change ase to use most recent pypi release

* add missing pip install line

* revert lobster vis potcar changes

* remove version conflict

* remove version conflict

* remove version conflict

* replace lobster sets with pymatgen equivalents

* precommit

* add ispin to lobster tightstatitsetgenerator

* remove BaseVasp.yaml to rely on inheritance from MP input sets

* precommit

* remove temp test file

* move matpes jobs/flow to pymatgen sets, mark matpes sets for deprecation

* lint

* move mp sets fully to pmg, add deprecation warnings to existing atomate2 mp sets

* remove mp set dependence from tests

* precommit

* add bandgap_tol options to vasp.test_sets

* remove todo from tests.vasp.flows.test_mp

* add pytest.warns check for deprecated mp sets

* revert docstr changes

* move deprecation warnings from __post_init__ to class

warning before:
<string>:31: FutureWarning: __post_init__ is deprecated, and will be removed on 2025-01-01
Use MPRelaxSet in pymatgen.io.vasp.sets instead.

warning after:
<string>:31: FutureWarning: MPGGARelaxSetGenerator is deprecated, and will be removed on 2025-01-01
Use MPRelaxSet in pymatgen.io.vasp.sets instead.

* pin monty==2024.7.30 in deps and strict

* add kludge for monty zpath

* precommit

* extend monty fix to vasp tests

* precommit

---------

Co-authored-by: Janosh Riebesell <[email protected]>
  • Loading branch information
esoteric-ephemera and janosh authored Jul 30, 2024
1 parent 270408f commit fad9396
Show file tree
Hide file tree
Showing 1,304 changed files with 643 additions and 10,737 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ jobs:
python -m pip install --upgrade pip
mkdir -p ~/.abinit/pseudos
cp -r tests/test_data/abinit/pseudos/ONCVPSP-PBE-SR-PDv0.4 ~/.abinit/pseudos
# ase needed to get FrechetCellFilter used by ML force fields
pip install git+https://gitlab.com/ase/ase
pip install .[strict,tests,abinit]
pip install torch-runstats
pip install --no-deps nequip==0.5.6
Expand Down Expand Up @@ -100,8 +98,6 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# ase needed to get FrechetCellFilter used by ML force fields
pip install git+https://gitlab.com/ase/ase
pip install .[strict,docs]
- name: Build
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Change log

## v0.0.15

## New Features 🎉
* Transition VASP calculations to use input sets defined in pymatgen by @esoteric-ephemera in https://github.com/materialsproject/atomate2/pull/854

### Bug Fixes 🐛
* Increase k-point density for MP GGA static calculations to close issue https://github.com/materialsproject/atomate2/issues/844 by @esoteric-ephemera in https://github.com/materialsproject/atomate2/pull/854
* Adds missing MAGMOMs for MatPES jobs by @esoteric-ephemera in https://github.com/materialsproject/atomate2/pull/854

## v0.0.14

### New Features 🎉
Expand Down
12 changes: 5 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ dependencies = [
"custodian>=2024.4.18",
"emmet-core==0.82.2",
"jobflow>=0.1.11",
"monty>=2024.2.2",
"monty>=2024.7.30",
"numpy",
"pydantic-settings>=2.0.3",
"pydantic>=2.0.1",
"pymatgen>=2024.4.13",
"pymatgen>=2024.6.4",
]

[project.optional-dependencies]
Expand All @@ -50,7 +50,7 @@ defects = [
"python-ulid",
]
forcefields = [
"ase>=3.22.1",
"ase>=3.23.0",
"calorine<=2.2.1",
"chgnet>=0.2.2",
"mace-torch>=0.3.3",
Expand Down Expand Up @@ -81,9 +81,7 @@ tests = [
]
strict = [
"PyYAML==6.0.1",
# must use >= for ase to not uninstall main branch install in CI
# last known working commit: https://gitlab.com/ase/ase@2bab58f4e
"ase>=3.22.1",
"ase==3.23.0",
"calorine==2.2.1",
"cclib==1.8.1",
"chgnet==0.3.8",
Expand All @@ -96,7 +94,7 @@ strict = [
"lobsterpy==0.4.5",
"mace-torch>=0.3.3",
"matgl==1.1.2",
"monty==2024.5.24",
"monty==2024.7.30",
"mp-api==0.41.2",
"numpy",
"phonopy==2.26.6",
Expand Down
7 changes: 3 additions & 4 deletions src/atomate2/abinit/sets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,10 @@ def get_input_set(
structure : Structure
Pymatgen Structure object.
restart_from : str or Path or list or tuple
Directory (as a str or Path) or list/tuple of 1 directory (as a str
or Path) to restart from.
Directory or list/tuple of 1 directory to restart from.
prev_outputs : str or Path or list or tuple
Directory (as a str or Path) or list/tuple of directories (as a str
or Path) needed as dependencies for the AbinitInputSet generated.
Directory or list/tuple of directories needed as dependencies for the
AbinitInputSet generated.
"""
# Get the pseudos as a PseudoTable
pseudos = as_pseudo_table(self.pseudos) if self.pseudos else None
Expand Down
2 changes: 1 addition & 1 deletion src/atomate2/abinit/utils/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def get_total_run_time(self) -> Any:
"""Get the total run time based summing the abinit stop event run times."""
total_run_time = 0
for te in self.get_events_by_types(JobEvent.ABINIT_STOP):
run_time = te.details.get("run_time", None)
run_time = te.details.get("run_time")
if run_time:
total_run_time += run_time

Expand Down
16 changes: 8 additions & 8 deletions src/atomate2/common/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ def delete_files(
The hostname used to specify a remote filesystem. Can be given as either
"username@host" or just "host" in which case the username will be
inferred from the current user. If ``None``, the local filesystem will be used.
include_files : None or list of (str or Path)
include_files : None or list of (str or .Path)
Filenames to include as a list of str or Path objects given relative to
directory. Glob file paths are supported, e.g. "\*.dat". If ``None``, all files
in the directory will be deleted.
exclude_files : None or list of (str or Path)
exclude_files : None or list of (str or .Path)
Filenames to exclude. Supports glob file matching, e.g., "\*.dat".
allow_missing : bool
Whether to error if a file in ``include_files`` is not present in the directory.
Expand Down Expand Up @@ -188,11 +188,11 @@ def gzip_files(
The hostname used to specify a remote filesystem. Can be given as either
"username@host" or just "host" in which case the username will be
inferred from the current user. If ``None``, the local filesystem will be used.
include_files : None or list of (str or Path)
include_files : None or list of (str or .Path)
Filenames to include as a list of str or Path objects given relative to
directory. Glob file paths are supported, e.g. "\*.dat". If ``None``, all files
in the directory will be gzipped.
exclude_files : None or list of (str or Path)
exclude_files : None or list of (str or .Path)
Filenames to exclude. Supports glob file matching, e.g., "\*.dat".
allow_missing : bool
Whether to error if a file in ``include_files`` is not present in the directory.
Expand Down Expand Up @@ -241,11 +241,11 @@ def gunzip_files(
The hostname used to specify a remote filesystem. Can be given as either
"username@host" or just "host" in which case the username will be
inferred from the current user. If ``None``, the local filesystem will be used.
include_files : None or list of (str or Path)
include_files : None or list of (str or .Path)
Filenames to include as a list of str or Path objects given relative to
directory. Glob file paths are supported, e.g. "\*.dat". If ``None``, all
gzipped files in the directory will be gunzipped.
exclude_files : None or list of (str or Path)
exclude_files : None or list of (str or .Path)
Filenames to exclude. Supports glob file matching, e.g., "\*.dat".
allow_missing : bool
Whether to error if a file in ``include_files`` is not present in the directory.
Expand Down Expand Up @@ -287,11 +287,11 @@ def find_and_filter_files(
A file client.
directory : str or Path
A directory in which to find files.
include_files : None or list of (str or Path)
include_files : None or list of (str or .Path)
Filenames to include as a list of str or Path objects given relative to
directory. Glob file paths are supported, e.g. "\*.dat". If ``None``, all files
in the source directory will be returned.
exclude_files : None or list of (str or Path)
exclude_files : None or list of (str or .Path)
Filenames to exclude. Supports glob file matching, e.g., "\*.dat".
host : str or None
A hostname used to specify a remote filesystem. Can be given as either
Expand Down
2 changes: 1 addition & 1 deletion src/atomate2/common/jobs/defect.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ def get_defect_entry(charge_state_summary: dict, bulk_summary: dict) -> list[dic
"bulk_dir_name": bulk_dir_name,
"bulk_locpot": bulk_locpot,
"bulk_uuid": bulk_summary.get("uuid"),
"defect_uuid": qq_summary.get("uuid", None),
"defect_uuid": qq_summary.get("uuid"),
}
)
return defect_ent_res
2 changes: 1 addition & 1 deletion src/atomate2/cp2k/jobs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class BaseCp2kMaker(Maker):
----------
name : str
The job name.
input_set_generator : .VaspInputGenerator
input_set_generator : .Cp2kInputGenerator
A generator used to make the input set.
write_input_set_kwargs : dict
Keyword arguments that will get passed to :obj:`.write_cp2k_input_set`.
Expand Down
9 changes: 8 additions & 1 deletion src/atomate2/lobster/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
from emmet.core.structure import StructureMetadata
from monty.dev import requires
from monty.json import MontyDecoder, jsanitize
from monty.os.path import zpath

# TODO: remove this kludge when monty is fixed
from monty.os.path import zpath as monty_zpath
from pydantic import BaseModel, Field
from pymatgen.core import Structure
from pymatgen.electronic_structure.cohp import Cohp, CompleteCohp
Expand Down Expand Up @@ -45,6 +47,11 @@
logger = logging.getLogger(__name__)


def zpath(pathname: Union[str, Path]) -> str:
"""Kludge to fix monty zpath bug."""
return monty_zpath(str(pathname))


class LobsteroutModel(BaseModel):
"""Definition of computational settings from the LOBSTER computation."""

Expand Down
2 changes: 1 addition & 1 deletion src/atomate2/vasp/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,4 @@ def write_vasp_input_set(
Path(filename).unlink()

logger.info("Writing VASP input set.")
vis.write_input(directory, potcar_spec=potcar_spec, **kwargs)
vis.write_input(directory, **kwargs)
4 changes: 2 additions & 2 deletions src/atomate2/vasp/flows/defect.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ def check_defect_relax_maker(relax_maker: RelaxMaker) -> RelaxMaker:
input_gen = relax_maker.input_set_generator
if input_gen.use_structure_charge is False:
raise ValueError("use_structure_charge should be set to True")
isif_ = input_gen.get_incar_updates(None).get("ISIF", None)
isif = input_gen.user_incar_settings.get("ISIF", isif_)
default_isif = input_gen.incar_updates.get("ISIF")
isif = input_gen.user_incar_settings.get("ISIF", default_isif)
if isif != 2:
raise ValueError("ISIF should be set to 2")
return relax_maker
Expand Down
6 changes: 3 additions & 3 deletions src/atomate2/vasp/flows/matpes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
from typing import TYPE_CHECKING

from jobflow import Flow, Maker
from pymatgen.io.vasp.sets import MatPESStaticSet

from atomate2.vasp.jobs.matpes import MatPesGGAStaticMaker, MatPesMetaGGAStaticMaker
from atomate2.vasp.sets.matpes import MatPesGGAStaticSetGenerator

if TYPE_CHECKING:
from pathlib import Path
Expand Down Expand Up @@ -43,7 +43,7 @@ class MatPesStaticFlowMaker(Maker):
name: str = "MatPES static flow"
static1: Maker | None = field(
default_factory=lambda: MatPesGGAStaticMaker(
input_set_generator=MatPesGGAStaticSetGenerator(
input_set_generator=MatPESStaticSet(
# write WAVECAR so we can use as pre-conditioned starting point for
# static2/3
user_incar_settings={"LWAVE": True}
Expand All @@ -62,7 +62,7 @@ class MatPesStaticFlowMaker(Maker):
static3: Maker | None = field(
default_factory=lambda: MatPesGGAStaticMaker(
name="MatPES GGA+U static",
input_set_generator=MatPesGGAStaticSetGenerator(
input_set_generator=MatPESStaticSet(
user_incar_settings={"LDAU:": True}, # enable +U corrections
),
copy_vasp_kwargs={"additional_vasp_files": ("WAVECAR",)},
Expand Down
20 changes: 2 additions & 18 deletions src/atomate2/vasp/flows/mp.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from typing import TYPE_CHECKING

from jobflow import Flow, Maker
from pymatgen.io.vasp.sets import LobsterSet

from atomate2.lobster.jobs import LobsterMaker
from atomate2.vasp.flows.core import DoubleRelaxMaker
Expand All @@ -24,7 +25,6 @@
MPMetaGGAStaticMaker,
MPPreRelaxMaker,
)
from atomate2.vasp.sets.mp import MPGGAStaticSetGenerator

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -234,23 +234,7 @@ class MPVaspLobsterMaker(VaspLobsterMaker):
name: str = "lobster"
relax_maker: BaseVaspMaker | None = field(default_factory=MPGGADoubleRelaxMaker)
lobster_static_maker: BaseVaspMaker = field(
default_factory=lambda: MPGGAStaticMaker(
input_set_generator=MPGGAStaticSetGenerator(
user_potcar_functional="PBE_54",
user_potcar_settings={"W": "W_sv"},
user_kpoints_settings={"reciprocal_density": 310},
user_incar_settings={
"EDIFF": 1e-6,
"NSW": 0,
"LWAVE": True,
"ISYM": 0,
"IBRION": -1,
"ISMEAR": -5,
"LORBIT": 11,
"ALGO": "Normal",
},
)
)
default_factory=lambda: MPGGAStaticMaker(input_set_generator=LobsterSet())
)
lobster_maker: LobsterMaker | None = field(default_factory=LobsterMaker)
delete_wavecars: bool = True
Expand Down
29 changes: 7 additions & 22 deletions src/atomate2/vasp/jobs/lobster.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from atomate2.utils.path import strip_hostname
from atomate2.vasp.jobs.base import BaseVaspMaker
from atomate2.vasp.powerups import update_user_incar_settings
from atomate2.vasp.sets.core import StaticSetGenerator
from atomate2.vasp.sets.core import LobsterTightStaticSetGenerator

if TYPE_CHECKING:
from pathlib import Path
Expand Down Expand Up @@ -58,20 +58,7 @@ class LobsterStaticMaker(BaseVaspMaker):

name: str = "static_run"
input_set_generator: VaspInputGenerator = field(
default_factory=lambda: StaticSetGenerator(
auto_ispin=True,
user_kpoints_settings={"reciprocal_density": 400},
user_incar_settings={
"EDIFF": 1e-7,
"LAECHG": False,
"LREAL": False,
"LVTOT": False,
"ALGO": "Normal",
"LCHARG": False,
"LWAVE": True,
"ISYM": 0,
},
)
default_factory=LobsterTightStaticSetGenerator
)


Expand Down Expand Up @@ -103,14 +90,12 @@ def get_basis_infos(
"""
# this logic enables handling of a flow or a simple maker
try:
potcar_symbols = vasp_maker.static_maker.input_set_generator._get_potcar( # noqa: SLF001
structure=structure, potcar_spec=True
)

vis = vasp_maker.static_maker.input_set_generator
except AttributeError:
potcar_symbols = vasp_maker.input_set_generator._get_potcar( # noqa: SLF001
structure=structure, potcar_spec=True
)
vis = vasp_maker.input_set_generator

vis.structure = structure
potcar_symbols = vis.potcar_symbols

# get data from LobsterInput
list_basis_dict = Lobsterin.get_all_possible_basis_functions(
Expand Down
14 changes: 6 additions & 8 deletions src/atomate2/vasp/jobs/matpes.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from pymatgen.io.vasp.sets import MatPESStaticSet

from atomate2.vasp.jobs.base import BaseVaspMaker
from atomate2.vasp.sets.matpes import (
MatPesGGAStaticSetGenerator,
MatPesMetaGGAStaticSetGenerator,
)

if TYPE_CHECKING:
from atomate2.vasp.sets.base import VaspInputGenerator
Expand Down Expand Up @@ -49,9 +47,7 @@ class MatPesGGAStaticMaker(BaseVaspMaker):
"""

name: str = "MatPES GGA static"
input_set_generator: VaspInputGenerator = field(
default_factory=MatPesGGAStaticSetGenerator
)
input_set_generator: VaspInputGenerator = field(default_factory=MatPESStaticSet)


@dataclass
Expand Down Expand Up @@ -85,5 +81,7 @@ class MatPesMetaGGAStaticMaker(BaseVaspMaker):

name: str = "MatPES meta-GGA static"
input_set_generator: VaspInputGenerator = field(
default_factory=MatPesMetaGGAStaticSetGenerator
default_factory=lambda: MatPESStaticSet(
xc_functional="R2SCAN", user_incar_settings={"GGA": None}
)
)
Loading

0 comments on commit fad9396

Please sign in to comment.