Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions q2mm/models/hessian.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def replace_neg_eigenvalue(
eigenvalues: np.ndarray,
replace_with: float = 1.0,
zer_out_neg: bool = False,
units: int = co.KJMOLA,
units: str = co.GAUSSIAN,
strict: bool = True,
) -> np.ndarray:
"""Replace the most negative eigenvalue to invert TS curvature (Method C).
Expand All @@ -264,9 +264,10 @@ def replace_neg_eigenvalue(
large positive value so that the TS is treated as an energy minimum by
the MM force field.

The default replacement is 1.0 Hartree/Bohr², converted to
kJ/(mol·Å²) via :func:`~q2mm.models.units.hessian_au_to_kjmola2`
(≈ 9376). This operates on **Cartesian** Hessian eigenvalues —
The default replacement is 1.0 Hartree/Bohr² (atomic units). When
*units* is ``co.KJMOLA``, the replacement is converted via
:func:`~q2mm.models.units.hessian_au_to_kjmola2` (≈ 9376) to
kJ/mol/Ų. This operates on **Cartesian** Hessian eigenvalues —
not mass-weighted ones.

Note: Limé & Norrby showed that "Method D" (fitting the natural eigenvalue
Expand All @@ -280,8 +281,9 @@ def replace_neg_eigenvalue(
replace_with (float): Replacement value in Hartree/Bohr². Defaults to 1.0.
zer_out_neg (bool): If True, zero out remaining negative eigenvalues after
replacing the most negative. Defaults to False.
units (int): Target units for the replacement. If ``co.KJMOLA``
(default), *replace_with* is converted via
units (str): Unit system of the eigenvalues. If ``co.GAUSSIAN``
(default), *replace_with* is used as-is (Hartree/Bohr²).
If ``co.KJMOLA``, *replace_with* is converted via
:func:`~q2mm.models.units.hessian_au_to_kjmola2`.
strict (bool): If True, raise ValueError when more than one negative
eigenvalue is found (indicates a higher-order saddle point or
Expand Down
17 changes: 13 additions & 4 deletions q2mm/parsers/jaguar.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@
class JaguarIn(File):
"""Retrieve data from Jaguar ``.in`` files.

The Hessian is not mass-weighted. Hessian units are assumed to be
kJ/(mol·Å²).
The Hessian is **not** mass-weighted and is returned in atomic units
(Hartree/Bohr²), matching the convention used by Gaussian .fchk and
Psi4 outputs. Jaguar stores the Hessian in the ``&hess`` section of
its ``.in`` file in Hartree/Bohr² (confirmed empirically: raw diagonal
elements give frequencies that match the Jaguar ``.out`` exactly when
treated as atomic units).
Comment thread
ericchansen marked this conversation as resolved.
"""

def __init__(self, path: str) -> None:
Expand Down Expand Up @@ -57,7 +61,8 @@ def get_hessian(self, num_atoms: int) -> np.ndarray:

Returns:
(numpy.ndarray): 2-D Hessian matrix of shape
``(num_atoms * 3, num_atoms * 3)`` after unit conversion.
``(num_atoms * 3, num_atoms * 3)`` in Hartree/Bohr²
(atomic units, no additional conversion applied).

"""
if self._hessian is None:
Expand Down Expand Up @@ -85,7 +90,11 @@ def get_hessian(self, num_atoms: int) -> np.ndarray:

logger.log(1, f">>> hessian:\n{hessian}")
logger.log(5, f" -- Created {hessian.shape} Hessian matrix (w/o dummy atoms).")
self._hessian = hessian * co.HESSIAN_CONVERSION # Hartree/Bohr² → kJ/(mol·Å²); see constants.py
# Jaguar stores the Hessian in atomic units (Hartree/Bohr²).
# We return it as-is to match the convention of other QM parsers
# (Gaussian .fchk, Psi4). Downstream code (Seminario, frequency
# computation) expects AU when au_hessian=True / au_units=True.
self._hessian = hessian
logger.log(1, f">>> hessian.shape: {hessian.shape}")
return self._hessian

Expand Down
Empty file.
Loading
Loading