Skip to content

Commit

Permalink
Define PBE64Base.yaml for new VASP PBE_64 POTCARs (#3470)
Browse files Browse the repository at this point in the history
* add pymatgen/io/vasp/PBE64Base.yaml

* update MatPESStaticSet PARENT to PBE64Base

* update MatPES known_hash and add PBE64Base hash in test_sets.py

* fix TestMatPESStaticSet to expect PBE_64 as default POTCARs

* use monty zpath in generate_fake_potcar_libraries

* fix TestWavecar.test_standard ValueError

Invalid rtag=-9223372036854775808, must be one of {45200, 45210, 53300, 53310}

/home/runner/work/pymatgen/pymatgen/pymatgen/io/vasp/outputs.py:4252
  • Loading branch information
janosh committed Nov 15, 2023
1 parent 3ebcbad commit f7c92fa
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 24 deletions.
9 changes: 4 additions & 5 deletions dev_scripts/potcar_scrambler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import warnings

import numpy as np
from monty.os.path import zpath
from monty.serialization import zopen

from pymatgen.core import SETTINGS
Expand Down Expand Up @@ -51,7 +52,7 @@ def _rand_float_from_str_with_prec(self, input_str: str, bloat: float = 1.5):
def _read_fortran_str_and_scramble(self, input_str: str, bloat: float = 1.5):
input_str = input_str.strip()

if input_str.lower() in ["t", "f"] or input_str.lower() in ["true", "false"]:
if input_str.lower() in ("t", "f", "true", "false"):
return bool(np.random.randint(2))

if input_str.upper() == input_str.lower() and input_str[0].isnumeric():
Expand Down Expand Up @@ -128,10 +129,8 @@ def generate_fake_potcar_libraries():
for psp_name in psp_variants:
rebase_dir = f"{output_dir}/{func_dir}/{psp_name}/"
paths_to_try = [
f"{func_dir}/POTCAR.{psp_name}",
f"{func_dir}/POTCAR.{psp_name}.gz",
f"{func_dir}/{psp_name}/POTCAR",
f"{func_dir}/{psp_name}/POTCAR.gz",
zpath(f"{func_dir}/POTCAR.{psp_name}"),
zpath(f"{func_dir}/{psp_name}/POTCAR"),
]
if not any(map(os.path.isfile, paths_to_try)):
warnings.warn(f"Could not find {psp_name} in {paths_to_try}")
Expand Down
3 changes: 1 addition & 2 deletions pymatgen/apps/borg/hive.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ class SimpleVaspToComputedEntryDrone(VaspToComputedEntryDrone):
def __init__(self, inc_structure=False):
"""
Args:
inc_structure (bool): Set to True if you want
ComputedStructureEntries to be returned instead of
inc_structure (bool): Set to True if you want ComputedStructureEntries to be returned instead of
ComputedEntries. Structure will be parsed from the CONTCAR.
"""
self._inc_structure = inc_structure
Expand Down
2 changes: 1 addition & 1 deletion pymatgen/io/vasp/MatPESStaticSet.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 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
PARENT: PBE64Base
INCAR:
ALGO: Normal # Normal for PBE, ALL for R2SCAN, included to have some reasonable default
EDIFF: 1.e-05
Expand Down
101 changes: 101 additions & 0 deletions pymatgen/io/vasp/PBE64Base.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# POTCARs for PBE_64

This comment has been minimized.

Copy link
@Andrew-S-Rosen

Andrew-S-Rosen Nov 29, 2023

Member

@janosh, @esoteric-ephemera: Out of curiosity, are there any planned changes for the PBE .64 set, or is everything going to match the .54 set in terms of the "flavor" of POTCAR chosen? Curious to know what your unofficial recommendations are.

PARENT: VASPIncarBase
POTCAR_FUNCTIONAL: PBE_64
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
Yb: Yb_3
Zn: Zn
Zr: Zr_sv
2 changes: 1 addition & 1 deletion pymatgen/io/vasp/outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ def hubbards(self) -> dict[str, float]:
if len(js) != len(us):
js = [0] * len(us)
if len(us) == len(symbols):
return {symbols[i]: us[i] - js[i] for i in range(len(symbols))}
return {symbols[idx]: us[idx] - js[idx] for idx in range(len(symbols))}
if sum(us) == 0 and sum(js) == 0:
return {}
raise VaspParseError("Length of U value parameters and atomic symbols are mismatched")
Expand Down
9 changes: 6 additions & 3 deletions pymatgen/io/vasp/sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1270,9 +1270,12 @@ def __init__(
self._config_dict["INCAR"].pop("GGA", None)
if xc_functional.upper().endswith("+U"):
self._config_dict["INCAR"]["LDAU"] = True
user_potcar_functional = kwargs.get("user_potcar_functional", "PBE_54")
if user_potcar_functional.upper() != "PBE_54":
warnings.warn(f"{user_potcar_functional=} is inconsistent with the recommended PBE_54.", UserWarning)
default_potcars = self.CONFIG["PARENT"].replace("PBE", "PBE_").replace("BASE", "") # PBE64BASE -> PBE_64
user_potcar_functional = kwargs.get("user_potcar_functional", default_potcars)
if user_potcar_functional.upper() != default_potcars:
warnings.warn(
f"{user_potcar_functional=} is inconsistent with the recommended {default_potcars}.", UserWarning
)

self.kwargs = kwargs
self.xc_functional = xc_functional
Expand Down
25 changes: 13 additions & 12 deletions tests/io/vasp/test_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def test_sets_changed(self):
hashes[name] = hashlib.sha1(text).hexdigest()

known_hashes = {
"MatPESStaticSet.yaml": "8789f974913c935f21ff2fbffc0502714ca39470",
"MatPESStaticSet.yaml": "8edecff2bbd1932c53159f56a8e6340e900aaa2f",
"MITRelaxSet.yaml": "1a0970f8cad9417ec810f7ab349dc854eaa67010",
"MPAbsorptionSet.yaml": "5931e1cb3cf8ba809b3d4f4a5960d728c682adf1",
"MPHSERelaxSet.yaml": "0d0d96a620461071cfd416ec9d5d6a8d2dfd0855",
Expand All @@ -120,12 +120,13 @@ def test_sets_changed(self):
"MVLGWSet.yaml": "104ae93c3b3be19a13b0ee46ebdd0f40ceb96597",
"MVLRelax52Set.yaml": "4cfc6b1bd0548e45da3bde4a9c65b3249da13ecd",
"PBE54Base.yaml": "ec317781a7f344beb54c17a228db790c0eb49282",
"PBE64Base.yaml": "a0d6cd02c6ff8e24b0005e30c56a33b155c2280b",
"VASPIncarBase.yaml": "19762515f8deefb970f2968fca48a0d67f7964d4",
"vdW_parameters.yaml": "04bb09bb563d159565bcceac6a11e8bdf0152b79",
}

for input_set in hashes:
assert hashes[input_set] == known_hashes[input_set], f"{input_set} got {hashes[input_set]}\n\n{msg}"
assert hashes[input_set] == known_hashes[input_set], f"{input_set=}\n{msg}"


class TestDictSet(PymatgenTest):
Expand Down Expand Up @@ -774,12 +775,12 @@ def test_default(self):
assert incar["PREC"] == "Accurate"
assert incar["SIGMA"] == 0.05
assert incar["LMAXMIX"] == 6
# test POTCAR files are default PBE_54 PSPs and functional
# test POTCAR files are default PBE_64 PSPs and functional
assert input_set.potcar_symbols == ["Fe_pv", "P", "O"]
assert input_set.potcar.functional == "PBE_54"
assert input_set.potcar.functional == "PBE_64"
assert input_set.kpoints is None

assert str(input_set.potcar[0]) == str(PotcarSingle.from_symbol_and_functional("Fe_pv", "PBE_54"))
assert str(input_set.potcar[0]) == str(PotcarSingle.from_symbol_and_functional("Fe_pv", "PBE_64"))

def test_with_prev_incar(self):
default_prev = MatPESStaticSet(structure=self.struct, prev_incar=self.prev_incar)
Expand Down Expand Up @@ -811,9 +812,9 @@ def test_with_prev_incar(self):
assert incar["NSW"] == 0
assert incar["PREC"] == "Accurate"
assert incar["SIGMA"] == 0.05
# test POTCAR files are default PBE_54 PSPs and functional
# test POTCAR files are default PBE_64 PSPs and functional
assert default_prev.potcar_symbols == ["Fe_pv", "P", "O"]
assert default_prev.potcar.functional == "PBE_54"
assert default_prev.potcar.functional == "PBE_64"
assert default_prev.kpoints is None

def test_r2scan(self):
Expand All @@ -823,9 +824,9 @@ def test_r2scan(self):
assert incar_scan.get("GGA") is None
assert incar_scan["ALGO"] == "All"
assert incar_scan.get("LDAU") is None
# test POTCAR files are default PBE_54 PSPs and functional
# test POTCAR files are default PBE_64 PSPs and functional
assert scan.potcar_symbols == ["Fe_pv", "P", "O"]
assert scan.potcar.functional == "PBE_54"
assert scan.potcar.functional == "PBE_64"
assert scan.kpoints is None

def test_default_u(self):
Expand All @@ -834,10 +835,10 @@ def test_default_u(self):
assert incar_u["LDAU"] is True
assert incar_u["GGA"] == "Pe"
assert incar_u["ALGO"] == "Normal"
# test POTCAR files are default PBE_54 PSPs and functional
# test POTCAR files are default PBE_64 PSPs and functional
assert incar_u["LDAUU"] == [5.3, 0, 0]
assert default_u.potcar_symbols == ["Fe_pv", "P", "O"]
assert default_u.potcar.functional == "PBE_54"
assert default_u.potcar.functional == "PBE_64"
assert default_u.kpoints is None

def test_functionals(self):
Expand All @@ -847,7 +848,7 @@ def test_functionals(self):
):
MatPESStaticSet(self.struct, xc_functional=xc_functional)

with pytest.warns(UserWarning, match="inconsistent with the recommended PBE_54"):
with pytest.warns(UserWarning, match="inconsistent with the recommended PBE_64"):
diff_potcar = MatPESStaticSet(self.struct, user_potcar_functional="PBE")
assert str(diff_potcar.potcar[0]) == str(PotcarSingle.from_symbol_and_functional("Fe_pv", "PBE"))

Expand Down

0 comments on commit f7c92fa

Please sign in to comment.