Repository navigation
Default Newton-Krylov Auto warm starts to guarded Hegedüs - #4040
ChrisRackauckas merged 1 commit into
Conversation
f465cf3 to
9f91980
Compare
|
Full local test results (all run after the change, on Julia 1.12.6):
The new regression test was additionally run standalone under both configurations it has to 🤖 Generated with Claude Code |
9f91980 to
be825ff
Compare
|
The branch has been rewritten on current clean Final decision:
The reason is performance, not only robustness: on the matrix-free Exact final local verification on Julia 1.12.6:
The clean-master standalone regression was also run and failed at Hairer4 drift |
|
CI note: the immediate documentation, downstream, and ImplicitDiscreteSolve downgrade failures are the clean- |
SciML#3991 resolved `WarmStart.Auto` to `WarmStart.Hegedus` on the Newton path. The guess there is the previous Newton increment, and those converge to zero, so once Newton has converged the guess is pure round-off while the Hegedüs scalar `ξ = ⟨Au,b⟩/⟨Au,Au⟩` is ill-conditioned exactly where it is applied. A 1-ulp input change moved the Hairer4 solution by 3.7e-03 (SciML#4034). SciML/LinearSolve.jl#1123, released in 5.8.0, fixes that at the source: a Hegedüs guess is discarded unless it reduces the residual by at least half. Pin that with a `[compat]` floor rather than feature-detecting it, so the guarantee is expressed in the resolver instead of in a runtime probe of a LinearSolve internal. Verified against LinearSolve 5.8.0, 1-ulp perturbation of the SciML#4034 DAE: Hairer4, Auto (this branch) 1.33e-15 Hairer4, unguarded Hegedus 3.73e-03 Hairer4, cold start 6.64e-08 The guarded default is also the fastest of the three on the workloads measured: 1D Brusselator KenCarp4 (N=400) nf 158_259 guarded vs 175_852 unguarded vs 202_145 cold, at identical accuracy against a 1e-13 reference. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
be825ff to
7815da0
Compare
This PR should be ignored until reviewed by @ChrisRackauckas.
Fixes #4034. Scope changed after SciML/LinearSolve.jl#1123 merged — please re-read.
The bug
#3991 resolved
WarmStart.AutotoWarmStart.Hegeduson the Newton path. Theguess there is the previous Newton increment, which converges to zero by
construction — so once Newton converges the guess is pure round-off, while the
Hegedüs scalar
ξ = ⟨Au,b⟩/⟨Au,Au⟩is ill-conditioned exactly where it isapplied (
ξmeasured over3.9e-32 … 5.1e+31;|cos∠(Au,b)|down to 2e-16).GMRES then returns the rescaled noise verbatim at iteration 0 on ~37% of solves,
and it feeds the SDIRK error estimate and step-size control.
Result: a 1-ulp input change moved the Hairer4 solution by 3.7e-03.
What changed since the first revision
The first revision gated the default behind
isdefined(LinearSolve, :HEGEDUS_MIN_RESIDUAL_REDUCTION). SciML/LinearSolve.jl#1123 has since merged andreleased in 5.8.0, but named the constant
_HEGEDUS_MAX_RESIDUAL_RATIO—internal, no
publicdeclaration. That gate would therefore have beenfalseforever, silently disabling the warm start for good.
Rather than probe someone else's internal, this now states the requirement where
it belongs — a
[compat]floor:default_krylov_warm_startresolvesAuto → Hegedusunconditionally again; theresolver, not a runtime check, guarantees the guard is present.
Verification (LinearSolve 5.8.0, the released guard)
1-ulp perturbation of the #4034 DAE, exercising the
Autodefault this PRresolves — no explicit
warm_start:Better than a cold start, because the guard rejects precisely the guesses that
were injecting noise.
Performance
The guarded default is also the fastest of the three. 1D Brusselator,
nsolveidentical within each pair:At identical accuracy — KenCarp4 final-state error against a 1e-13 reference is
3.5894789585e-7 cold vs 3.5894791672e-7 guarded, so the iteration savings are
real work saved, not a weaker stopping test.
TRBDF2's +5% is within noise of a cold start rather than a win; worth knowing
which workloads Hegedüs actually helps, but that is a tuning question now, not a
correctness one.
Also tried and rejected
Warm-starting only the first Newton iteration of each step (cold-starting the
rest) — the obvious fix if the problem is only converged increments. It reduced
the amplification just 3.73e-03 → 1.69e-03, still ~25,000× worse than cold,
because the first solve of each step inherits the previous step's converged
increment. Not carried.
🤖 Generated with Claude Code
https://claude.ai/code/session_01TPHRh64BLfoXSzQ3AxKNwC