Geometry optimization in PySCF, by the diff
Quantum Chemistry
A single-point energy tells you what one fixed shape costs. Geometry optimization answers the question a chemist actually cares about: what shape does the molecule adopt? The route there is short — compute the forces on the nuclei, then walk downhill until they vanish — and in PySCF it's a handful of one-line additions on top of the basics. As before, every program runs and every number below is what PySCF actually printed.
The chain: a single point at a deliberately-bad guess → the gradient
(forces) → optimize() → confirm the minimum → the effect of
the level of theory. Step with the arrows; hover a marked line for its
rationale.
from pyscf import gto, scf mol = gto.M( atom="O 0 0 0; H 0 -0.90 0.70; H 0 0.90 0.70", basis="sto-3g", ) mf = scf.RHF(mol) e = mf.kernel() print(f"E = {e:.6f} Ha")E = -74.925328 Ha
Everything follows from the gradient
Three things to take from the diffs, all visible in the output panels:
- A geometry is optimized exactly when the gradient is zero
(steps 2 vs 4). Same calculation, before and after:
max|grad|falls from 0.122 to 0.000014 Ha/bohr. The gradient is the force; no force means no incentive to move; that's the minimum. The optimizer just chases the gradient to zero. - Optimization returns a new molecule, the energy drops
(step 3). −74.925 → −74.966 Ha as the stretched 1.14 Å guess
relaxes to 0.989 Å. You always re-attach a method to the optimized
Moleto read properties at the new geometry. - The minimum lives on the surface you chose (step 5). RHF/sto-3g bottoms out at 0.989 Å / 100.0°; B3LYP/cc-pVDZ at 0.969 Å / 102.7°, against experiment's 0.957 Å / 104.5°. Optimization is faithful to the surface; whether the surface is faithful to reality is a separate choice.
As a citeable, falsifiable claim: at a converged geometry optimum the maximum nuclear gradient is zero (to the convergence threshold), because the optimum is where the forces vanish. The experiment is steps 2 and 4; it would be falsified by a structure the optimizer reports as converged while a fresh gradient comes back large — which would mean a broken convergence test, not a real minimum.
Read next
- PySCF basics, by the diff — the single-point energies this chain builds on.
- Hartree-Fock — what the energy and its gradient come from.
- Ownership in C++, by the diff — the same differential-learning format in another domain.