Skip to content

Add transition-state thermochemistry and Eyring rate constants - #105

Merged
galjos merged 1 commit into
mainfrom
transition-state-eyring
Jul 8, 2026
Merged

Add transition-state thermochemistry and Eyring rate constants#105
galjos merged 1 commit into
mainfrom
transition-state-eyring

Conversation

@galjos

@galjos galjos commented Jul 8, 2026

Copy link
Copy Markdown
Member

Thermo.run() previously raised on any imaginary vibrational frequency, so a transition state (a first-order saddle point) could not be evaluated at all — blocking barrier/rate work.

Core: Thermo(..., transition_state=True)

  • Requires exactly one imaginary mode among the kept frequencies (raises a clear error otherwise: too few/too many).
  • Excludes that mode from the vibrational partition function / entropy / energy / heat-capacity sums (the reaction coordinate contributes no thermal vibrational term) — everything else (rotational/translational/electronic) is unchanged.
  • Exposes it via Thermo.imaginary_mode_wavenumber() (cm⁻¹, negative).
  • Non-TS behavior (the default) is byte-for-byte unchanged. temperature_scan propagates the flag.

Plumbing

transition_state=False threaded through run_thermo, orca_thermo, cclib_thermo, pyscf_thermo — the "import an externally-computed structure" engines, since a DFTB+/xtb geometry optimization is a minimizer and can't itself land on a saddle point.

New: ThermoScreening.thermo.kinetics

  • eyring_rate_constant(reactants, ts, temperature, kappa=1.0) — TST rate constant k = kappa * (kB T/h) * exp(-ΔG‡/RT), using the same Thermo/(coefficient, Thermo) stoichiometry convention as reaction_free_energy.
  • wigner_tunneling_correction(imaginary_wavenumber, temperature) — a simple first-order tunneling estimate from the TS's imaginary frequency.

Verification

  • Manually verified k(ΔG‡=0) = kB*T/h (~6.212×10¹² s⁻¹ at 298.15 K, the exact textbook TST prefactor) and cross-checked a 20 kcal/mol barrier against the well-known "ΔG‡≈17.5 kcal/mol → k≈1 s⁻¹" rule of thumb — both match exactly.
  • New tests for the core TS logic (exclude-one-mode, wrong-count errors, temperature_scan propagation), kinetics.py (closed-form cross-checks, stoichiometry, kappa scaling), and one transition-state forwarding test per engine (run_thermo, orca_thermo, cclib_thermo, pyscf_thermo).
  • Full suite: 365 passed. Docs updated (usage + API reference). Full patch coverage (verified diff-line-by-line, not just file-level).

Closes #104

Thermo.run() previously raised on any imaginary vibrational frequency, so a
transition state (a first-order saddle point) could not be evaluated at
all. Add Thermo(..., transition_state=True): requires exactly one
imaginary mode among the kept frequencies, excludes it from the
vibrational partition function/entropy/energy/heat-capacity sums (the
reaction coordinate contributes no thermal vibrational term), and exposes
its wavenumber via Thermo.imaginary_mode_wavenumber(). Non-TS behavior
(the default) is unchanged; temperature_scan propagates the flag.

Thread transition_state=False through run_thermo, orca_thermo,
cclib_thermo and pyscf_thermo -- the "import an externally-computed
structure" engines, since a DFTB+/xtb geometry optimization is a
minimizer and cannot land on a saddle point.

Add ThermoScreening.thermo.kinetics:
- eyring_rate_constant(reactants, ts, temperature, kappa=1.0): TST rate
  constant from the activation free energy, using the same
  Thermo/(coefficient, Thermo) stoichiometry convention as
  reaction_free_energy.
- wigner_tunneling_correction(imaginary_wavenumber, temperature): a simple
  first-order tunneling estimate from the TS's imaginary frequency.

Closes #104
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.25%. Comparing base (88f3db1) to head (3fdf181).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #105      +/-   ##
==========================================
+ Coverage   97.22%   97.25%   +0.03%     
==========================================
  Files          30       31       +1     
  Lines        1872     1895      +23     
==========================================
+ Hits         1820     1843      +23     
  Misses         52       52              
Flag Coverage Δ
unittests 97.25% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@galjos
galjos merged commit 3e3307a into main Jul 8, 2026
5 checks passed
@galjos
galjos deleted the transition-state-eyring branch July 8, 2026 06:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transition-state thermochemistry and Eyring rate constants

1 participant