Repository navigation
feat(saddle): follow the intrinsic reaction coordinate after a saddle - #868
Merged
Merged
Conversation
A converged saddle does not say which minima it joins. Process search runs two minimizations from points displaced along the mode. Either minimization can slide into a minimum the saddle does not connect. rgsaddle exports an intrinsic reaction coordinate (IRC) session from C application binary interface (ABI) minor 14. The continuous integration (CI) pin 06c55c5 is minor 18. irc_after in [Saddle Search] follows that IRC from a converged saddle with a negative eigenvalue. It walks both directions over the free atoms and relaxes both ends with the eOn minimizer. It writes seven entries in results.dat and the files irc.con, irc.dat, irc_min1.con and irc_min2.con. Each branch gets its own rgsaddle session. A session halves its step after every rejected trial and keeps the shorter step through rgsaddle_irc_set_direction. The rgsaddle crate stayed at 0.2.2 from C ABI minor 5 to 18. For that reason the build reads RGSADDLE_ABI_MINOR and the ABI version of the loaded library, not the pkg-config version. A build without the session refuses irc_after before the search starts. The step defaults to 0.1 amu^1/2 Angstroms, where amu is the atomic mass unit. The force threshold defaults to 0.05 electronvolts/Angstrom. Sella's IRC stops its path there, and so does the rgsaddle session. The [Optimizer] tolerance that relaxes the ends stays separate. eOn passes the threshold to the session and has it compare the largest atomic force. A branch stops at a minimum when rgsaddle reports one. rgsaddle reports a minimum only after the first step and at a force at or below that threshold, so eOn adds no test of its own. On the Morse Pt saddle of the systems tutorials the pinned rgsaddle stops both branches at the defaults after a few steps. The ends lie 0.0077 and 0.0116 Angstroms from the saddle, where the forces are already under 0.05. eOn counts both branches, and the minimizer relaxes them into the two minima. On the 7- and 13-atom Lennard-Jones clusters the path and the ends take 259 and 464 force calls at 0.05, and 259 and 492 at 0.01. At step 0.5 and threshold 0.05 the 13-atom branch along the mode stops after 144 steps. Its end lies 0.49 step lengths from the saddle in mass-weighted distance. The option is off by default. With it off the client reads four more keys and writes the same bytes as before.
The schema documents the four irc keys of [Saddle Search] with their units, defaults, outputs and build requirement. irc_converged_force defaults to 0.05, the path stop of the intrinsic reaction coordinate (IRC) in Sella. Its note says that a branch ends at a minimum when rgsaddle reports one. It also says that the rgsaddle pinned by continuous integration can stop a branch beside the saddle. The generated JavaScript Object Notation (JSON) Schema follows.
The 13-atom Lennard-Jones (LJ13) test refines the saddle of a nudged elastic band (NEB) and follows the intrinsic reaction coordinate (IRC) both ways. It checks that each relaxed end matches exactly one of the two NEB minima. It also checks that energies fall monotonically from the saddle. Each branch must reach the minimum flag at the default threshold and end within 1e-3 electronvolts of its relaxed end. With one session shared by both branches the second branch ends 0.10 or 0.14 electronvolts above its end, at thresholds 0.05 and 0.01. The job tests check three things. With irc_after off, setting the irc keys leaves the bytes of every returned file unchanged. A build without the IRC refuses the option. On the Morse Pt saddle the IRC leaves saddle.con, mode.dat and the saddle force calls unchanged. There it relaxes into the reactant and writes one irc.con frame per irc.dat row.
With rgsaddle, eOn runs min_mode_method = dimer through XtsciMinMode whatever [Dimer] improved says. XtsciMinMode set rotation_tol to torque_min, 0.1 by default. eOn's own improved dimer has no torque stop. Its rotation ends on converged_angle or after rotations_max. The rgsaddle session ends a rotation once the rotational force is at or below rotation_tol. From 0.3.0 rgsaddle also reads a rotation_tol of 1e-4 or more as the classic torque window. Once the rotational force is below 1, that window stops a rotation after its first step. So the default improved request got a classic dimer. The improved dimer now passes rotation_tol = 0. The classic dimer and Lanczos still pass torque_min. It needs no rgsaddle change and no new C application binary interface (ABI) minor. Every minor that eOn reads has rotation_tol, so the change applies to the continuous integration (CI) pin 06c55c5 and to the releases 0.3.0 to 0.3.2 alike. The runs cover five saddle searches against the CI pin. They are the Morse Pt saddle, the 7- and 13-atom Lennard-Jones clusters (LJ7 and LJ13), the Pt island of examples/akmc-pt and the how-to input. Four of the five saddles move, with energies equal to six decimals. The Morse Pt search takes 46 force calls instead of 38, LJ7 750 instead of 748, the island 486 instead of 471 and the how-to input 39 instead of 32. Their eigenvalues go from -1.013461, -9.880619, -0.612079 and -1.010681 to -1.010819, -9.880954, -0.613662 and -1.010010. LJ13 keeps its saddle.con and mode.dat. Each moved saddle lies within 1e-4 Angstroms of the old one. Against rgsaddle main fe6bed89 the five searches give the same saddle.con and mode.dat as against the pin. Develop against main ends the island search at another saddle, at -1774.804074 electronvolts (eV) after 449 force calls. With this change it ends at -1775.190088 eV, as with the pin. Two job tests bound the Morse Pt force calls by the Subversion (SVN) reference, 39 for the saddle search and 69 for the process search. With rgsaddle these searches now take 47 and 75, and the bounds under WITH_RGSADDLE move to those counts. The rgsaddle eigenvalue of the saddle search test moves to -1.010819. eOn's own dimers do not change, and their bounds stay.
The how-to runs irc_after, which follows the intrinsic reaction coordinate (IRC), on the Morse Pt saddle of the systems tutorials. It shows the exact config, copy commands from the checkout root and the output of the run. A table of six runs shows how step size and force threshold trade path detail for force calls. Four of them trace both branches with the pinned rgsaddle. The config sets step 0.5 and threshold 0.01, the cheapest of those four. The page says which output comes from the committed run and which from the other runs. At the default threshold of 0.05, one branch stops next to the saddle at step 0.1 and at step 0.5. The pinned rgsaddle reports a minimum there, so eOn counts the branch. The figure comes from the run, and its irc.dat, results.dat and plotting script sit next to it. The user guide gains a short IRC section with references. It credits Sella's QuasiNewtonIRC for the step on the sphere. It also says that a branch ends where rgsaddle reports a minimum. A towncrier fragment records the new keys and their defaults.
eOn Documentation PreviewDownload: documentation.zip Unzip and open |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Commit cf269a1 added four irc keys to the [Saddle Search] schema. Without them in eon/config.yaml, test_schema_matches_config_yaml failed. The keys now appear in config.yaml with the defaults of the schema. Those are off, 0.1, 0.05 and 1000, the same as in the client options. Their comments repeat the descriptions in the schema.
HaoZeke
force-pushed
the
feat/rgsaddle-irc
branch
from
November 2, 2026 18:32
701dea5 to
dff3482
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A converged saddle does not say which two minima it joins.
Process search checks it with two minimizations displaced along the
mode.
These can slide into a minimum the saddle does not connect.
irc_after = truein[Saddle Search]follows the intrinsic reactioncoordinate (IRC) with rgsaddle.
The path goes downhill from the saddle in both directions, and the eOn
minimizer relaxes both ends.
Six commits on develop
630ccad2add the path, the relaxed ends, adimer fix and the config.yaml keys, 29 files, +1762/-10.
A diff against
mainalso shows develop's own commits that are not onmainyet.2f464bd1follows the intrinsic reaction coordinate, in 8 files with+430.
cf269a18describes the saddle irc keys in the schema, in 3 files with+67.
417c404fcovers the irc_after ends and default bytes, in 3 files with+235.
bf0f5ae4drops the torque stop from the improved rgsaddle dimer, in 6files with +35/-10.
f36b286dadds a how-to for the reaction path after a saddle, in 11files with +970.
dff34824adds the saddle irc keys to config.yaml, in 1 file with +25.Rebase onto develop
The series now sits on the develop commit that refuses
prfo_refinebefore the first force call.
The rebase had conflicts in two files.
SaddleSearchJob.cppincludes bothPrfoRefine.handXtsciIrc.h.Its
runstill callsrequirePrfoRefinefor a min-mode search.runPreparedkeeps the IRC check as it was.In
client/meson.build,test_prfo_refinestays outside the rgsaddleblock, where develop moved it.
test_rgsaddle_ircstays inside that block.No commit became empty.
The sixth commit adds the four irc keys to
eon/config.yaml.The schema drift test compares that file with the schema, and it failed
from the second commit on.
Keys and outputs
The keys are
irc_after,irc_step_size,irc_converged_forceandirc_max_steps.The first is off by default, and the last defaults to 1000.
The step defaults to 0.1 amu^1/2 Angstroms, where amu is the atomic mass
unit.
The force threshold defaults to 0.05
electronvolts/Angstrom (eV/Angstrom).
Sella's IRC stops its path there, and so does the rgsaddle session.
A branch ends at a minimum when rgsaddle reports one.
rgsaddle does so only after the first step and where the largest atomic
force is at or below the threshold.
The job writes
irc.con,irc.dat,irc_min1.conandirc_min2.con,plus seven
results.datentries.With the option off, a saddle search writes the same files as before.
The IRC needs rgsaddle C application binary interface (ABI) minor 14 or
newer.
Both the build and the library loaded at run time must meet it.
The rgsaddle crate stayed at 0.2.2 from minor 5 to 18.
So eOn checks
RGSADDLE_ABI_MINORand the ABI version the libraryreports, not the pkg-config version.
Other builds refuse
irc_afterbefore the saddle search starts.Dimer rotation
The fourth commit fixes the dimer search itself, and it would apply
without the IRC.
With rgsaddle, eOn hands both of its dimers to
XtsciMinMode.That class passed
[Dimer] torque_min, 0.1 by default, to rgsaddle asrotation_tol.rgsaddle 0.3.0 and newer read a
rotation_tolof 1e-4 or more as theclassic torque window.
Once the rotational force is below 1, that window stops a rotation after
its first step.
So a request for the improved dimer ran a classic one.
On the Pt island of
examples/akmc-pt, develop against rgsaddlemainfe6bed89ends at another saddle.It stops at -1774.804074 eV after 449 force calls, against -1775.190088
eV on the pin.
The commit passes
rotation_tol = 0when[Dimer] improvedis true.Lanczos keeps
torque_min, since it readsrotation_tolas itsresidual stop.
The improved dimer then rotates until
converged_angleorrotations_max, as eOn's ownImprovedDimerdoes.It needs no ABI change, so it applies to the pin
06c55c5and to thereleases 0.3.0 to 0.3.2.
With it, the pin and
mainfind the same saddle on all five inputsbelow, the island included.
Four of the five saddles that the pinned rgsaddle finds move.
LJ7 and LJ13 are the 7- and 13-atom Lennard-Jones clusters.
The numbers below compare develop and this series, both against the pin.
For the Morse Pt adatom the saddle energy is -1462.008706 eV, the force
calls go from 38 to 46, and the eigenvalue goes from -1.013461 to
-1.010819.
For LJ7 the saddle energy is -15.283414 eV, the force calls go from 748
to 750, and the eigenvalue goes from -9.880619 to -9.880954.
For the Pt island the saddle energy is -1775.190088 eV, the force calls
go from 471 to 486, and the eigenvalue goes from -0.612079 to -0.613662.
For the how-to input the saddle energy is -1462.008706 eV, the force
calls go from 32 to 39, and the eigenvalue goes from -1.010681 to
-1.010010.
The energies agree to six decimals, and each moved saddle lies within
1e-4 Angstroms of develop's.
LJ13 keeps its saddle and its 8 force calls.
Two job tests bound the force calls of the Morse Pt search.
Under
WITH_RGSADDLEthe bounds rise from 39 to 47 and from 69 to 75,and the expected eigenvalue becomes -1.010819.
The bounds without rgsaddle stay as they were.
Once rgsaddle releases C ABI minor 26, a separate follow-up will set the
torque window through
rgsaddle_minmode_set_torque_window.The pinned rgsaddle
The rgsaddle that continuous integration (CI) pins,
06c55c5, canreport a minimum beside the saddle.
On the Morse Pt saddle at the defaults it stops the branch along the
mode 0.0152 Angstroms from the saddle.
The largest force there is 0.017 eV/Angstrom, already below 0.05.
It can also run a branch to
irc_max_stepswith its force below thethreshold.
LJ13 at step 0.5 shows this.
The LJ13 step-0.5 numbers come from runs on an earlier revision of this
series.
Its eOn code differs from this tip only in rebases, one local variable
name, and comment, docs and config.yaml text.
The how-to shows the first case.
It uses step 0.5 and threshold 0.01, the cheapest of its runs that trace
both branches with the pin.
The schema note for
irc_converged_forcesays so too.The fix is one rgsaddle commit on
mainfe6bed89, not yet opened as apull request.
It stops a branch on the force and on the curvature along the launch
mode.
eOn needs no change for it, because eOn reads only the converged status.
With it, the LJ13 step-0.5 case reaches the minimum on both branches at
both thresholds.
On the Pt island the pin stops both branches about one step from the
saddle.
The relaxed ends still reach the right minima there.
The island path with the fix runs slowly, a separate known issue in the
rgsaddle IRC stop.
The LJ13 and island sentences on the fix also come from runs on that
earlier revision.
Tests
On the tip,
meson test --suite eonpasses 77 tests against the pin and74 without rgsaddle.
test_prfo_refinenow runs in both builds, as on develop.Only the pinned build has
test_rgsaddle_band,test_rgsaddle_ircandtest_rgsaddle_neb.The Python tests give 789 passed and 17 skipped, with 206 subtests
passed.
The eon-schema tests give 56 passed and 1 failed,
test_published_tree_matches_generator.Develop
630ccad2fails it the same way.Its published
index.json,instanton.jsonandnudged-elastic-band.jsonlack the develop keystunnel_wall_pointsand
symmetrize.This series does not touch those keys, and its own irc keys match the
generator.
One nudged elastic band (NEB) test compares a band with Subversion (SVN)
reference data.
Against rgsaddle
mainthat test,NEB LJ matches SVN reference, failsits
status == 0check.Develop fails it the same way against
main, and passes it against thepin.
It is the only failure against rgsaddle 0.3.2, on the tip and on develop
alike.
The failure comes from rgsaddle
e253dab, which changed theclimbing-image rule of the band.
A pending rgsaddle change, not yet on
main, keeps the climb off anendpoint that slopes into the band.
This series does not touch the band.
test_rgsaddle_ircfollows the IRC from the LJ13 saddle that the NEBtest refines.
It checks that each relaxed end matches one of the two NEB minima.
The
[irc]job cases check three things.With
irc_afteroff, setting the irc keys leaves every returned fileunchanged.
A build without the IRC refuses the option.
On the Morse Pt saddle the IRC leaves
saddle.con,mode.datand thesaddle force calls unchanged.
The two job cases with raised bounds pass with and without rgsaddle.
Docs
docs/source/tutorials/systems/irc_after_saddle.mdis a how-to on theMorse Pt saddle.
Its log line,
results.datlines and figure come from the run indata/irc_pt/.A table of six runs shows how step size and threshold trade path detail
for force calls.
A cost section compares the IRC with the displaced minimizations on four
systems.
These are the Morse Pt adatom saddle, LJ7, LJ13 and the Pt island of
examples/akmc-pt.On all four the IRC reached the same minima and used more force calls.
On the island, with 175 free atoms, the path took about 120 s for 16
force calls.
The user guide gains a short IRC section, and a towncrier fragment
records the keys.
docs/source/user_guide/optimizer.mdand a second fragment record thedimer change.