NSA: gate iter-1 convergence on inner solver retcode (#3817) - #3893
Merged
ChrisRackauckas merged 1 commit intoJul 31, 2026
Merged
Conversation
Member
|
don't stack this |
singhharsh1708
force-pushed
the
nsa-trustregion-ndz-convergence-3817
branch
from
July 13, 2026 17:30
4f63a59 to
eae4139
Compare
Contributor
Author
done. |
singhharsh1708
force-pushed
the
nsa-trustregion-ndz-convergence-3817
branch
4 times, most recently
from
July 18, 2026 07:33
8628e6d to
7718a44
Compare
singhharsh1708
force-pushed
the
nsa-trustregion-ndz-convergence-3817
branch
from
July 21, 2026 14:31
7718a44 to
9ae749a
Compare
A globalized inner solver (TrustRegion and friends) can reject its trial step: `step!` returns with the iterate exactly unmoved and the cache not terminated, having only shrunk its trust region for the next attempt. The outer convergence test read that zero displacement as a perfect solve - `ndz < 1e-5` on the first iteration, `eta*ndz = 0 < kappa` on later ones - and accepted the stage with no correction applied. SciML#4020 surfaces inner caches that *terminated* unsuccessfully; a rejected step terminates nothing, so it slipped through both branches. `nlsolve!` now skips the convergence and divergence bookkeeping for an iteration whose `NonlinearSolveAlg` step left the iterate unmoved without terminating: no new iterate exists to judge, and a zero `ndz` would also poison the next iteration's theta. The inner solver retries with its shrunken radius; if it never moves, the loop runs out and the step is rejected as unconverged. A cache that terminated at zero displacement converged exactly (failures already return `Inf` from `compute_step!`), so that case still counts as convergence. ROBER with FBDF and a TrustRegion inner solver: - fixed dt = 1.0 (transient unresolvable): was ReturnCode.Success with the state frozen at u0; now ConvergenceFailure, matching NewtonRaphson. - adaptive, default tolerances: relerr 1.7e-2 -> 1.8e-5 (NLNewton 2.1e-5, NSA NewtonRaphson 4.0e-6). Same for RobustMultiNewton. - adaptive, reltol=1e-8: relerr 2.4e-8 -> 1.6e-9 (NewtonRaphson 1.3e-9). NewtonRaphson inner solves are unchanged step-for-step (their iterates always move or terminate), and NLNewton never enters the predicate.
singhharsh1708
force-pushed
the
nsa-trustregion-ndz-convergence-3817
branch
from
July 30, 2026 20:26
9ae749a to
8d994e3
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.
Fixes #3817.
A globalized inner solver like TrustRegion can reject its trial step:
step!returns with the iterate exactly unmoved and the cache not terminated, having only shrunk its trust region for the next attempt. The outer Newton loop measures displacement, so that rejected step reads asndz == 0— which both convergence tests treat as a perfect solve (ndz < 1e-5on the first iteration,eta*ndz = 0 < kappaafterwards). The stage gets accepted with no correction applied. On fixed-dt FBDF + TrustRegion Robertson, master returns Success with the state frozen atu0.#4020 already gates on a terminated inner cache; the case it cannot see is rejected-but-not-terminated. This PR adds exactly that discriminator, for
NLSolver{<:NonlinearSolveAlg}only:When it fires,
nlsolve!skips the convergence/divergence bookkeeping for that iteration (a zerondzwould also poison the next iteration's theta) and lets the inner solver retry with its shrunken region. If it never moves, the loop exhausts and the step is rejected as unconverged. A cache that terminated at zero displacement either converged exactly or already failed (failures becomeInfincompute_step!), so termination is the right discriminator between "at the root" and "undecided".NLNewtonand the other legacy solvers hit thefalsefallback and are untouched.Measured on Robertson
(0, 1e5)against an FBDF reltol=1e-12 reference:u0-> ConvergenceFailure (matches what NewtonRaphson reports there)This replaces the earlier iter-1 retcode gate from the first version of this PR, which #4020 made partially redundant. The testset that asserted a 1e-4 error bound the old gate could not meet now measures 1.6e-9 and asserts honestly; a second testset covers the fixed-dt frozen case. Also drops a non-public SimpleNonlinearSolve import the QA lane flagged.
AI Disclosure
Claude assisted with this work.