Effective Quasi-Harmonic#
- class directupsampling.effqh.effqh.EffQH(atoms: Atoms | list[Atoms], fit_order: int | None = None, cutoffs: list[float] | None = None, comm: DummyMPI = <directupsampling.parallel.MPI object>)[source]#
Bases:
objectClass representing an effective quasi-harmonic model.
- property calc: EffQHCalculator#
- change_reference(new_atoms: Atoms) EffQH[source]#
Return a new EffQH instance for
new_atoms.Parameters#
- new_atomsAtoms
Must have the same symmetry as
effqh.atomsand be large enough for the cutoff to fit inside, but can differ in number or order of atoms, and cell shape.
Returns#
EffQH
- change_size(new_atoms: Atoms) EffQH[source]#
Return a new EffQH instance for
new_atoms.Parameters#
- new_atomsAtoms
Must have the same symmetry as
effqh.atomsand be large enough for the cutoff to fit inside, but can differ in number of atoms and cell shape.
Returns#
EffQH
- property exact_free_energy_surface#
- property exact_phonons#
- extract_fc_potentials() None[source]#
Extract ForceConstantPotential.
The ForceConstantPotential instances is extracted from
self.fc_fit.raw_dataintoself.fc_potentials.
- fit_snapshots(snapshots: SnapshotContainer | list[list[Atoms]], method: str | None = None) None[source]#
Fits the EffQH to snapshots over volumes.
Internally fits a hiphive ForceConstantPotential to the snapshots for each volume, and then fits each resulting force-constant component with a polynomial over volume.
Parameters#
- snapshotsSnapshotContainer or list of list of Atoms
Either a SnapshotContainer with volumes in the index or a list grouped by volume with lists of Atoms.
- methodstr (optional)
Method for fitting the effective force constants. Defaults to ‘least-squares’ in general and lasso for underdetermined systems.
Notes#
For large systems, the ‘least-squares’ method is preferred for speed reasons.
- property mesh_free_energy_surface#
- property mesh_phonons#
- classmethod read_fcp(pathname: str, atoms: Atoms | list[Atoms], fit_order: int | None = None)[source]#
- write_hessian(volume: float, file: os.PathLike | str, filetype: str | None = None, fmt: str = 'sphinx', unit: str = 'eVperAng2') None[source]#
Write the force-constant matrix for a given volume to file.
Parameters#
- volumefloat
Volume for which to write the force-constant matrix.
- fileos.PathLike or str
Path to the output file.
- filetypestr
Filetype to write. Must be ‘txt’, ‘hdf5’ or None. If None, the filetype is guessed from the file suffix.
- fmtstr
Format of the output file. Must be ‘sphinx’ or ‘phonopy’. Default is ‘sphinx’.
- unitstr
Unit of the force constants, only relevant for
fmt="sphinx". Must be ‘eVperAng2’ or ‘HaperBohr2’. Default is ‘eVperAng2’.
- directupsampling.effqh.utils.get_ref_atoms(atoms: Atoms | list[Atoms], volume: float) Atoms[source]#
Return atoms scaled to volume per atom, or the list entry closest to it.
Returns#
Atoms
Raises#
- TypeError
If no entry in the list matches volume.
- class directupsampling.effqh.fcfit.ForceConstantFit(fit_order: int | None = None)[source]#
Bases:
objectClass for fitting force constants.
- property coefficients: ndarray[Any, dtype[float64]]#
Fitted force constant coefficients.
- directupsampling_objtype = 'forceconstantfit'#
- fit_force_constants(volumes, force_constants)[source]#
Fit each element of force constants to polynomials of volumes
- classmethod fit_from_hiphive(volumes: list[float], force_constant_potentials: list[ForceConstantPotential], atoms: Atoms | list[Atoms], fit_order: int | None = None) Self[source]#
Fit a ForceConstantFit from a list of hiphive ForceConstantPotentials.
Parameters#
- volumes: list of float
List of volumes corresponding to the ForceConstantPotentials.
- force_constant_potentials: list of ForceConstantPotential
List of hiphive ForceConstantPotentials to fit to.
- atoms: Atoms or list of Atoms
Reference Atoms or list of Atoms to get the force constants with.
- fit_order: int, optional
The fitting order of polynomials. If None, the order is 3 or less.
Returns#
ForceConstantFit
- classmethod fromdict(dct: dict) Self[source]#
Reconstruct a
ForceConstantFitfrom itstodict()form.Returns#
ForceConstantFit
- get_force_constants(volume: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray[Any, dtype[float64]][source]#
Get force constants at the given volume(s) by interpolation.
- class directupsampling.effqh.phonons.BasePhonons(atoms: Atoms, volume_bounds: list | None = None, freq_coeffs: ndarray | None = None, weights: ndarray | None = None, *, invert_neg: bool = False, freq_cutoff: float = 1e-05)[source]#
Bases:
objectBase class for phonon models fitted as polynomial functions of volume.
Subclasses implement
force_constants_to_frequenciesfor a specific diagonalisation scheme (Gamma-point exact diagonalisation or BZ mesh via phonopy).- FREQ_WARN_TOL = 1e-05#
- abstractmethod force_constants_to_frequencies(force_constants: ndarray) ndarray[source]#
Return frequencies in eV and set
self.weights.Parameters#
- force_constants :
Force-constant matrix for the structure.
Returns#
- np.ndarray
Frequencies in eV, sorted in ascending order.
- classmethod from_fcfit(atoms: Atoms, force_constant_fit: ForceConstantFit, mesh: list | None = None, *, invert_neg: bool = False, freq_cutoff: float = 1e-05) BasePhonons[source]#
Construct a phonon model by fitting frequencies from a ForceConstantFit.
Parameters#
- atoms :
Reference structure.
- force_constant_fit :
Fitted force constants as a function of volume.
- mesh :
BZ mesh passed to MeshPhonons; omit for ExactPhonons.
- invert_neg :
Forwarded to
__init__.- freq_cutoff :
Forwarded to
__init__.
Returns#
- BasePhonons
Instance with
freq_coeffsandweightsset.
- get_energy(volume: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], *, classical: bool = False) ndarray[source]#
Harmonic internal energy per atom.
Parameters#
- volume :
Volume(s) in ų.
- temperature :
Temperature(s) in Kelvin.
- classical :
Use the classical (k_B*T) expression instead of quantum.
Returns#
- np.ndarray
Internal energy in eV/atom.
- get_free_energy(volume: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], *, classical: bool = False) ndarray[source]#
Harmonic Helmholtz energy per atom.
Parameters#
- volume :
Volume(s) in ų.
- temperature :
Temperature(s) in Kelvin.
- classical :
Use the classical expression instead of quantum.
Returns#
- np.ndarray
Helmholtz energy in eV/atom.
- get_frequencies(volume: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray[source]#
Evaluate the polynomial frequency model at the given volume(s).
Parameters#
- volume :
Volume(s) in ų.
Returns#
- np.ndarray
Frequencies in eV with shape (n_freq, *volume.shape).
- sum_over_frequencies(fun: Callable[[ndarray, ndarray], ndarray], volume: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray[source]#
Weighted sum of
funover modes abovefreq_cutoff.Normalised per vibrational atom (see denominator note below).
Modes at or below
freq_cutoffare excluded from the sum via a binary mask; they contribute zero to the numerator regardless offun.The denominator is
weights.sum() / 3 - 1, equal to N_atoms - 1 (ExactPhonons) or N_atoms * N_kpoints - 1 (MeshPhonons). This normalises per vibrational atom: after removing the 3 translational modes the system has 3N-3 physical degrees of freedom, giving N-1 effective 3-DOF “atoms”. This matches the MD convention where COM kinetic energy is subtracted before normalising. For large supercells the difference from 1/N is negligible; for small unit cells (e.g. N=2) the factor of 2 is intentional and ensures consistency with MD.Parameters#
- fun :
Function
(temperature, frequency) -> energy.- volume :
Volume(s) in ų.
- temperature :
Temperature(s) in Kelvin.
Returns#
- np.ndarray
Weighted sum of
funover active frequencies, per atom.
Warns#
- RuntimeWarning
If any frequency remains below
-FREQ_WARN_TOLafter optional inversion.
- class directupsampling.effqh.phonons.ExactPhonons(atoms: Atoms, volume_bounds: list | None = None, freq_coeffs: ndarray | None = None, weights: ndarray | None = None, *, invert_neg: bool = False, freq_cutoff: float = 1e-05)[source]#
Bases:
BasePhononsGamma-point phonons via exact diagonalisation of the dynamical matrix.
- directupsampling_objtype = 'exactphonons'#
- force_constants_to_frequencies(force_constants: ndarray) ndarray[source]#
Diagonalise the dynamical matrix and return frequencies in eV.
Uses
eigvalsh(real-symmetric solver) for numerical stability. Negative eigenvalues are mapped to negative frequencies viasqrt(|lambda|) * sign(lambda)rather than producing imaginary values. Setsself.weights = ones(3N).Parameters#
- force_constants :
Force-constant matrix for the structure.
Returns#
- np.ndarray
Frequencies in eV sorted in ascending order, shape (3N,).
- class directupsampling.effqh.phonons.MeshPhonons(*args: Any, mesh: list, **kwargs: Any)[source]#
Bases:
BasePhononsBZ-mesh phonons computed via phonopy.
- directupsampling_objtype = 'meshphonons'#
- force_constants_to_frequencies(force_constants: ndarray) ndarray[source]#
Compute BZ-mesh frequencies via phonopy and return them in eV.
Sets
self.weightsto the phonopy k-point weights repeated over branches (shape: n_qpoints * 3 * N_primitive).Parameters#
- force_constants :
Force-constant matrix for the structure.
Returns#
- np.ndarray
Frequencies in eV, shape (n_qpoints * 3 * N_primitive,).
- class directupsampling.effqh.phonons.PhonopyHandler(atoms: Atoms, force_constants: ndarray, mesh: list)[source]#
Bases:
objectThin wrapper around a phonopy Phonopy object for a single structure.
- get_weights() ndarray[source]#
Return k-point weights repeated over branches (3 * N_primitive per q-point).
- property phonons#
- directupsampling.effqh.phonons.evib_classical(temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], frequency: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] = None) ndarray[source]#
Classical harmonic internal energy: k_B * T.
Parameters#
- temperature :
Temperature in Kelvin.
- frequency :
Ignored; present for interface compatibility with the QM form.
Returns#
- np.ndarray
k_B * T.
- directupsampling.effqh.phonons.evib_qm(temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], frequency: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray[source]#
Quantum harmonic internal energy.
Parameters#
- temperature :
Temperature in Kelvin.
- frequency :
Frequency in eV.
Returns#
- np.ndarray
omega/2 + omega / (exp(omega / (k_B*T)) - 1). At T=0 returns the zero-point energy omega/2.
- directupsampling.effqh.phonons.fvib_classical(temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], frequency: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray[source]#
Classical harmonic vibrational Helmholtz energy.
Parameters#
- temperature :
Temperature in Kelvin.
- frequency :
Frequency in eV.
Returns#
- np.ndarray
k_B * T * ln(omega / (k_B*T)).
- directupsampling.effqh.phonons.fvib_qm(temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], frequency: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray[source]#
Quantum harmonic vibrational Helmholtz energy.
Parameters#
- temperature :
Temperature in Kelvin.
- frequency :
Frequency in eV.
Returns#
- np.ndarray
omega/2 + k_B*T * ln(1 - exp(-omega / (k_B*T))). At T=0 returns the zero-point energy omega/2.