Commit 7d706b3
committed
Clear the TS energy cache and checkfile when switching to the next TS guess
`switch_ts()` discards a TS guess and re-optimizes the next one, and it already
invalidates every piece of state the new geometry makes meaningless: the chosen
guess, the running jobs, the output paths and job_types (via
`delete_all_species_jobs()`), the copied `freq.out`, the TS checks dict, and the
rotors dict. It did not invalidate the energy data cached on the TS species
itself, nor the checkfile pointing at the abandoned guess's wavefunction.
All three energy fields are read straight off the species object, which is
exactly where `delete_all_species_jobs()` cannot reach:
* `e0` decides the E0 check. `compute_rxn_e0()` skips any species that already
carries an `e0`, and `ARCReaction.copy_e0_values()` only fills an empty one, so
the TS E0 was computed once, for the first guess, and every later guess was
judged against it. `e0` is also written to the restart file, so the stale value
survived a restart. Measured on a benchmark run, two guesses whose own E0 was
2.51 kJ/mol above the reactants were rejected on the first guess's
121.88 kJ/mol.
* `e_elect` decides a second gate by the same mechanism, and this is the
strongest reason to clear it. `check_rxn_e_elect()` — the check that runs when
E0 cannot be determined — reads `reaction.ts_species.e_elect` directly off the
species object, so a retained value silently answered that gate for the new
guess too.
* `freqs` is the primary source of the reported imaginary frequency.
`arc/output.py::_get_ts_imag_freq()` takes the most negative entry of
`spc.freqs` and only falls back to the chosen guess's `imaginary_freqs` when
`spc.freqs` is empty, so without this clear the run reports the abandoned
guess's imaginary frequency for the accepted TS.
Caching is correct for the reactants and the products, whose geometries do not
change here; it is wrong for the TS, whose geometry changes on every switch.
Until the new sp and freq jobs replace them, `e_elect` and `freqs` are also saved
to the restart file and reported in output.yml as if they belonged to the new
guess.
`checkfile` is the same defect class, reached through the route builder rather
than through a check. `run_job()` reads the checkfile off the species and hands
it to every job it spawns, and `GaussianAdapter` resolves the SCF initial guess
for any polyatomic species as ` guess=read` when the checkfile exists and
` guess=mix` when it does not — the fallback is not TS-specific. Left uncleared,
the new guess is seeded from the discarded geometry's converged orbitals instead
of the symmetry-broken default that a fresh species gets. That branch is right
when the checkfile is current; what is wrong is the stale pointer.
Deliberately left alone:
* `opt_level` — a level of theory, not a geometry-derived quantity.
* `external_symmetry` and `optical_isomers` — also sticky, but only ever written
onto the scheduler's species by the final Arkane rate/thermo run, after all
switching is over. Excluding them is safe only because `compute_rxn_e0()`
operates on `reaction.copy()`, which round-trips through `as_dict`/`from_dict`
— a genuine deep copy — and merges only `e0` back onto the live reaction; were
`copy()` ever to become shallow, this exclusion would become a bug of the same
shape as the ones fixed here.
* `t1` — a wavefunction diagnostic that no check reads and that output.yml does
not carry.
* `active` — considered, and deliberately not cleared. It has the identical
sticky shape: set only when it is `None`, persisted to the restart file, and
consumed by the Orca and Molpro CASSCF route builders. Whether an active space
is guess-dependent is a chemistry question rather than a caching one, so it is
left for a deliberate decision.
The regression test asserts the invalidation of all four fields and, for `e0`,
its consequence: that an E0 computed for the new guess is adopted by
`copy_e0_values()` rather than masked by the old one.1 parent 79540b6 commit 7d706b3
2 files changed
Lines changed: 81 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2989 | 2989 | | |
2990 | 2990 | | |
2991 | 2991 | | |
| 2992 | + | |
| 2993 | + | |
| 2994 | + | |
| 2995 | + | |
2992 | 2996 | | |
2993 | 2997 | | |
2994 | 2998 | | |
| |||
2999 | 3003 | | |
3000 | 3004 | | |
3001 | 3005 | | |
| 3006 | + | |
| 3007 | + | |
| 3008 | + | |
| 3009 | + | |
3002 | 3010 | | |
3003 | 3011 | | |
3004 | 3012 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1214 | 1214 | | |
1215 | 1215 | | |
1216 | 1216 | | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
| 1278 | + | |
| 1279 | + | |
| 1280 | + | |
| 1281 | + | |
| 1282 | + | |
| 1283 | + | |
| 1284 | + | |
| 1285 | + | |
| 1286 | + | |
| 1287 | + | |
| 1288 | + | |
| 1289 | + | |
1217 | 1290 | | |
1218 | 1291 | | |
1219 | 1292 | | |
| |||
0 commit comments