Skip to content

SDIRK smooth_est: W⁻¹-filtered error estimate underestimates VDP local error by ~3 orders; silently disabled under NonlinearSolveAlg (isnewton gate) #3821

Description

@ChrisRackauckas-Claude

Investigation follow-up from the NonlinearSolveAlg benchmarking work (#3819/#3820 series). Two intertwined findings, both empirically verified on VdP μ=1e5, tspan=(0,6.3), rtol=1e-8/atol=1e-11, reference Rodas5P@1e-13.

Finding 1: the smoothed estimate can catastrophically underestimate

TRBDF2() (default smooth_est=true) returns final relative error 4.3e-2 at rtol=1e-8. A per-step audit of the accepted trajectory shows:

  • Replaying every accepted step with fully-converged nonlinear solves (NLNewton(κ=1e-8, max_iter=200, always_new=true)) changes results by ≤ 0.042 tolerance units (median 0.0016) → the nonlinear solves and all Newton acceptance heuristics (η·ndz<κ, iter-1 shortcut, θ≈1 branch, relaxation) are sound; this is not a nonlinear-solver problem.
  • True local error of accepted steps (vs Rodas5P@1e-13 restarts): median 3.3e3× tol, p90 6.1e5×, max 3.4e6×; 927/1133 accepted steps exceed 100× tol. The W⁻¹-filtered (Hosea–Shampine smoothed) embedded estimate is blind to the dominant error mode here.
  • κ-sweep control: tightening NLNewton's κ from 1e-2 to 1e-6 leaves the error at ~2–4e-2 — confirming the acceptance threshold is not the lever.

One-variable isolation (only smooth_est changed):

config naccept nreject final rel err
TRBDF2 smooth_est=true (default) 1,133 443 4.3e-2
TRBDF2 smooth_est=false 45,261 3,839 9.6e-7
KenCarp4 smooth_est=true 498 1 3.2e-2
KenCarp4 smooth_est=false 5,825 674 6.9e-8

The smoothing is the literature-standard stiff filter and clearly intentional — but a 1e-8 request returning 4e-2 with Success is an accuracy trap on relaxation-oscillator problems. (FBDF/QNDF at the same tolerances deliver ~1e-6 — this is SDIRK-estimator-specific.) Whether the default or the filter formulation should change is a design call; filing the quantified evidence.

Finding 2: NonlinearSolveAlg silently loses the smoothing (isnewton gate)

generic_imex_perform_step.jl (~L1255, ~L2299):

if isnewton(nlsolver) && _esdirk_smooth_est(alg)
    est = W \ tmp          # smoothed
else
    est = tmp              # raw
end

isnewton is false for NonlinearSolveAlg, so NSA always error-controls on the raw estimate regardless of smooth_est. Consequences:

For NSA parity, the gate needs (isnewton(nlsolver) || nsa_with_W(nlsolver)) && smooth_est, with the smoothing solve done against the NSA-held W (nlsolver.cache.W); the wrinkle is that NSA has no ODE-side linsolve cache — the factorization lives inside the inner NonlinearSolve cache, so either a dedicated linsolve for the estimator or reuse of the inner cache's factorization is needed.

Repro scripts available (per-step audit + isolation experiment) — happy to attach.

🤖 Filed by an agent after local reproduction; benchmarks and audit run on the #3819+#3820+NonlinearSolve#1003 stack, Julia 1.12.6.

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