Skip to content

Commit 64d5890

Browse files
authored
Set kpoints in from_str method as integer in auto Gamma and Monkhorst modes (#3994)
* kpoints as int in auto Gamma and Monkhorst * add deprecation warning and docstring tweak * add unit test * filter Kpoints warning * docstring tweaks * also test deprecation warning * merge tests into test_static_constructors * assert int type in automatic_density methods * clarify typing for Kpoint * relocate setter and getter to avoid mypy redefine errors * type annotate some class vars * remove boilerplate code * revert changes in io.vasp.inputs * revert change in POTCAR_spec * reapply deprecation warning * My bad, reapply float -> int change * use Tuple3Ints for more specific typing * use Tuple3Floats when type is known
1 parent 3fee7d5 commit 64d5890

File tree

4 files changed

+31
-10
lines changed

4 files changed

+31
-10
lines changed

src/pymatgen/io/vasp/inputs.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,8 @@ def automatic(cls, subdivisions: int) -> Self:
12451245
Returns:
12461246
Kpoints
12471247
"""
1248+
warnings.warn("Please use INCAR KSPACING tag.", DeprecationWarning, stacklevel=2)
1249+
12481250
return cls(
12491251
"Fully automatic kpoint scheme",
12501252
0,
@@ -1255,7 +1257,7 @@ def automatic(cls, subdivisions: int) -> Self:
12551257
)
12561258

12571259
@classmethod
1258-
def gamma_automatic(cls, kpts: Kpoint = (1, 1, 1), shift: Vector3D = (0, 0, 0)) -> Self:
1260+
def gamma_automatic(cls, kpts: Tuple3Ints = (1, 1, 1), shift: Vector3D = (0, 0, 0)) -> Self:
12591261
"""
12601262
Construct an automatic Gamma-centered Kpoint grid.
12611263
@@ -1270,7 +1272,7 @@ def gamma_automatic(cls, kpts: Kpoint = (1, 1, 1), shift: Vector3D = (0, 0, 0))
12701272
return cls("Automatic kpoint scheme", 0, cls.supported_modes.Gamma, kpts=[kpts], kpts_shift=shift)
12711273

12721274
@classmethod
1273-
def monkhorst_automatic(cls, kpts: Kpoint = (2, 2, 2), shift: Vector3D = (0, 0, 0)) -> Self:
1275+
def monkhorst_automatic(cls, kpts: Tuple3Ints = (2, 2, 2), shift: Vector3D = (0, 0, 0)) -> Self:
12741276
"""
12751277
Construct an automatic Monkhorst-Pack Kpoint grid.
12761278
@@ -1417,7 +1419,7 @@ def automatic_density_by_lengths(
14171419
lattice = structure.lattice
14181420

14191421
abc = lattice.abc
1420-
num_div: Tuple3Ints = tuple(np.ceil(ld / abc[idx]) for idx, ld in enumerate(length_densities))
1422+
num_div: Tuple3Ints = tuple(math.ceil(ld / abc[idx]) for idx, ld in enumerate(length_densities))
14211423

14221424
is_hexagonal: bool = lattice.is_hexagonal()
14231425
is_face_centered: bool = structure.get_space_group_info()[0][0] == "F"
@@ -1516,10 +1518,10 @@ def from_str(cls, string: str) -> Self:
15161518

15171519
# Automatic Gamma-centered or Monkhorst-Pack KPOINTS, with optional shift
15181520
if style in {"g", "m"}:
1519-
_kpt: list[float] = [float(i) for i in lines[3].split()]
1521+
_kpt: list[int] = [int(i) for i in lines[3].split()]
15201522
if len(_kpt) != 3:
15211523
raise ValueError("Invalid Kpoint length.")
1522-
kpt: Tuple3Floats = cast(Tuple3Floats, tuple(_kpt))
1524+
kpt: Tuple3Ints = cast(Tuple3Ints, tuple(_kpt))
15231525

15241526
kpts_shift: Vector3D = (0, 0, 0)
15251527
if len(lines) > 4 and coord_pattern.match(lines[4]):
@@ -1559,7 +1561,7 @@ def from_str(cls, string: str) -> Self:
15591561
"Cartesian" if lines[3].lower()[0] in "ck" else "Reciprocal"
15601562
)
15611563
_style = cls.supported_modes.Line_mode
1562-
_kpts: list[Kpoint] = []
1564+
_kpts: list[Tuple3Floats] = []
15631565
labels = []
15641566
patt = re.compile(r"([e0-9.\-]+)\s+([e0-9.\-]+)\s+([e0-9.\-]+)\s*!*\s*(.*)")
15651567
for idx in range(4, len(lines)):
@@ -1588,7 +1590,7 @@ def from_str(cls, string: str) -> Self:
15881590

15891591
for idx in range(3, 3 + num_kpts):
15901592
tokens = lines[idx].split()
1591-
kpts.append(cast(Kpoint, tuple(float(i) for i in tokens[:3])))
1593+
kpts.append(cast(Tuple3Floats, tuple(float(i) for i in tokens[:3])))
15921594
kpts_weights.append(float(tokens[3]))
15931595
if len(tokens) > 4:
15941596
labels.append(tokens[4])

src/pymatgen/io/vasp/sets.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,7 @@ def kpoints(self) -> Kpoints | None:
810810
"added_kpoints, or zero weighted k-points."
811811
)
812812
# If length is in kpoints settings use Kpoints.automatic
813+
warnings.filterwarnings("ignore", message="Please use INCAR KSPACING tag")
813814
return Kpoints.automatic(kconfig["length"])
814815

815816
base_kpoints = None

src/pymatgen/util/typing.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@
6060
SitePropsType = Union[list[dict[Any, Sequence[Any]]], dict[Any, Sequence[Any]]]
6161

6262
# Types specific to io.vasp
63-
Kpoint = Union[Tuple3Floats, tuple[int,]]
63+
Kpoint = Union[
64+
Tuple3Ints,
65+
tuple[int,], # Automatic k-point mesh
66+
Vector3D, # Line-mode and explicit k-point mesh
67+
]
6468

6569
# Miller index
6670
MillerIndex = Tuple3Ints

tests/io/vasp/test_inputs.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -888,29 +888,44 @@ def test_static_constructors(self):
888888
kpoints = Kpoints.gamma_automatic((3, 3, 3), [0, 0, 0])
889889
assert kpoints.style == Kpoints.supported_modes.Gamma
890890
assert kpoints.kpts == [(3, 3, 3)]
891+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0])
892+
891893
kpoints = Kpoints.monkhorst_automatic((2, 2, 2), [0, 0, 0])
892894
assert kpoints.style == Kpoints.supported_modes.Monkhorst
893895
assert kpoints.kpts == [(2, 2, 2)]
894-
kpoints = Kpoints.automatic(100)
896+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0])
897+
898+
with pytest.warns(DeprecationWarning, match="Please use INCAR KSPACING tag"):
899+
kpoints = Kpoints.automatic(100)
895900
assert kpoints.style == Kpoints.supported_modes.Automatic
896901
assert kpoints.kpts == [(100,)]
902+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0])
903+
897904
filepath = f"{VASP_IN_DIR}/POSCAR"
898905
struct = Structure.from_file(filepath)
899906
kpoints = Kpoints.automatic_density(struct, 500)
900907
assert kpoints.kpts == [(1, 3, 3)]
908+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0])
901909
assert kpoints.style == Kpoints.supported_modes.Gamma
910+
902911
kpoints = Kpoints.automatic_density(struct, 500, force_gamma=True)
903912
assert kpoints.style == Kpoints.supported_modes.Gamma
913+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0])
914+
904915
kpoints = Kpoints.automatic_density_by_vol(struct, 1000)
905916
assert kpoints.kpts == [(6, 10, 13)]
917+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0])
906918
assert kpoints.style == Kpoints.supported_modes.Gamma
919+
907920
kpoints = Kpoints.automatic_density_by_lengths(struct, [50, 50, 1], force_gamma=True)
908921
assert kpoints.kpts == [(5, 9, 1)]
922+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0]), kpoints.kpts
909923
assert kpoints.style == Kpoints.supported_modes.Gamma
910924

911925
struct.make_supercell(3)
912926
kpoints = Kpoints.automatic_density(struct, 500)
913927
assert kpoints.kpts == [(1, 1, 1)]
928+
assert all(isinstance(kpt, int) for kpt in kpoints.kpts[0])
914929
assert kpoints.style == Kpoints.supported_modes.Gamma
915930
kpoints = Kpoints.from_str(
916931
"""k-point mesh
@@ -966,7 +981,6 @@ def test_copy(self):
966981
assert kpts != kpt_copy
967982

968983
def test_automatic_kpoint(self):
969-
# struct = PymatgenTest.get_structure("Li2O")
970984
poscar = Poscar.from_str(
971985
"""Al1
972986
1.0

0 commit comments

Comments
 (0)