Skip to content

Commit a9a7323

Browse files
add test for running without potcar library
1 parent 680ed0a commit a9a7323

File tree

6 files changed

+92
-473
lines changed

6 files changed

+92
-473
lines changed

pymatgen/io/validation/check_kpoints_kspacing.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ def _get_valid_num_kpts(
6767
valid_kspacing = kspacing
6868
# number of kpoints along each of the three lattice vectors
6969
valid_num_kpts = np.prod(
70-
get_kpoint_divisions_from_kspacing(vasp_files.user_input.structure, valid_kspacing)
70+
get_kpoint_divisions_from_kspacing(vasp_files.user_input.structure, valid_kspacing), dtype=int
7171
)
7272
# If MP input set specifies a KPOINTS file
7373
elif vasp_files.valid_input_set.kpoints:
7474
valid_num_kpts = vasp_files.valid_input_set.kpoints.num_kpts or np.prod(
75-
vasp_files.valid_input_set.kpoints.kpts[0]
75+
vasp_files.valid_input_set.kpoints.kpts[0], dtype=int
7676
)
7777

7878
return int(np.floor(int(valid_num_kpts) * self.kpts_tolerance))
@@ -115,17 +115,17 @@ def _check_kpoint_density(self, vasp_files: VaspFiles, reasons: list[str], warni
115115
# Checks should work regardless of whether vasprun was supplied.
116116
valid_num_kpts = self._get_valid_num_kpts(vasp_files)
117117
if vasp_files.actual_kpoints:
118-
cur_num_kpts: int = max( # type: ignore[assignment]
119-
vasp_files.actual_kpoints.num_kpts, # type: ignore[union-attr]
120-
np.prod(vasp_files.actual_kpoints.kpts), # type: ignore[union-attr]
121-
len(vasp_files.actual_kpoints.kpts), # type: ignore[union-attr]
122-
)
118+
if vasp_files.actual_kpoints.num_kpts <= 0:
119+
cur_num_kpts = np.prod(vasp_files.actual_kpoints.kpts, dtype=int)
120+
else:
121+
cur_num_kpts = vasp_files.actual_kpoints.num_kpts
123122
else:
124123
cur_num_kpts = np.prod(
125124
get_kpoint_divisions_from_kspacing(
126125
vasp_files.user_input.structure,
127126
vasp_files.user_input.incar.get("KSPACING", self.vasp_defaults["KSPACING"].value),
128-
)
127+
),
128+
dtype=int,
129129
)
130130

131131
if cur_num_kpts < valid_num_kpts:

pymatgen/io/validation/common.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
from functools import cached_property
66
import hashlib
77
from importlib import import_module
8+
from monty.serialization import loadfn
89
import os
910
import numpy as np
1011
from pathlib import Path
1112
from pydantic import BaseModel, Field, model_validator, model_serializer, PrivateAttr
1213
from typing import TYPE_CHECKING, Any, Optional
1314

1415
from pymatgen.core import Structure
15-
from pymatgen.io.vasp import Incar, Kpoints, Poscar, Potcar, Outcar, Vasprun
16+
from pymatgen.io.vasp.inputs import POTCAR_STATS_PATH, Incar, Kpoints, Poscar, Potcar
17+
from pymatgen.io.vasp.outputs import Outcar, Vasprun
1618
from pymatgen.io.vasp.sets import VaspInputSet
1719

1820
from pymatgen.io.validation.vasp_defaults import VaspParam, VASP_DEFAULTS_DICT
@@ -170,18 +172,49 @@ def from_vasp_input_set(cls, vis: VaspInputSet) -> Self:
170172
-----------
171173
VaspInputSafe
172174
"""
173-
new_vis = cls(
174-
**{
175-
k: getattr(vis, k)
176-
for k in (
177-
"incar",
178-
"kpoints",
179-
"structure",
180-
)
181-
},
182-
potcar=PotcarSummaryStats.from_file(vis.potcar),
183-
potcar_functional=vis.potcar_functional,
175+
176+
cls_config: dict[str, Any] = {
177+
k: getattr(vis, k)
178+
for k in (
179+
"incar",
180+
"kpoints",
181+
"structure",
182+
)
183+
}
184+
try:
185+
# Cleaner solution (because these map one POTCAR symbol to one POTCAR)
186+
# Requires POTCAR library to be available
187+
potcar: list[PotcarSummaryStats] = PotcarSummaryStats.from_file(vis.potcar)
188+
potcar_functional = vis.potcar_functional
189+
190+
except FileNotFoundError:
191+
# Fall back to pregenerated POTCAR meta
192+
# Note that multiple POTCARs may use the same symbol / TITEL
193+
# within a given release of VASP.
194+
195+
potcar_stats = loadfn(POTCAR_STATS_PATH)
196+
potcar_functional = vis._config_dict["POTCAR_FUNCTIONAL"]
197+
potcar = []
198+
for ele in vis.structure.elements:
199+
if potcar_symb := vis._config_dict["POTCAR"].get(ele.name):
200+
for titel_no_spc, potcars in potcar_stats[potcar_functional].items():
201+
for entry in potcars:
202+
if entry["symbol"] == potcar_symb:
203+
titel_comp = titel_no_spc.split(potcar_symb)
204+
205+
potcar += [
206+
PotcarSummaryStats(
207+
titel=" ".join([titel_comp[0], potcar_symb, titel_comp[1]]),
208+
lexch=entry.get("LEXCH"),
209+
**entry,
210+
)
211+
]
212+
213+
cls_config.update(
214+
potcar=potcar,
215+
potcar_functional=potcar_functional,
184216
)
217+
new_vis = cls(**cls_config)
185218
new_vis._pmg_vis = vis
186219
return new_vis
187220

tests/conftest.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
_test_dir = Path(__file__).parent.joinpath("test_files").resolve()
1010

11-
FAKE_POTCAR_DIR = _test_dir / "vasp" / "fake_potcar"
12-
pytest.MonkeyPatch().setitem(PMG_SETTINGS, "PMG_VASP_PSP_DIR", str(FAKE_POTCAR_DIR))
11+
12+
def set_fake_potcar_dir() -> None:
13+
FAKE_POTCAR_DIR = _test_dir / "vasp" / "fake_potcar"
14+
pytest.MonkeyPatch().setitem(PMG_SETTINGS, "PMG_VASP_PSP_DIR", str(FAKE_POTCAR_DIR))
1315

1416

1517
@pytest.fixture(scope="session")

0 commit comments

Comments
 (0)