Skip to content

fix(saddle): refuse prfo_refine before the first force call - #869

Merged
HaoZeke merged 2 commits into
TheochemUI:developfrom
HaoZeke:feat/rgsaddle-prfo-refine
Nov 2, 2026
Merged

HaoZeke merged 2 commits into
TheochemUI:developfrom
HaoZeke:feat/rgsaddle-prfo-refine

Conversation

@HaoZeke

@HaoZeke HaoZeke commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Pull request 867 added the opt-in partitioned rational function optimization (P-RFO) refinement through the rgsaddle Sella session.
Its checks of the rgsaddle library and of the prfo_refine_* values ran only after the search converged.
This change runs the same checks before the first force call, so a job that cannot refine stops at once.

  • A min-mode saddle search, a min-mode process search and a nudged elastic band (NEB) job call requirePrfoRefine at the start of run.
  • The MinModeSaddleSearch constructor calls it too, for other callers such as the Python bindings.
  • It throws std::runtime_error for a build without rgsaddle or a loaded library older than application binary interface (ABI) 1.15, and std::invalid_argument for a prfo_refine_force that is not positive or a prfo_refine_max_iterations below 1.
  • With prfo_refine off nothing is called, and every output is unchanged.

Measurements

All runs use the 13-atom Lennard-Jones (LJ13) test systems with the configurations of test_prfo_refine.
rgsaddle is the continuous integration (CI) pin, crate version 0.2.2 at ABI 1.18.
Counts are force calls before the job stopped, read from the potential registry.

Before this change, a client without rgsaddle spent 279 force calls on the dimer saddle search with prfo_refine = true.
It then reported termination reason 11, "Potential evaluation failed".
Its process search took 279 force calls and its NEB job 283 before each stopped on an unhandled exception.
A client with rgsaddle spent 821 force calls on the dimer saddle search with prfo_refine_force = 0.
It also reported termination reason 11.
That build took 821 force calls in the process search and 283 in the NEB job before the same unhandled exception.
After this change, all six jobs stop with zero force calls.

With valid keys the refinement is unchanged.
Before and after this change, the dimer run with prfo_refine_force = 1e-5 lowered the max-atom force of saddle.con from 3.7e-3 to 4.3e-9 eV/Angstrom, in 946 force calls against 821 for the search alone.
The NEB run refined the climbing image from 3.3e-3 to 6.6e-8 eV/Angstrom in 65 force calls, the curvature probe included.
saddle.con, mode.dat, neb.con, sp.con, sp_refined.con and results.dat apart from timings were the same before and after, with the keys on and off.

Tests

  • test_prfo_refine is now built in every configuration.
  • With rgsaddle it adds a case that runs the three jobs with prfo_refine_force = 0 and requires a refusal with zero force calls.
  • Without rgsaddle, the same three jobs run with prfo_refine = true and must make no force call, next to the existing case for the default path.
  • Built against the base, the new cases fail with the counts listed above.

Docs

  • The saddle search guide says where the refusal happens, in the how-to step and as a reference rule.
  • The prfo_refine description in the eon-schema model and the published schema say the same.
  • The P-RFO step also cites Banerjee et al. 1985, after the eOn papers on the searches it continues.
  • The entry for the 2025 Journal of Chemical Theory and Computation paper gains its volume, issue and pages from Crossref.
  • A newsfragment of type changed.

A min-mode saddle search, a min-mode process search and a nudged elastic
band (NEB) job now check prfo_refine before any force call.
They throw when the build has no rgsaddle, when the loaded rgsaddle
library reports an application binary interface (ABI) older than 1.15,
or when prfo_refine_force or prfo_refine_max_iterations is out of range.
The MinModeSaddleSearch constructor runs the same check for other
callers.
Before, the check ran only after a converged search.
A client without rgsaddle spent 279 force calls on the dimer search of
the 13-atom Lennard-Jones (LJ13) test cluster.
It then reported a potential evaluation failure.
The band of that cluster took 283 force calls before the job stopped.
Runs without prfo_refine are unchanged.
test_prfo_refine is now built without rgsaddle too, where it checks the
refusal.
The how-to and reference sections of the saddle search guide, the
eon-schema docstring and the published schema now say that a client that
cannot refine refuses the job before its first force call.
The partitioned rational function optimization (P-RFO) step also cites
Banerjee et al. 1985.
The 2025 Journal of Chemical Theory and Computation entry gains its
volume, issue and pages from Crossref.
@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
client/PrfoRefine.cpp 66.66% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@HaoZeke
HaoZeke merged commit 630ccad into TheochemUI:develop Nov 2, 2026
40 checks passed
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.

1 participant