Skip to content

NonlinearSolveAlg(TrustRegion) + W-reuse: displacement-based ndz declares convergence on rejected TR steps → silently wrong solutions #3817

Description

@ChrisRackauckas-Claude

Found while investigating the master nlstep_tests.jl FBDF+NSA(TrustRegion) order failures (see #3807 discussion; the order-test failure itself is fixed separately).

Symptom

Fixed-dt FBDF + NonlinearSolveAlg(TrustRegion()) on Robertson (analytic jac, plain W-reuse path, no MTK nlstep) produces a final-state error of 4.741e-2, constant across dt = 2^-15 … 2^-18 — a dt-independent error floor, i.e. silently wrong results with Success retcodes. Stats show exactly 1 inner iteration and 1 f-eval per step.

Mechanism

compute_step! for NonlinearSolveAlg computes the convergence norm from the displacement: ndz = internalnorm(calculate_residuals(z .- nlcache.u, ...)) (newton.jl, from #3693). When TrustRegion rejects or truncates its internal step, nlcache.u barely moves, so ndz ≈ 0 — and the iter-1 η-convergence shortcut (iter == 1 && ndz < 1e-5, plus the first-iter trust gate enabled for cache.W !== nothing in nlsolve.jl) declares the stage converged with essentially no correction applied. A rejected globalization step reads as "converged" to the outer loop.

Two related consequences observed with the same mechanism:

  • The θ≈1 stall detection (eps_around_one branch in nlsolve.jl) misfires for globalized inner solvers: a rejected TR step leaves fu unchanged → θ = 1 exactly → premature Divergence (after 2 iterations) or premature convergence depending on ndz.
  • On a freshly built MTK nlstep problem, FBDF + NSA(TrustRegion) at dt=2^-15 aborts at step 0 with ConvergenceFailure after 2 inner iterations via that θ≈1 path (test files only pass because earlier testsets warm the shared nlprob; see also the companion NonlinearSolve.jl issue about reinit! resetting the trust radius to its build-time value).

Proposed fix direction

Outer convergence must not be declared from displacement-ndz when the inner solver did not actually accept a step / make progress: consult the inner cache (descent success / step acceptance / retcode) before treating a small ndz as convergence — or, longer-term, drive NonlinearSolveAlg inner solvers by their own residual-based termination instead of NLNewton's θ/η heuristics, which assume a plain (modified-)Newton contraction.

Repro scripts from the investigation are available; error table:

dt final-state l∞ error (FBDF+NSA(TrustRegion), fixed dt)
2^-15 4.741e-2
2^-16 4.741e-2
2^-17 4.741e-2
2^-18 4.741e-2

(For comparison, FBDF+NSA(NewtonRaphson) and FBDF+NLNewton halve cleanly.)

🤖 Filed by an agent after local reproduction on master 72706ab, Julia 1.12.6, NonlinearSolve 4.20.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions