Transition-State Search (Berny Optimizer)
The Berny optimizer supports transition-state (TS) searches via the TS task
token or by setting TransitionState true in the OPT section. The implementation
uses Partitioned Rational Function Optimization (P-RFO) to locate first-order
saddle points.
See also: the GeomeTRIC Optimizer provides an alternative restricted-step partitioned RFO (RS-P-RFO) TS engine in translation-rotation internal coordinates. Select it with
Algorithm geometricplusTransitionState true.
Theory
A transition state is a first-order saddle point on the potential energy surface (PES) — a stationary point with exactly one negative eigenvalue of the Hessian matrix. The negative eigenvalue corresponds to the reaction coordinate (the direction connecting reactant and product).
The P-RFO method partitions the Hessian eigenvectors into two subspaces:
- TS mode (mode 1, lowest eigenvalue): maximize energy along this direction
- Minimisation modes (all other modes): minimize energy along these directions
The step is computed as:
where the coefficients are:
The RFO roots are:
Implementation Details
The TS search in the Berny optimizer includes:
-
Initial TS Hessian (
init_ts_hessian):- When no analytical Hessian is provided, the Lindh model Hessian is used
- The softest IC mode (lowest eigenvalue) is set to −0.2 a.u.
- This ensures P-RFO has a well-defined ascent direction from the first step
-
P-RFO Step (
prfo_stepinstep_engine.rs):- Eigendecomposes the Hessian:
- Sorts eigenvalues/eigenvectors by ascending eigenvalue
- Projects gradient onto eigenvectors:
- Computes RFO roots for TS mode (upper) and minimisation modes (lower)
- Forms step in eigenbasis, transforms back to IC space
- Scales to trust radius if step is too large
-
Hessian Eigenvalue Check (
ensure_correct_negative_eigenvalues):- Runs every 3 cycles during TS optimization
- Checks that the Hessian has exactly 1 negative eigenvalue
- If too few: flips smallest positive eigenvalues to −0.2 a.u.
- If too many: flips least-negative eigenvalues to +0.2 a.u.
-
Bofill Hessian Update (
update_hessian_bofill):- Blends PSB (Powell-Symmetric-Broyden) and MS (Murtagh-Sargent) updates
- Weight:
- When : pure PSB (preserves curvature info)
- When : pure MS (rank-1 correction)
- Automatically adapts based on local surface curvature
-
TS-Specific Trust Radius:
- Initial trust: 0.01 Å (vs 0.3 Å for minima)
- Maximum trust: 0.03 Å (vs 0.3 Å for minima)
- Conservative values prevent large steps near saddle points
-
TS-Specific DIIS Weighting:
- Reaction coordinate gradient component scaled by factor 2.0
- Minimum subspace size: 3 points (vs 2 for minima)
- Cosine threshold: 0.5 (vs 0.0 for minima)
-
TS-Specific Output:
- Prints Hessian negative eigenvalue count at each cycle
- Header shows "Transition-State Optimization (Berny IC-space, P-RFO)"
TS Search Algorithm Flow
berny_optimize_ic_with_controls()
│
├─ Set TS-specific trust defaults (0.01, 0.03)
│
├─ Initialize Hessian
│ ├─ If cart_hessian provided: use it
│ └─ Else: guess_hessian_lindh()
│ └─ If transition_state: init_ts_hessian(h, 1, -0.2)
│
└─ Main loop
│
├─ Compute IC gradient
│
├─ TS diagnostics (print negative eigenvalue count)
│
├─ Select step method
│ ├─ If transition_state: prfo_step()
│ └─ Else: trm_step() or gediis()
│
├─ IC → Cartesian back-transform
│
├─ Evaluate energy and gradient
│
├─ Convergence check
│
├─ Trust-radius update
│
├─ Hessian update
│ ├─ If transition_state: update_hessian_bofill()
│ └─ Else: update_hessian_msp()
│
├─ Periodic eigenvalue check (every 3 cycles)
│ └─ ensure_correct_negative_eigenvalues(h, 1, 0.2)
│
└─ Accept step
Verification
A genuine TS shows exactly one imaginary frequency (printed as a negative value):
Frequencies (cm⁻¹): -1247.3 1652.1 3825.4
Verify with a subsequent FREQ job on the converged TS geometry.