Skip to content

Commit 252efa7

Browse files
tpurcell90janosh
andauthored
Fix d2k function (#3932)
* Fix d2k function Need to use the transpose of the inverse matrix for recipmatrix * breaking: snake_case method args kpt_density and recip_cell (better to do early while user base small) * d2k_recip_cell fix kpt_density type anno and doc str * Add test for aims density conversions * Fix mypy errors * Add print line to see what the actual errors look like All tests pass locally * for supercell round coords should fix error in tests * remove extra print line * refactor test_static_si_no_kgrid --------- Co-authored-by: Janosh Riebesell <[email protected]>
1 parent 7a01f3c commit 252efa7

File tree

6 files changed

+49
-40
lines changed

6 files changed

+49
-40
lines changed

src/pymatgen/io/aims/sets/base.py

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import copy
66
import json
77
import logging
8-
from collections.abc import Iterable
98
from dataclasses import dataclass, field
109
from typing import TYPE_CHECKING, Any
1110
from warnings import warn
@@ -19,7 +18,7 @@
1918
from pymatgen.io.core import InputFile, InputGenerator, InputSet
2019

2120
if TYPE_CHECKING:
22-
from collections.abc import Sequence
21+
from collections.abc import Iterable, Sequence
2322

2423
from pymatgen.util.typing import PathLike
2524

@@ -234,7 +233,7 @@ def _read_previous(
234233
prev_dir (str or Path): The previous directory for the calculation
235234
"""
236235
prev_structure: Structure | Molecule | None = None
237-
prev_parameters = {}
236+
prev_params = {}
238237
prev_results: dict[str, Any] = {}
239238

240239
if prev_dir:
@@ -243,7 +242,7 @@ def _read_previous(
243242
# jobflow_remote)
244243
split_prev_dir = str(prev_dir).split(":")[-1]
245244
with open(f"{split_prev_dir}/parameters.json") as param_file:
246-
prev_parameters = json.load(param_file, cls=MontyDecoder)
245+
prev_params = json.load(param_file, cls=MontyDecoder)
247246

248247
try:
249248
aims_output: Sequence[Structure | Molecule] = read_aims_output(
@@ -256,7 +255,7 @@ def _read_previous(
256255
except (IndexError, AimsParseError):
257256
pass
258257

259-
return prev_structure, prev_parameters, prev_results
258+
return prev_structure, prev_params, prev_results
260259

261260
@staticmethod
262261
def _get_properties(
@@ -308,12 +307,9 @@ def _get_input_parameters(
308307
Returns:
309308
dict: The input object
310309
"""
311-
# Get the default configuration
312-
# FHI-aims recommends using their defaults so bare-bones default parameters
313-
parameters: dict[str, Any] = {
314-
"xc": "pbe",
315-
"relativistic": "atomic_zora scalar",
316-
}
310+
# Get the default config
311+
# FHI-aims recommends using their defaults so bare-bones default params
312+
params: dict[str, Any] = {"xc": "pbe", "relativistic": "atomic_zora scalar"}
317313

318314
# Override default parameters with previous parameters
319315
prev_parameters = {} if prev_parameters is None else copy.deepcopy(prev_parameters)
@@ -327,25 +323,25 @@ def _get_input_parameters(
327323
kpt_settings["density"] = density
328324

329325
parameter_updates = self.get_parameter_updates(structure, prev_parameters)
330-
parameters = recursive_update(parameters, parameter_updates)
326+
params = recursive_update(params, parameter_updates)
331327

332328
# Override default parameters with user_params
333-
parameters = recursive_update(parameters, self.user_params)
334-
if ("k_grid" in parameters) and ("density" in kpt_settings):
329+
params = recursive_update(params, self.user_params)
330+
if ("k_grid" in params) and ("density" in kpt_settings):
335331
warn(
336332
"WARNING: the k_grid is set in user_params and in the kpt_settings,"
337333
" using the one passed in user_params.",
338334
stacklevel=1,
339335
)
340-
elif isinstance(structure, Structure) and ("k_grid" not in parameters):
336+
elif isinstance(structure, Structure) and ("k_grid" not in params):
341337
density = kpt_settings.get("density", 5.0)
342338
even = kpt_settings.get("even", True)
343-
parameters["k_grid"] = self.d2k(structure, density, even)
344-
elif isinstance(structure, Molecule) and "k_grid" in parameters:
339+
params["k_grid"] = self.d2k(structure, density, even)
340+
elif isinstance(structure, Molecule) and "k_grid" in params:
345341
warn("WARNING: removing unnecessary k_grid information", stacklevel=1)
346-
del parameters["k_grid"]
342+
del params["k_grid"]
347343

348-
return parameters
344+
return params
349345

350346
def get_parameter_updates(
351347
self,
@@ -366,7 +362,7 @@ def get_parameter_updates(
366362
def d2k(
367363
self,
368364
structure: Structure,
369-
kptdensity: float | list[float] = 5.0,
365+
kpt_density: float | tuple[float, float, float] = 5.0,
370366
even: bool = True,
371367
) -> Iterable[float]:
372368
"""Convert k-point density to Monkhorst-Pack grid size.
@@ -376,15 +372,15 @@ def d2k(
376372
Args:
377373
structure (Structure): Contains unit cell and
378374
information about boundary conditions.
379-
kptdensity (float | list[float]): Required k-point
375+
kpt_density (float | list[float]): Required k-point
380376
density. Default value is 5.0 point per Ang^-1.
381377
even (bool): Round up to even numbers.
382378
383379
Returns:
384380
dict: Monkhorst-Pack grid size in all directions
385381
"""
386-
recipcell = structure.lattice.inv_matrix
387-
return self.d2k_recipcell(recipcell, structure.lattice.pbc, kptdensity, even)
382+
recip_cell = structure.lattice.inv_matrix.transpose()
383+
return self.d2k_recip_cell(recip_cell, structure.lattice.pbc, kpt_density, even)
388384

389385
def k2d(self, structure: Structure, k_grid: np.ndarray[int]):
390386
"""Generate the kpoint density in each direction from given k_grid.
@@ -398,36 +394,36 @@ def k2d(self, structure: Structure, k_grid: np.ndarray[int]):
398394
Returns:
399395
dict: Density of kpoints in each direction. result.mean() computes average density
400396
"""
401-
recipcell = structure.lattice.inv_matrix
402-
densities = k_grid / (2 * np.pi * np.sqrt((recipcell**2).sum(axis=1)))
397+
recip_cell = structure.lattice.inv_matrix.transpose()
398+
densities = k_grid / (2 * np.pi * np.sqrt((recip_cell**2).sum(axis=1)))
403399
return np.array(densities)
404400

405401
@staticmethod
406-
def d2k_recipcell(
407-
recipcell: np.ndarray,
402+
def d2k_recip_cell(
403+
recip_cell: np.ndarray,
408404
pbc: Sequence[bool],
409-
kptdensity: float | Sequence[float] = 5.0,
405+
kpt_density: float | tuple[float, float, float] = 5.0,
410406
even: bool = True,
411407
) -> Sequence[int]:
412408
"""Convert k-point density to Monkhorst-Pack grid size.
413409
414410
Args:
415-
recipcell (Cell): The reciprocal cell
411+
recip_cell (Cell): The reciprocal cell
416412
pbc (Sequence[bool]): If element of pbc is True
417413
then system is periodic in that direction
418-
kptdensity (float or list[floats]): Required k-point
419-
density. Default value is 3.5 point per Ang^-1.
414+
kpt_density (float or list[floats]): Required k-point
415+
density. Default value is 5 points per Ang^-1.
420416
even(bool): Round up to even numbers.
421417
422418
Returns:
423419
dict: Monkhorst-Pack grid size in all directions
424420
"""
425-
if not isinstance(kptdensity, Iterable):
426-
kptdensity = 3 * [float(kptdensity)]
421+
if isinstance(kpt_density, float):
422+
kpt_density = (kpt_density, kpt_density, kpt_density)
427423
kpts: list[int] = []
428424
for i in range(3):
429425
if pbc[i]:
430-
k = 2 * np.pi * np.sqrt((recipcell[i] ** 2).sum()) * float(kptdensity[i])
426+
k = 2 * np.pi * np.sqrt((recip_cell[i] ** 2).sum()) * float(kpt_density[i])
431427
if even:
432428
kpts.append(2 * int(np.ceil(k / 2)))
433429
else:

src/pymatgen/util/testing/aims.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def comp_system(
8484
generator_cls: type,
8585
properties: list[str] | None = None,
8686
prev_dir: str | None | Path = None,
87+
user_kpt_settings: dict[str, Any] | None = None,
8788
) -> None:
8889
"""Compare files generated by tests with ones in reference directories.
8990
@@ -96,16 +97,24 @@ def comp_system(
9697
generator_cls (type): The class of the generator
9798
properties (list[str] | None): The list of properties to calculate
9899
prev_dir (str | Path | None): The previous directory to pull outputs from
100+
user_kpt_settings (dict[str, Any] | None): settings for k-point density in FHI-aims
99101
100102
Raises:
101103
AssertionError: If the input files are not the same
102104
"""
105+
if user_kpt_settings is None:
106+
user_kpt_settings = {}
107+
103108
k_point_density = user_params.pop("k_point_density", 20)
104109

105110
try:
106-
generator = generator_cls(user_params=user_params, k_point_density=k_point_density)
111+
generator = generator_cls(
112+
user_params=user_params,
113+
k_point_density=k_point_density,
114+
user_kpoints_settings=user_kpt_settings,
115+
)
107116
except TypeError:
108-
generator = generator_cls(user_params=user_params)
117+
generator = generator_cls(user_params=user_params, user_kpoints_settings=user_kpt_settings)
109118

110119
input_set = generator.get_input_set(structure, prev_dir, properties)
111120
input_set.write_input(work_dir / test_name)
@@ -117,7 +126,7 @@ def compare_single_files(ref_file: str | Path, test_file: str | Path) -> None:
117126
"""Compare single files generated by tests with ones in reference directories.
118127
119128
Args:
120-
ref_file (str | Path): The reference file to cmpare against
129+
ref_file (str | Path): The reference file to compare against
121130
test_file (str | Path): The file to compare against the reference
122131
123132
Raises:
-82 Bytes
Binary file not shown.
-28 Bytes
Binary file not shown.

tests/io/aims/aims_input_generator_ref/static-no-kgrid-si/parameters.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"species_dir": "/home/tpurcell/git/atomate2/tests/aims/species_dir/light",
55
"k_grid": [
66
12,
7-
12,
8-
12
7+
6,
8+
4
99
]
1010
}

tests/io/aims/test_sets/test_static_generator.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ def test_static_si(tmp_path):
1919

2020
def test_static_si_no_kgrid(tmp_path):
2121
parameters = {"species_dir": "light"}
22-
comp_system(Si, parameters, "static-no-kgrid-si", tmp_path, ref_path, StaticSetGenerator)
22+
Si_supercell = Si.make_supercell([1, 2, 3], in_place=False)
23+
for site in Si_supercell:
24+
# round site.coords to ignore floating point errors
25+
site.coords = [round(x, 15) for x in site.coords]
26+
comp_system(Si_supercell, parameters, "static-no-kgrid-si", tmp_path, ref_path, StaticSetGenerator)
2327

2428

2529
def test_static_o2(tmp_path):

0 commit comments

Comments
 (0)