Reuse homotopy caches across implicit ODE stages - #3985
Conversation
|
CI dependency checkpoint: the docs job failed during package resolution before loading OrdinaryDiffEq code. General currently provides NonlinearSolve through 4.22.0, while this stacked PR requires the new reusable cache API in NonlinearSolve 4.23 from SciML/NonlinearSolve.jl#1100. This is the expected prerequisite boundary, not a source/test failure. No transient |
130ac87 to
1bd5941
Compare
|
Clean-rebase update: this branch is now stacked only on #3984 and depends on SciML/NonlinearSolve.jl#1100. The unrelated #3983 commit has been removed. I reran the official CI has restarted on the clean stack. Dependency resolution for this PR remains expected to wait for NonlinearSolve 4.23/#1100 to be released; no transient source override is committed. |
1bd5941 to
b1f231d
Compare
|
Current-master rebase and exact-head validation update (
During the requested IDS comparison I also found a separate clean-master |
|
Exact-head CI dependency checkpoint: the apparent broad red matrix has one common pre-test cause. Representative logs from Documentation, root CI, downgrade sublibraries (including OrdinaryDiffEqNonlinearSolve), and downstream integration all stop during No failing job reached package loading or this PR's tests. This is the expected SciML/NonlinearSolve.jl#1100 release boundary; local exact-head Core/QA used that PR's 4.24 implementation and passed. I am leaving the public dependency explicit rather than committing a transient source override. CI should be rerun after #1100 merges and NonlinearSolve 4.24 is registered. |
b1f231d to
01929d4
Compare
|
Rebased onto current upstream/master The full official |
|
Early CI note: the immediate documentation, downstream, downgrade, and StochasticDiffEq failures all resolve the current master copy of ImplicitDiscreteSolve and stop at its |
01929d4 to
967902f
Compare
|
Rebased onto current |
|
Fresh benchmark audit after checking the environment manifest: The prior workspace environment had subsequently been developed onto local NonlinearSolve sources, so its current manifest could not substantiate the registered-version label. I discarded that as version evidence and rebuilt a fresh local environment. The new manifest pins registered SciMLBase 3.39.1, NonlinearSolve 4.24.0, and NonlinearSolveBase 2.38.0. Only OrdinaryDiffEq's DiffEqBase, Core, and ImplicitDiscreteSolve sublibraries are developed locally, from the explicit test-only stack Two independent 20-sample runs of the exact 51-solve recurrence measured:
A separate interleaved check (31 paired trials, 200 complete recurrences per timing) measured 250.94 μs for Kantorovich versus 268.39 μs for Sweep, a 6.55% median paired time reduction. A rotated predictor/acceptance check (31 trials × 100 recurrences) measured:
Thus Kantorovich already has the useful trust-monitored secant machinery from Sweep. This smooth recurrence is not enough evidence to change defaults: on the S-fold, constant/strict and secant/strict Kantorovich returned The PR body now contains the corrected pinned-stack evidence. No code or branch change was made for this audit. |
|
Current-head CI triage (
On #4066, the full official The homotopy branch is unchanged. A test-only stack of this head plus the two focused
No CI-only workaround or unrelated change has been added to #3985. It should be rerun |
|
Broader registered-version comparison after the IDS-specific benchmark: Environment: registered SciMLBase 3.39.1, NonlinearSolve 4.24.0, and NonlinearSolveBase 2.38.0. I compared Timing used 31 trials of 50 solves per algorithm with algorithm order rotated each trial. All returned accurate endpoints in every trial.
Default Kantorovich was faster on 6/8 paths; the median of the eight paired default-Kantorovich/Sweep ratios was about 0.91. One of the standard Kantorovich predictor settings was fastest on every path, but neither setting dominated: constant won six, while secant mattered on the linear and sharp-turn paths. Testing secant with Strict and non-strict secant had identical residual counts on all eight no-fold paths, so the strict safety check had no observed ordinary-path cost. On the cubic S-fold, strict Kantorovich correctly returned Conclusion: Kantorovich is often faster than Sweep, but is not categorically better. Strict rejection is path-safety behavior, not random instability; arc length remains the correct fold tool. The results do not justify replacing the default Sweep to arc-length polyalgorithm, and they strengthen the conclusion that generic homotopy should not replace the specialized IDS recurrence, which remained 2.64–2.97x faster than cached Kantorovich in the exact IDS benchmark. No code or branch change was made for this comparison. |
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
967902f to
7c027e4
Compare
|
Rebased onto current upstream/master Before pushing I fetched and audited the fork branch and PR: it still contained exactly the previous single PR commit ( Validation:
Fresh CI is running on |
|
Post-rebase hosted CI audit for
Final branch audit: current |
Ignore this PR until it has been reviewed by @ChrisRackauckas.
Dependencies and scope
SciML/NonlinearSolve.jl#1100 is merged and released in NonlinearSolve 4.24 / NonlinearSolveBase 2.38. It provides reusable
HomotopySweepandKantorovichHomotopyinit/reinit!/solve!caches through public APIs.The related ImplicitDiscreteSolve cache work, #4042, and its registered NonlinearSolveBase 2.38 compatibility correction, #4055, are merged.
This PR only changes implicit ODE stage solves through
OrdinaryDiffEqNonlinearSolve.HomotopyNonlinearSolveAlg.What this changes
HomotopyNonlinearSolveAlgpreviously rebuilt aHomotopyProblemand used one-shotsolvefor every implicit stage. This PR:HomotopySweepandKantorovichHomotopy;reinit!, then calls publicsolve!;solvefor homotopy algorithms without this reusable cache path, including arc-length continuation;NonlinearSolveBase;IDSolveshould not be replaced by this wrapper. Its controller is a timestep/path-continuation policy that uses the previous accepted state and every Newton contraction ratio, whereasHomotopyNonlinearSolveAlgsolves an individual implicit ODE stage equation. The merged IDS path now has its own reusableinit/reinit!/solve!implementation.Solver comparison
On the exact 51-solve IDS recurrence benchmark, using a fresh environment pinned to registered SciMLBase 3.39.1, NonlinearSolve 4.24, and NonlinearSolveBase 2.38, two independent 20-sample runs measured:
IDS was 2.64x-2.97x faster than Kantorovich and 2.88x-3.08x faster than Sweep on its native problem. To reduce sequential-load bias, a separate 31-trial paired benchmark with 200 recurrences per timing measured 250.94 microseconds for Kantorovich versus 268.39 microseconds for Sweep, a 6.55% median paired time reduction. Kantorovich also used 13.04% fewer residual calls.
A rotated 31-trial variant benchmark also measured 250.27 microseconds / 2,040 residual calls for strict Kantorovich's constant predictor, 243.56 microseconds / 1,989 calls with its trust-monitored secant predictor, and 242.25 microseconds / 1,989 calls for secant plus non-strict acceptance. The useful Sweep predictor machinery is therefore already available in Kantorovich; this single smooth recurrence is not evidence to change its defaults.
That does not make strict Kantorovich the safer default. In a controlled slow-corrector check with a 0.99 residual-contraction ratio, strict Kantorovich rejected the converged corrector from
u0 = 0, while non-strict Kantorovich and Sweep both reachedu = 0.1. At a fold, Kantorovich failed and the Sweep-to-arc-length polyalgorithm succeeded. Strict Kantorovich is therefore more conservative/less robust on these checks, not numerically “unstable”; Sweep remains the default, with arc length needed to round folds.Local verification
Final rebased head
967902f1b3on currentupstream/master(fd3f95bb99):homotopy_nlsolve_tests.jlfile passed 38/38. This includes cache identity across stages, time-dependent parameter refresh, resize rebuild, exact warmed@allocated == 0for both cached algorithms, out-of-place/static arrays, arc-length fallback, fold rejection, and DAE rejection.GROUP=QA julia --project=lib/OrdinaryDiffEqNonlinearSolve -e 'using Pkg; Pkg.test()'exited 0: JET 13/13 with 33 pre-existing broken cases; Aqua 19/19; package tests passed.--checkon every changed Julia file andgit diff --check upstream/masterexited 0. Whole-tree Runic on current master is tracked independently by Run Runic on the disco-optimizations files #4064; the homotopy diff is not involved.UndefVarError: issquare not defined in LinearSolveForwardDiffExtwith registered LinearSolve 5.3, before reaching the homotopy file. This dependency regression is being handled separately; it was not skipped or silenced here.