Harmonic Approximation
This tutorial calculates harmonic thermodynamic properties for periclase (MgO) over a series of eleven volumes. The same calculation is performed through the command-line interface and the public Python API.
The tutorial demonstrates an important property of the HA workflow: a single input may contain several volumes. Quantas evaluates the harmonic thermodynamic functions independently at every sampled volume; it does not select an equilibrium volume in this workflow. Equilibrium as a function of pressure and temperature is introduced later by the QHA tutorial.
Scientific objective
For each sampled volume and temperature, calculate:
zero-point energy, \(U_{\mathrm{zp}}(V)\);
thermal vibrational energy, \(U_{\mathrm{th}}(T,V)\);
total internal energy, \(U(T,V)\);
entropy, \(S(T,V)\);
vibrational and total Helmholtz free energy;
isochoric heat capacity, \(C_V(T,V)\).
Dataset
The example is derived from a CRYSTAL17 quasi-harmonic calculation for MgO. The normalized Quantas YAML contains:
2 atoms in the primitive cell;
1 formula unit per cell;
32 supplied q-points;
6 phonon branches at every q-point;
11 volumes from approximately 15.50 to 21.16 ų;
one static energy and one phonon-frequency set for every volume.
The complete input is distributed at
examples/qha/crystal-qha/mgo_b3lyp.yaml.
A shortened excerpt is shown below. The complete file also contains the volume-dependent structures and all frequency arrays.
job: MgO Periclase (CRYSTAL17 QHA)
natom: 2
formula_units: 1
mode_continuity: assumed
supercell:
- [-2, 2, 2]
- [ 2, -2, 2]
- [ 2, 2, -2]
structure:
representation: primitive
reference_index: 6
volume_series:
volume:
- 15.495426716592775
- 16.068019225910940
# ... nine additional volumes ...
- 21.164485271468507
qpoints: 32
phonon:
- q-position: [0.0, 0.0, 0.0]
weight: 1
band:
- frequency: [0.0, 0.0, 0.0, ...]
# ... remaining branches and q-points ...
Note
Quantas uses the q-point weights supplied by the input. It does not derive symmetry multiplicities during an HA or QHA run. Input weights must therefore already represent the intended sampling convention.
Temperature grid
The calculation uses temperatures from 0 to 1000 K in steps of 100 K. This coarse grid is chosen for a readable tutorial. Production calculations should use a resolution appropriate to the scientific question.
Running HA from the command line
From the repository root, run:
quantas ha run examples/qha/crystal-qha/mgo_b3lyp.yaml \
--temperature 0 1000 100 \
--output mgo_ha.hdf5 \
--report mgo_ha.log \
--verbosity standard \
--no-progress \
--force
The command produces:
mgo_ha.hdf5Native scientific result containing normalized metadata and all HA arrays.
mgo_ha.logDeterministic plain-text report.
The beginning of the report confirms that the full multi-volume dataset was accepted:
Input summary: 2 atoms, 32 q-points, 11 volumes
Selected options
----------------
Option | Value
-------------------------+--------
Temperature minimum | 0
Temperature maximum | 1000
Temperature step | 100
Temperature unit | K
Energy unit | Ha
Volume unit | A
Frequency unit | cm^-1
Numerical precision | float64
Understanding the HA report
Volume-only quantities
The static energy and zero-point energy depend on volume but not on the requested temperature grid. They are therefore reported once per volume:
Static and zero-point energies
------------------------------
V | U0 | Uzp
(A^3) | (Ha) | (Ha)
------------+---------------------+-------------------
15.49542672 | -2.754467055837E+02 | 7.053334071905E-03
18.89686185 | -2.754628820004E+02 | 5.470199108461E-03
21.16448527 | -2.754585023425E+02 | 4.614423074024E-03
For this dataset, \(U_{\mathrm{zp}}\) decreases as the cell expands. The phonon spectrum softens with increasing volume, so the sum of \(h\nu/2\) terms becomes smaller.
Temperature-volume arrays
The report then identifies the stored shapes:
Key Description Available Shape
Uzp Zero-point energy yes (1, 11)
Uth Thermal energy yes (11, 11)
Utot Internal energy yes (11, 11)
S Entropy yes (11, 11)
Fvib Vibrational Helmholtz free energy yes (11, 11)
F Helmholtz free energy yes (11, 11)
Cv Isochoric heat capacity yes (11, 11)
The first axis of the temperature-dependent arrays contains the 11
temperatures; the second contains the 11 sampled volumes. The zero-point
energy retains its physically meaningful shape (1, 11) because it does not
depend on temperature.
At the reference-like volume of 18.8969 ų, selected values are:
T (K) |
\(U_{\mathrm{th}}\) (kJ mol⁻¹) |
\(F_{\mathrm{vib}}\) (kJ mol⁻¹) |
\(S\) (J mol⁻¹ K⁻¹) |
\(C_V\) (J mol⁻¹ K⁻¹) |
|---|---|---|---|---|
0 |
0.000 |
14.362 |
0.000 |
0.000 |
300 |
5.000 |
11.694 |
25.558 |
35.922 |
1000 |
36.238 |
-27.417 |
78.017 |
47.638 |
The zero-temperature vibrational free energy equals the zero-point energy. With increasing temperature, entropy lowers \(F_{\mathrm{vib}}\), while \(C_V\) approaches the classical high-temperature limit.
Exporting a property table
A selected property can be exported from the HDF5 result. For example:
quantas ha export mgo_ha.hdf5 \
--property Cv \
--unit J/mol \
--output mgo_ha_Cv.dat
Download the complete HA heat-capacity table
The table preserves one column per sampled volume:
# Quantas HA table export
# Property: Cv - Isochoric heat capacity
# Units: J mol^-1 K^-1
#
T / K V=15.495427 / A^3 ... V=18.896862 / A^3 ... V=21.164485 / A^3
0.00000000 0.000000000000E+00 ... 0.000000000000E+00 ... 0.000000000000E+00
300.000000 2.980199098224E+01 ... 3.592223697777E+01 ... 3.903139950331E+01
1000.00000 4.670869809859E+01 ... 4.763783551464E+01 ... 4.802494090781E+01
Generating selected HA plots
Isochoric heat capacity
quantas ha plot mgo_ha.hdf5 \
--property Cv \
--unit J/mol \
--output figures/mgo_ha_cv \
--preset publication \
--format png \
--dpi 180
Harmonic \(C_V(T,V)\) for all sampled volumes. Larger volumes have softer frequencies and therefore reach a given fraction of the high-temperature limit at lower temperature. At high temperature the curves converge toward the same classical limit.
Vibrational Helmholtz free energy
quantas ha plot mgo_ha.hdf5 \
--property Fvib \
--unit kJ/mol \
--output figures/mgo_ha_fvib \
--preset publication \
--format png \
--dpi 180
Vibrational Helmholtz free energy as a function of temperature. Expanded cells have lower-frequency phonons and acquire a more negative entropic contribution. This changing volume dependence is the physical ingredient used by the quasi-harmonic approximation.
Running the same calculation from Python
The complete API script is distributed with the examples:
1"""Reproduce the HA MgO tutorial through the public Quantas API."""
2
3from __future__ import annotations
4
5import argparse
6from pathlib import Path
7
8from quantas.api import ha, rendering
9
10
11def main() -> None:
12 """Run HA, write HDF5/report files, and render selected figures."""
13 parser = argparse.ArgumentParser()
14 parser.add_argument("input", type=Path)
15 parser.add_argument("--output-dir", type=Path, default=Path("ha_tutorial"))
16 args = parser.parse_args()
17
18 args.output_dir.mkdir(parents=True, exist_ok=True)
19
20 options = ha.Options(
21 temperature_min=0.0,
22 temperature_max=1000.0,
23 temperature_step=100.0,
24 energy_unit="Ha",
25 volume_unit="A",
26 frequency_unit="cm^-1",
27 temperature_unit="K",
28 )
29
30 result = ha.run(args.input, options=options)
31 payload = ha.get_result(result)
32
33 report = rendering.render_tables(ha.build_report(result))
34 report_path = args.output_dir / "mgo_ha_api.log"
35 report_path.write_text(report, encoding="utf-8")
36
37 hdf5_path = ha.write_result(
38 result,
39 args.output_dir / "mgo_ha_api.hdf5",
40 report_text=report,
41 )
42
43 plot_requests = (
44 ("Cv", "J/mol", "mgo_ha_cv_"),
45 ("Fvib", "kJ/mol", "mgo_ha_fvib_"),
46 )
47 for property_name, unit, prefix in plot_requests:
48 collection = ha.build_plots(
49 result,
50 properties=property_name,
51 unit=unit,
52 )
53 rendering.render_plots(
54 collection,
55 output_dir=args.output_dir,
56 filename_prefix=prefix,
57 preset="publication",
58 dpi=180,
59 close=True,
60 )
61
62 print(f"Temperatures: {payload.temperature.size}")
63 print(f"Volumes: {payload.volume.size}")
64 print(f"Cv shape: {payload.isochoric_heat_capacity.shape}")
65 print(f"Written: {hdf5_path}")
66 print(f"Written: {report_path}")
67
68
69if __name__ == "__main__":
70 main()
Run it with:
python examples/ha/tutorial_api.py \
examples/qha/crystal-qha/mgo_b3lyp.yaml \
--output-dir ha_tutorial
The relevant public steps are:
construct
quantas.api.ha.Options;call
quantas.api.ha.run();obtain the typed payload with
quantas.api.ha.get_result();build deterministic tables with
quantas.api.ha.build_report();write HDF5 with
quantas.api.ha.write_result();build neutral plots with
quantas.api.ha.build_plots();render them through
quantas.api.rendering.
The script reports:
Temperatures: 11
Volumes: 11
Cv shape: (11, 11)
Written: ha_tutorial/mgo_ha_api.hdf5
Written: ha_tutorial/mgo_ha_api.log
Scientific interpretation
This HA calculation provides thermodynamic functions at fixed volumes. It shows that the volume dependence of the vibrational spectrum is substantial, but HA alone does not determine which volume is stable at a given pressure and temperature. The next tutorial combines the static and vibrational free energies, minimizes \(F(V,T)+PV\), and obtains equilibrium QHA properties.
Reproducibility checkpoints
For the distributed input and the options used above:
the input contains 11 volumes and 32 supplied q-points;
Uzphas shape(1, 11);every temperature-dependent property has shape
(11, 11);at 18.89686185 ų, \(U_{\mathrm{zp}}\) is approximately 14.3620 kJ mol⁻¹;
at 300 K and the same volume, \(C_V\) is approximately 35.9222 J mol⁻¹ K⁻¹.