Skip to content

Commit 2345cc7

Browse files
Enable hdf5 for phonons bands (#557)
Co-authored-by: Elliott Kasoar <45317199+ElliottKasoar@users.noreply.github.com>
1 parent e40fc92 commit 2345cc7

File tree

7 files changed

+176
-53
lines changed

7 files changed

+176
-53
lines changed

docs/source/tutorials/python/phonons.ipynb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@
140140
" temp_min=0.0,\n",
141141
" temp_max=1000.0,\n",
142142
" minimize=False,\n",
143-
" force_consts_to_hdf5=True,\n",
143+
" hdf5=True,\n",
144144
" plot_to_file=True,\n",
145145
" symmetrize=False,\n",
146146
" write_full=True,\n",
@@ -249,7 +249,7 @@
249249
" temp_min=0.0,\n",
250250
" temp_max=1000.0,\n",
251251
" minimize=True,\n",
252-
" force_consts_to_hdf5=True,\n",
252+
" hdf5=True,\n",
253253
" plot_to_file=True,\n",
254254
" symmetrize=False,\n",
255255
" write_full=True,\n",
@@ -317,7 +317,7 @@
317317
" temp_min=0.0,\n",
318318
" temp_max=1000.0,\n",
319319
" minimize=True,\n",
320-
" force_consts_to_hdf5=True,\n",
320+
" hdf5=True,\n",
321321
" plot_to_file=True,\n",
322322
" symmetrize=False,\n",
323323
" write_full=True,\n",
@@ -399,7 +399,7 @@
399399
" temp_min=0.0,\n",
400400
" temp_max=1000.0,\n",
401401
" minimize=True,\n",
402-
" force_consts_to_hdf5=True,\n",
402+
" hdf5=True,\n",
403403
" plot_to_file=True,\n",
404404
" symmetrize=False,\n",
405405
" write_full=True,\n",
@@ -440,7 +440,7 @@
440440
" temp_min=0.0,\n",
441441
" temp_max=1000.0,\n",
442442
" minimize=True,\n",
443-
" force_consts_to_hdf5=True,\n",
443+
" hdf5=True,\n",
444444
" plot_to_file=True,\n",
445445
" symmetrize=False,\n",
446446
" write_full=True,\n",

docs/source/user_guide/command_line.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ This will save the Phonopy parameters, including displacements and force constan
494494
in addition to generating a log file, ``NaCl-phonons-log.yml``, and summary of inputs, ``NaCl-phonons-summary.yml``.
495495

496496
Additionally, the ``--bands`` option can be added to calculate the band structure
497-
and save the results to a compressed yaml file, ``NaCl-auto_bands.yml.xz``:
497+
and save the results to a compressed yaml file, ``NaCl-auto_bands.hdf5``:
498498

499499
.. code-block:: bash
500500
@@ -533,7 +533,7 @@ but band paths can also be specified explicitly using the ``--paths`` option to
533533
janus phonons --struct tests/data/NaCl.cif --arch mace_mp --bands --plot-to-file --paths tests/data/paths.yml
534534
535535
536-
This will save the results in a compressed yaml file, ``NaCl-bands.yml.xz``, as well as the generated plot, ``NaCl-bands.svg``.
536+
This will save the results in a compressed yaml file, ``NaCl-bands.hdf5``, as well as the generated plot, ``NaCl-bands.svg``.
537537

538538
The ``--paths`` file must include:
539539

janus_core/calculations/phonons.py

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from collections.abc import Sequence
66
from typing import Any, get_args
7+
from warnings import warn
78

89
from ase import Atoms
910
from numpy import ndarray
@@ -108,7 +109,9 @@ class Phonons(BaseCalculation):
108109
temp_step
109110
Temperature step for thermal properties calculations, in K. Default is 50.0.
110111
force_consts_to_hdf5
111-
Whether to write force constants in hdf format or not. Default is True.
112+
Deprecated. Please use `hdf5`.
113+
hdf5
114+
Whether to write force constants and bands in hdf5 or not. Default is True.
112115
plot_to_file
113116
Whether to plot various graphs as band stuctures, dos/pdos in svg.
114117
Default is False.
@@ -159,7 +162,8 @@ def __init__(
159162
temp_min: float = 0.0,
160163
temp_max: float = 1000.0,
161164
temp_step: float = 50.0,
162-
force_consts_to_hdf5: bool = True,
165+
force_consts_to_hdf5: bool | None = None,
166+
hdf5: bool = True,
163167
plot_to_file: bool = False,
164168
write_results: bool = True,
165169
write_full: bool = True,
@@ -238,7 +242,9 @@ def __init__(
238242
temp_step
239243
Temperature step for thermal calculations, in K. Default is 50.0.
240244
force_consts_to_hdf5
241-
Whether to write force constants in hdf format or not. Default is True.
245+
Deprecated. Please use `hdf5`.
246+
hdf5
247+
Whether to write force constants and bands in hdf5 or not. Default is True.
242248
plot_to_file
243249
Whether to plot various graphs as band stuctures, dos/pdos in svg.
244250
Default is False.
@@ -277,12 +283,27 @@ def __init__(
277283
self.temp_min = temp_min
278284
self.temp_max = temp_max
279285
self.temp_step = temp_step
280-
self.force_consts_to_hdf5 = force_consts_to_hdf5
286+
self.hdf5 = hdf5
281287
self.plot_to_file = plot_to_file
282288
self.write_results = write_results
283289
self.write_full = write_full
284290
self.enable_progress_bar = enable_progress_bar
285291

292+
# Handle deprecation
293+
if force_consts_to_hdf5 is not None:
294+
if hdf5 is False:
295+
raise ValueError(
296+
"""`force_consts_to_hdf5`: has replaced `hdf5`.
297+
Please only use `hdf5`"""
298+
)
299+
self.hdf5 = force_consts_to_hdf5
300+
warn(
301+
"""`force_consts_to_hdf5` has been deprecated.
302+
Please use `hdf5`.""",
303+
FutureWarning,
304+
stacklevel=2,
305+
)
306+
286307
# Ensure supercell is a valid list
287308
self.supercell = [supercell] * 3 if isinstance(supercell, int) else supercell
288309
if len(self.supercell) not in [3, 9]:
@@ -340,10 +361,11 @@ def __init__(
340361
# Output files
341362
self.phonopy_file = self._build_filename("phonopy.yml")
342363
self.force_consts_file = self._build_filename("force_constants.hdf5")
343-
if self.qpoint_file:
344-
self.bands_file = self._build_filename("bands.yml.xz")
345-
else:
346-
self.bands_file = self._build_filename("auto_bands.yml.xz")
364+
365+
filename = "bands" + (".hdf5" if hdf5 else ".yml")
366+
if not self.qpoint_file:
367+
filename = f"auto_{filename}"
368+
self.bands_file = self._build_filename(filename)
347369
self.bands_plot_file = self._build_filename("bands.svg")
348370
self.dos_file = self._build_filename("dos.dat")
349371
self.dos_plot_file = self._build_filename("dos.svg")
@@ -430,9 +452,7 @@ def output_files(self) -> None:
430452
return {
431453
"log": self.log_kwargs["filename"] if self.logger else None,
432454
"params": self.phonopy_file if self.write_results else None,
433-
"force_constants": (
434-
self.force_consts_file if self.force_consts_to_hdf5 else None
435-
),
455+
"force_constants": (self.force_consts_file if self.hdf5 else None),
436456
"bands": (
437457
self.bands_file
438458
if self.write_results and "bands" in self.calcs
@@ -552,7 +572,7 @@ def write_force_constants(
552572
self,
553573
*,
554574
phonopy_file: PathLike | None = None,
555-
force_consts_to_hdf5: bool | None = None,
575+
hdf5: bool | None = None,
556576
force_consts_file: PathLike | None = None,
557577
) -> None:
558578
"""
@@ -563,11 +583,11 @@ def write_force_constants(
563583
phonopy_file
564584
Name of yaml file to save params of phonopy and optionally force constants.
565585
Default is inferred from `file_prefix`.
566-
force_consts_to_hdf5
586+
hdf5
567587
Whether to save the force constants separately to an hdf5 file. Default is
568-
self.force_consts_to_hdf5.
588+
self.hdf5.
569589
force_consts_file
570-
Name of hdf5 file to save force constants. Unused if `force_consts_to_hdf5`
590+
Name of hdf5 file to save force constants. Unused if `hdf5`
571591
is False. Default is inferred from `file_prefix`.
572592
"""
573593
if "phonon" not in self.results:
@@ -576,8 +596,8 @@ def write_force_constants(
576596
"Please run `calc_force_constants` first"
577597
)
578598

579-
if force_consts_to_hdf5 is None:
580-
force_consts_to_hdf5 = self.force_consts_to_hdf5
599+
if hdf5 is None:
600+
hdf5 = self.hdf5
581601

582602
if phonopy_file:
583603
self.phonopy_file = phonopy_file
@@ -586,11 +606,11 @@ def write_force_constants(
586606

587607
phonon = self.results["phonon"]
588608

589-
save_force_consts = not force_consts_to_hdf5
609+
save_force_consts = not hdf5
590610
build_file_dir(self.phonopy_file)
591611
phonon.save(self.phonopy_file, settings={"force_constants": save_force_consts})
592612

593-
if force_consts_to_hdf5:
613+
if hdf5:
594614
build_file_dir(self.force_consts_file)
595615
write_force_constants_to_hdf5(
596616
phonon.force_constants, filename=self.force_consts_file
@@ -621,6 +641,7 @@ def calc_bands(self, write_bands: bool | None = None, **kwargs) -> None:
621641
def write_bands(
622642
self,
623643
*,
644+
hdf5: bool | None = None,
624645
bands_file: PathLike | None = None,
625646
save_plots: bool | None = None,
626647
plot_file: PathLike | None = None,
@@ -630,6 +651,9 @@ def write_bands(
630651
631652
Parameters
632653
----------
654+
hdf5
655+
Whether to save the bands in an hdf5 file. Default is
656+
self.hdf5.
633657
bands_file
634658
Name of yaml file to save band structure. Default is inferred from
635659
`file_prefix`.
@@ -645,11 +669,15 @@ def write_bands(
645669
"Please run `calc_force_constants` first"
646670
)
647671

672+
if hdf5 is None:
673+
hdf5 = self.hdf5
674+
648675
if save_plots is None:
649676
save_plots = self.plot_to_file
650677

651678
if bands_file:
652679
self.bands_file = bands_file
680+
653681
if plot_file:
654682
self.bands_plot_file = plot_file
655683

@@ -682,10 +710,14 @@ def write_bands(
682710
)
683711

684712
build_file_dir(self.bands_file)
685-
self.results["phonon"].write_yaml_band_structure(
686-
filename=self.bands_file,
687-
compression="lzma",
688-
)
713+
if hdf5:
714+
self.results["phonon"].write_hdf5_band_structure(
715+
filename=self.bands_file,
716+
)
717+
else:
718+
self.results["phonon"].write_yaml_band_structure(
719+
filename=self.bands_file,
720+
)
689721

690722
bplt = self.results["phonon"].plot_band_structure()
691723
if save_plots:

janus_core/cli/phonons.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
Summary,
2727
Tracker,
2828
)
29-
from janus_core.cli.utils import yaml_converter_callback
29+
from janus_core.cli.utils import deprecated_option, yaml_converter_callback
3030

3131
app = Typer()
3232

@@ -110,11 +110,20 @@ def phonons(
110110
),
111111
] = 0.1,
112112
minimize_kwargs: MinimizeKwargs = None,
113-
hdf5: Annotated[
113+
force_consts_to_hdf5: Annotated[
114114
bool,
115115
Option(
116116
help="Whether to save force constants in hdf5.",
117117
rich_help_panel="Calculation",
118+
callback=deprecated_option,
119+
hidden=True,
120+
),
121+
] = None,
122+
hdf5: Annotated[
123+
bool,
124+
Option(
125+
help="Whether to save force constants and bands in hdf5.",
126+
rich_help_panel="Calculation",
118127
),
119128
] = True,
120129
plot_to_file: Annotated[
@@ -228,8 +237,11 @@ def phonons(
228237
Default is 0.1.
229238
minimize_kwargs
230239
Other keyword arguments to pass to geometry optimizer. Default is {}.
240+
force_consts_to_hdf5
241+
Deprecated. Please use `hdf5`.
231242
hdf5
232-
Whether to save force constants in hdf5 format. Default is True.
243+
Whether to save force constants and bands in hdf5 format.
244+
Default is True.
233245
plot_to_file
234246
Whether to plot. Default is False.
235247
write_full
@@ -391,7 +403,7 @@ def phonons(
391403
"temp_min": temp_min,
392404
"temp_max": temp_max,
393405
"temp_step": temp_step,
394-
"force_consts_to_hdf5": hdf5,
406+
"hdf5": hdf5,
395407
"plot_to_file": plot_to_file,
396408
"write_results": True,
397409
"write_full": write_full,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ dependencies = [
3030
"click<9,>=8.2.1",
3131
"codecarbon<4.0.0,>=3.0.4",
3232
"numpy<3.0.0,>=1.26.4",
33-
"phonopy<3.0.0,>=2.23.1",
33+
"phonopy<3.0.0,>=2.39.0",
3434
"pymatgen>=2025.1.24",
3535
"pyyaml<7.0.0,>=6.0.1",
3636
"rich<14.0.0,>=13.9.1",

tests/test_phonons.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ def test_calc_phonons():
4040
assert "phonon" in phonons.results
4141

4242

43+
def test_force_consts_to_hdf5_deprecation():
44+
"""Test deprecation of force-consts-to-hdf5."""
45+
struct = read(DATA_PATH / "NaCl.cif")
46+
struct.calc = choose_calculator(arch="mace_mp", model=MODEL_PATH)
47+
with pytest.warns(
48+
FutureWarning, match="`force_consts_to_hdf5` has been deprecated."
49+
):
50+
phonons = Phonons(
51+
struct=struct,
52+
force_consts_to_hdf5=True,
53+
)
54+
55+
phonons.calc_force_constants(write_force_consts=True)
56+
assert "phonon" in phonons.results
57+
58+
4359
def test_optimize(tmp_path):
4460
"""Test optimizing structure before calculation."""
4561
log_file = tmp_path / "phonons.log"

0 commit comments

Comments
 (0)