Skip to content

NonlinearSolveAlg: let inner solver refresh J when no W is reused (fixes master nlstep order failures)#3818

Draft
ChrisRackauckas-Claude wants to merge 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:nsa-recompute-jacobian-wnothing
Draft

NonlinearSolveAlg: let inner solver refresh J when no W is reused (fixes master nlstep order failures)#3818
ChrisRackauckas-Claude wants to merge 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:nsa-recompute-jacobian-wnothing

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Please ignore until reviewed by @ChrisRackauckas. Draft opened by an agent.

Fixes two failing tests on master

test/modelingtoolkit/nlstep_tests.jl currently fails on master (17 pass / 2 fail / 6 broken): the FBDF + NSA(TrustRegion) Robertson order assertions at lines 60 and 116 measure order 0.6152 against bounds |𝒪est−1| < 0.3 / 0.35. (#3807 read this as "order 1.38" — it's 1 + 0.3848 in the test output; the order collapsed below 1.)

Root cause

#3703 changed both compute_step! methods from

recompute_jacobian = cache.W === nothing || (nlsolver.iter == 1 && cache.new_W)

to

recompute_jacobian = nlsolver.iter == 1 && (cache.W === nothing || cache.new_W)

which freezes the inner NonlinearSolve Jacobian after outer iteration 1 on the paths without a reusable W (MTK nlstep, DAE, OOP). The inner solve silently degrades to modified Newton while the outer η·ndz < κ termination keeps its calibration, so every step carries a dt-independent unconverged remainder. Measured l∞ errors over dts = 2^-15…2^-18: master [2.22e-7, 1.12e-7, 5.60e-8, 6.18e-8] (error stops halving, then rises); with this fix […, 1.38e-7, 5.60e-8, 2.80e-8] (clean halving). Warmed TrustRegion and NewtonRaphson give bit-identical trajectories — not TR-specific, and consistent with the principle that a converged inner solve must not change the ODE solution.

Fix

Restore the pre-#3703 condition: W === nothing paths let the inner solver refresh J every outer iteration; the W-reuse (modified-Newton) path is untouched — with a reused W the inner Jacobian is the ODE-side W by construction, so refreshing beyond iter 1 remains pointless there.

Verification (local)

  • A/B on master: this exact change turns nlstep_tests.jl from 17 pass / 2 fail into 19 pass / 0 fail, with orders 1.2576 and 1.3035 back inside their bounds.
  • newton_tests.jl + linear_nonlinear_tests.jl pass against this branch.

Related findings from the same investigation (separate issues)

🤖 Generated with Claude Code

SciML#3703 changed compute_step! from
    recompute_jacobian = cache.W === nothing || (iter == 1 && cache.new_W)
to
    recompute_jacobian = iter == 1 && (cache.W === nothing || cache.new_W)
which freezes the inner NonlinearSolve Jacobian after the first outer
iteration on the paths without a reusable W (MTK nlstep, DAE, OOP). The inner
solve silently degrades to modified Newton while the outer η·ndz < κ
termination keeps its full-Newton calibration, so each step carries an
unconverged remainder independent of dt. Observable: the FBDF + NSA
convergence order on the MTK Robertson nlstep tests collapsed from ~1.26/1.30
to 0.615 (l∞ error stops halving at dt = 2^-18), failing both order
assertions on master.

Restore the pre-SciML#3703 condition for the W === nothing paths. The W-reuse
(modified-Newton) path is unchanged: with a reused W the inner Jacobian is
the ODE-side W by construction, so per-iteration refreshes remain pointless
there.

A/B on master: reverting only this condition turns
test/modelingtoolkit/nlstep_tests.jl from 17 pass / 2 fail to 19 pass /
0 fail, with orders 1.2576 (< 0.3 bound) and 1.3035 (< 0.35 bound), and
restores clean error halving under dt refinement.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor Author

CI triage: the failing lanes here are master-baseline, not from this change — StochasticDiffEq QA/downgrade + GPU lanes fail on all concurrent PRs including the 2-line #3816; the OrdinaryDiffEqNonlinearSolve Core lane failure is the pre-existing Dependent Mass Matrix Tests error (mass_matrix_tests.jl:283, OOP NLNewton + non-concrete operator W, 221 pass/2 error/4 broken — the limitation #3796 documents), reproduced identically on unmodified master locally. The MTK nlstep lane failures are the two order-test failures that #3818 fixes.

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.

2 participants