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

Add VASP input set MatPESStaticSet #3254

Merged
merged 20 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions pymatgen/io/vasp/MatPESStaticSet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Default VASP settings for static calculations in the MatPES Project
# using the Regularized-Restored Strongly Constrained and Appropriately
# Normed functional (default PBE, PBE+U or R2SCAN or R2SCAN+U).
PARENT: PBE54Base
INCAR:
ALGO: Normal # Normal for PBE, ALL for R2SCAN, included to have some reasonable default
EDIFF: 1.e-05
ENAUG: 1360
ENCUT: 680
ISMEAR: 0 # change from 2 to 0, included to have some reasonable default
ISPIN: 2
KSPACING: 0.22 # included to have some reasonable default
LAECHG: True
LASPH: True
LCHARG: True
LELF: False # LELF = True restricts calculation to KPAR = 1
LMIXTAU: True
LORBIT: 11
LREAL: Auto
LVTOT: True
Copy link
Contributor

Choose a reason for hiding this comment

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

This line should be removed. The LOCPOT file is going to consume storage space.

LWAVE: False
GGA: PE # change R2SCAN to PBE as default
NELM: 200
SophiaRuan marked this conversation as resolved.
Show resolved Hide resolved
NSW: 0 # static calculation
PREC: Accurate
SIGMA: 0.05 # change from 0.02 to 0.05, included to have some reasonable default
103 changes: 103 additions & 0 deletions pymatgen/io/vasp/PBE54Base.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# POTCARs for PBE_54
PARENT: VASPIncarBase
POTCAR_FUNCTIONAL: PBE_54
POTCAR:
Ac: Ac
Ag: Ag
Al: Al
Am: Am
Ar: Ar
As: As
At: At
Au: Au
B: B
Ba: Ba_sv
Be: Be_sv
Bi: Bi
Br: Br
C: C
Ca: Ca_sv
Cd: Cd
Ce: Ce
Cf: Cf
Cl: Cl
Cm: Cm
Co: Co
Cr: Cr_pv
Cs: Cs_sv
Cu: Cu_pv
Dy: Dy_3
Er: Er_3
Eu: Eu
F: F
Fe: Fe_pv
Fr: Fr_sv
Ga: Ga_d
Gd: Gd
Ge: Ge_d
H: H
He: He
Hf: Hf_pv
Hg: Hg
Ho: Ho_3
I: I
In: In_d
Ir: Ir
K: K_sv
Kr: Kr
La: La
Li: Li_sv
Lu: Lu_3
Mg: Mg_pv
Mn: Mn_pv
Mo: Mo_pv
N: N
Na: Na_pv
Nb: Nb_pv
Nd: Nd_3
Ne: Ne
Ni: Ni_pv
Np: Np
O: O
Os: Os_pv
P: P
Pa: Pa
Pb: Pb_d
Pd: Pd
Pm: Pm_3
Po: Po_d
Pr: Pr_3
Pt: Pt
Pu: Pu
Ra: Ra_sv
Rb: Rb_sv
Re: Re_pv
Rh: Rh_pv
Rn: Rn
Ru: Ru_pv
S: S
Sb: Sb
Sc: Sc_sv
Se: Se
Si: Si
Sm: Sm_3
Sn: Sn_d
Sr: Sr_sv
Ta: Ta_pv
Tb: Tb_3
Tc: Tc_pv
Te: Te
Th: Th
Ti: Ti_pv
Tl: Tl_d
Tm: Tm_3
U: U
V: V_pv
W: W_sv
Xe: Xe
Y: Y_sv
# 2023-05-02: change Yb_2 to Yb_3 as Yb_2 gives incorrect thermodynamics for most systems with Yb3+
# https://github.com/materialsproject/pymatgen/issues/2968
Yb: Yb_3
Zn: Zn
Zr: Zr_sv
65 changes: 51 additions & 14 deletions pymatgen/io/vasp/sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1084,10 +1084,10 @@ def __init__(
self.small_gap_multiply = small_gap_multiply

@property
def incar(self):
def incar(self) -> Incar:
"""Incar"""
parent_incar = super().incar
incar = Incar(self.prev_incar) if self.prev_incar is not None else Incar(parent_incar)
incar = Incar(self.prev_incar or parent_incar)

incar.update(
{
Expand Down Expand Up @@ -1215,6 +1215,43 @@ def from_prev_calc(cls, prev_calc_dir, **kwargs):
return input_set.override_from_prev_calc(prev_calc_dir=prev_calc_dir)


class MatPESStaticSet(MPStaticSet):
"""Creates input files for a MatPES static calculation."""

CONFIG = _load_yaml_config("MatPESStaticSet")

def __init__(
self,
structure: str,
functional: Literal["R2SCAN", "R2SCAN+U", "PBE", "PBE+U"] = "PBE",
Copy link
Contributor

@JiQi535 JiQi535 Aug 26, 2023

Choose a reason for hiding this comment

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

@SophiaRuan Here, I think we should have PBE+U as default, inline with default of MPRelaxSet and MPStaticSet. Also, I don't think we should distinguish PBE and PBE+U as two functionals. Instead, +U can be disabled in the same way as in MPRelaxSet and MPStaticSet with user_incar_settings={"LDAU": False}.

@shyuep Please kindly comment if you agree.

**kwargs: Any,
) -> None:
"""
Args:
structure (Structure): Structure from previous run.
functional ('R2SCAN' | 'R2SCAN+U' | 'PBE' | 'PBE+U'): Which functional to use and whether to include
Hubbard U corrections. Defaults to 'PBE'.
**kwargs: Passed to MPStaticSet.
"""
super().__init__(structure, MatPESStaticSet.CONFIG, **kwargs)
if functional.startswith("R2SCAN"):
self.user_incar_settings.setdefault("METAGGA", "R2SCAN")
self.user_incar_settings.setdefault("ALGO", "ALL")
if functional.startswith("PBE"):
self.user_incar_settings.setdefault("GGA", "PE")
if functional.endswith("+U"):
self.user_incar_settings.setdefault("LDAU", True)

self.kwargs = kwargs
self.functional = functional

@property
def incar(self) -> Incar:
"""Incar"""
parent_incar = super().incar
return Incar(self.prev_incar or parent_incar)


class MPScanStaticSet(MPScanRelaxSet):
"""
Creates input files for a static calculation using the accurate and numerically
Expand Down Expand Up @@ -1245,10 +1282,10 @@ def __init__(self, structure: Structure, bandgap=0, prev_incar=None, lepsilon=Fa
self.lcalcpol = lcalcpol

@property
def incar(self):
def incar(self) -> Incar:
"""Incar"""
parent_incar = super().incar
incar = Incar(self.prev_incar) if self.prev_incar is not None else Incar(parent_incar)
incar = Incar(self.prev_incar or parent_incar)

incar.update({"LREAL": False, "NSW": 0, "LORBIT": 11, "LVHAR": True, "ISMEAR": -5})

Expand Down Expand Up @@ -1892,7 +1929,7 @@ def __init__(
super().__init__(structure, prev_incar=prev_incar, reciprocal_density=reciprocal_density, **kwargs)

@property
def incar(self):
def incar(self) -> Incar:
"""Incar"""
incar = super().incar

Expand Down Expand Up @@ -2037,18 +2074,18 @@ def __init__(
self.ncores = ncores

@property
def kpoints(self):
def kpoints(self) -> Kpoints:
"""
Generate gamma center k-points mesh grid for GW calc,
which is requested by GW calculation.
"""
return Kpoints.automatic_density_by_vol(self.structure, self.reciprocal_density, force_gamma=True)

@property
def incar(self):
def incar(self) -> Incar:
"""Incar"""
parent_incar = super().incar
incar = Incar(self.prev_incar) if self.prev_incar is not None else Incar(parent_incar)
incar = Incar(self.prev_incar or parent_incar)

if self.mode == "DIAG":
# Default parameters for diagonalization calculation.
Expand Down Expand Up @@ -2303,7 +2340,7 @@ def kpoints(self):
return kpt

@property
def incar(self):
def incar(self) -> Incar:
"""Incar"""
incar = super().incar

Expand Down Expand Up @@ -2531,7 +2568,7 @@ def __init__(self, structure: Structure, start_temp, end_temp, nsteps, time_step
self._config_dict["INCAR"].update(defaults)

@property
def kpoints(self):
def kpoints(self) -> Kpoints:
"""Kpoints"""
return Kpoints.gamma_automatic()

Expand Down Expand Up @@ -2613,7 +2650,7 @@ def __init__(self, structure: Structure, start_temp, end_temp, nsteps, spin_pola
self._config_dict["INCAR"].update(defaults)

@property
def kpoints(self):
def kpoints(self) -> Kpoints:
"""Kpoints"""
return Kpoints.gamma_automatic()

Expand Down Expand Up @@ -3106,15 +3143,15 @@ def __init__(
self.kwargs = kwargs

@property
def kpoints(self):
def kpoints(self) -> Kpoints:
"""
Generate gamma center k-points mesh grid for optical calculation. It is not mandatory for 'ALGO = Exact',
but is requested by 'ALGO = CHI' calculation.
"""
return Kpoints.automatic_density_by_vol(self.structure, self.reciprocal_density, force_gamma=True)

@property
def incar(self):
def incar(self) -> Incar:
"""Incar"""
parent_incar = super().incar
absorption_incar = {
Expand Down Expand Up @@ -3147,7 +3184,7 @@ def incar(self):
elif self.mode == "RPA":
# Default parameters for the response function calculation. NELM has to be set to 1.
# NOMEGA is set to 1000 in order to get smooth spectrum
incar = Incar(self.prev_incar) if self.prev_incar is not None else Incar(parent_incar)
incar = Incar(self.prev_incar or parent_incar)
incar.update({"ALGO": "CHI", "NELM": 1, "NOMEGA": 1000})

if self.nkred is not None:
Expand Down
67 changes: 67 additions & 0 deletions tests/io/vasp/test_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
BadInputSetWarning,
DictSet,
LobsterSet,
MatPESStaticSet,
MITMDSet,
MITNEBSet,
MITRelaxSet,
Expand All @@ -47,6 +48,7 @@
MVLScanRelaxSet,
MVLSlabSet,
VaspInputSet,
_load_yaml_config,
batch_write_input,
get_structure_from_prev_run,
get_valid_magmom_struct,
Expand Down Expand Up @@ -743,6 +745,71 @@ def test_grid_size_from_struct(self):
assert matched


class TestMatPESStaticSet(PymatgenTest):
def test_init(self):
prev_run = f"{TEST_FILES_DIR}/relaxation"

vis = MatPESStaticSet.from_prev_calc(prev_calc_dir=prev_run)
# Check that INCAR settings were load from yaml, check the default functional is PBE.
CONFIG = _load_yaml_config("MatPESStaticSet")
assert vis.incar == CONFIG["INCAR"]
assert vis.kpoints.style == Kpoints.supported_modes.Monkhorst

# Check as from dict.
vis = MatPESStaticSet.from_dict(vis.as_dict())
# Check that INCAR settings were load from yaml.
assert vis.incar == CONFIG["INCAR"]

prev_run_scan = f"{TEST_FILES_DIR}/scan_relaxation"

vis_scan = MatPESStaticSet.from_prev_calc(prev_calc_dir=prev_run_scan, functional="R2SCAN")
# Check that INCAR settings were load from yaml, check the functional "R2SCAN".
assert vis_scan.incar["METAGGA"] == "R2SCAN"
assert vis_scan.incar["ALGO"] == "ALL"

# Check as from dict.
vis_scan = MatPESStaticSet.from_dict(vis_scan.as_dict())
# Check that INCAR settings were load from yaml.
assert vis_scan.incar["METAGGA"] == "R2SCAN"
assert vis_scan.incar["ALGO"] == "ALL"

# test with changed user_incar_settings
non_prev_vis = MatPESStaticSet(vis.structure, user_incar_settings={"ENCUT": 800, "LORBIT": 12, "LWAVE": True})
# Check that the ENCUT and Kpoints style has NOT been inherited.
assert non_prev_vis.incar["ENCUT"] == 800
# Check that user incar settings are applied.
assert non_prev_vis.incar["LORBIT"] == 12
assert non_prev_vis.incar["LWAVE"]

non_prev_vis = MatPESStaticSet.from_dict(non_prev_vis.as_dict())
assert non_prev_vis.incar["ENCUT"] == 800
# Check that user incar settings are applied.
assert non_prev_vis.incar["LORBIT"] == 12
assert non_prev_vis.incar["LWAVE"]

# test R2SCAN with changed user_incar_settings
non_prev_vis_scan = MatPESStaticSet(
vis_scan.structure, functional="R2SCAN", user_incar_settings={"ENCUT": 800, "LORBIT": 12, "LWAVE": True}
)
# Check functional has been changed to R2SCAN
assert vis_scan.incar["METAGGA"] == "R2SCAN"
assert vis_scan.incar["ALGO"] == "ALL"
# Check that the ENCUT and Kpoints style has NOT been inherited.
assert non_prev_vis_scan.incar["ENCUT"] == 800
# Check that user incar settings are applied.
assert non_prev_vis_scan.incar["LORBIT"] == 12
assert non_prev_vis_scan.incar["LWAVE"]

non_prev_vis_scan = MatPESStaticSet.from_dict(non_prev_vis_scan.as_dict())
# Check functional has been changed to R2SCAN
assert vis_scan.incar["METAGGA"] == "R2SCAN"
assert vis_scan.incar["ALGO"] == "ALL"
assert non_prev_vis_scan.incar["ENCUT"] == 800
# Check that user incar settings are applied.
assert non_prev_vis_scan.incar["LORBIT"] == 12
assert non_prev_vis_scan.incar["LWAVE"]


class TestMPNonSCFSet(PymatgenTest):
def setUp(self):
self.set = MPNonSCFSet
Expand Down