Skip to content

Fix NonStiffODE under v7 stack: manifest refresh + script bugfixes#1573

Merged
ChrisRackauckas merged 3 commits into
SciML:masterfrom
ChrisRackauckas-Claude:fix/NonStiffODE-v7
Jun 10, 2026
Merged

Fix NonStiffODE under v7 stack: manifest refresh + script bugfixes#1573
ChrisRackauckas merged 3 commits into
SciML:masterfrom
ChrisRackauckas-Claude:fix/NonStiffODE-v7

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Root cause

The v7 stack run on amdci1-1 (CI job 75199969438, run 25374549824) failed in EnrightPryce_wpd.jmd because the pinned Manifest.toml had SymbolicUtils v4.26.0, which throws Method overwriting is not permitted during Module precompilation in apply_optimization_rules. That killed the ParameterizedFunctions precompile (the very first using line in EnrightPryce_wpd.jmd). The cascade of "no such directory" errors against the next six .jmd files in the same log was just the runner cleanup tripping over the killed job — not real per-file failures.

While reproducing locally on a fresh manifest, three additional bugs surfaced that the older pinned stack had been masking:

  1. enright_pryce.jl SF1 typo. Equation 2 of the SF1 system was 1880 * [y[4] - y[2] * (1 + k)] (vector literal [...]) instead of (...). New SymbolicUtils.AddWorkerBuffer correctly throws throw_unequal_shape_error when adding a scalar symbolic to a 1-vector symbolic.

  2. enright_pryce.jl stray ε parameter. The ND Kepler family declared @parameters ε and threaded [ε => e] through make_ds(...), but ε doesn't appear in the equations themselves (the eccentricity enters via initial conditions only). MTK now errors: Expected an Initial parameter to exist for variable ε, but did not find one. Removed.

  3. IRKGL16 (IRKGaussLegendre v1) treats verbose as a Bool, but the v7 stack hands it a DEVerbosity struct. Every WorkPrecisionSet chunk containing IRKGL16(...) raised TypeError: non-boolean ... DEVerbosity ... used in boolean context. Added verbose = SciMLLogging.None() to those chunks in LotkaVolterra / Pleiades / RigidBody / ThreeBody.

  4. OrdinaryDiffEqSIMDRK (MER5v2/MER6v2/RK6v4) StackOverflows on NaNMath.sqrt(::VectorizationBase.Vec{2,Float64}) whenever the RHS calls sqrt — which is exactly the ND Kepler family. Split out a setups_nd without SIMD-RK for the ND section of EnrightPryce_wpd.jmd. NA / NB / NC either don't use sqrt or already skip the affected problem, so SIMD-RK stays in setups for them.

Also: EnrightPryce_wpd.jmd referenced NC_PROBLEMS[5], but nc5prob is intentionally commented out in enright_pryce.jl (TODO: nc5sys — complex N-body system needs special handling for MTK v10). Dropped the NC5 chunk in the .jmd until that's restored.

Fix

  • Pkg.update() on benchmarks/NonStiffODE/ (no Project.toml / [compat] changes). Notable bumps:
    • SymbolicUtils 4.26.0 -> 4.30.1 (root cause)
    • ModelingToolkit 11.24.1 -> 11.26.3
    • SciMLBase 3.7.1 -> 3.13.0
    • LinearSolve 3.75 -> 3.80
    • OrdinaryDiffEqCore / BDF / Default / Rosenbrock / SDIRK / Verner / FIRK / LowOrderRK / Extrapolation: 2.0.0 -> 2.x.y
    • Symbolics 7.21 -> 7.24, DiffEqBase 7.1 -> 7.5, Sundials 6.1 -> 6.2, plus the usual smaller transitives
  • enright_pryce.jl: fix SF1 [...] -> (...) typo; drop stray @parameters ε.
  • EnrightPryce_wpd.jmd: drop the NC5 chunk; introduce setups_nd (no SIMD-RK) for the ND section.
  • LotkaVolterra_wpd.jmd / Pleiades_wpd.jmd / RigidBody_wpd.jmd / ThreeBody_wpd.jmd: add verbose = SciMLLogging.None() to every WorkPrecisionSet chunk that includes IRKGL16(...).

Local verification

Julia 1.11.9, --project=benchmarks/NonStiffODE:

  • Pkg.update() clean; all packages precompile.
  • SciMLBenchmarks.weave_file(..., (:script,)) tangles cleanly for all 7 .jmd files (EnrightPryce, FitzhughNagumo, linear, LotkaVolterra, Pleiades, RigidBody, ThreeBody).
  • EnrightPryce smoke run (numruns=3, abstols 1e-6..1e-8, reltols 1e-3..1e-5):
    • NA1, NA2, NA4, NA5 — pass with full setups (incl. SIMD-RK)
    • NB1, NB2, NB3, NB5 — pass with full setups
    • NC1, NC2, NC3, NC4 — pass with full setups
    • ND1, ND2, ND3, ND4, ND5 — pass with setups_nd (Tsit5/Vern6/Vern7/Vern9)
  • LotkaVolterra full (:github,) weave: previously raised TypeError in the IRKGL16 chunk. After the verbose patch, a direct IRKGL16 + verbose=SciMLLogging.None() WPSet call returns clean.

Test plan

  • Wait for the benchmarks/NonStiffODE job on amdci1-1 (or equivalent) to go green under the v7 stack.

Please ignore until reviewed by @ChrisRackauckas.

…KGL16 verbose

Root cause: three independent issues stacked on top of each other.

1. The pinned Manifest had `SymbolicUtils v4.26.0`, which throws
   `Method overwriting is not permitted during Module precompilation`
   in `apply_optimization_rules`. That kills `ParameterizedFunctions`
   precompile, which is the first `using` line in `EnrightPryce_wpd.jmd`
   — so the very first .jmd in the folder crashed at load time on amdci1-1
   (CI run 25374549824, job 75199969438) and the cascading "no such
   directory" errors on the remaining six files were just the runner
   cleanup tripping over the killed job.

2. `enright_pryce.jl` had two latent bugs that newer `SymbolicUtils` /
   `ModelingToolkit` now catch:
   - SF1 equation 2 had `1880 * [y[4] - y[2] * (1 + k)]` (vector literal)
     instead of `1880 * (y[4] - y[2] * (1 + k))`. The bracket made it a
     1-vector, and `SymbolicUtils.AddWorkerBuffer` now throws an
     unequal-shape error when adding scalar/vector symbolic terms.
   - The ND eccentric-orbit family declared `@parameters ε` and threaded
     `[ε => e]` through every `make_ds(...)`, but ε does not appear in
     the equations themselves (the eccentricity enters only via the
     initial conditions). MTK now correctly errors:
     "Expected an `Initial` parameter to exist for variable `ε`, but
     did not find one". Removed the stray parameter.

3. `IRKGL16` (IRKGaussLegendre v1) treats `verbose` as a Bool, but the
   v7 stack passes a `DEVerbosity` struct. Every `WorkPrecisionSet` chunk
   that included `IRKGL16(...)` raised `TypeError: non-boolean ...
   DEVerbosity ... used in boolean context`. Added
   `verbose = SciMLLogging.None()` to those chunks in
   LotkaVolterra/Pleiades/RigidBody/ThreeBody.

4. `OrdinaryDiffEqSIMDRK` (MER5v2/MER6v2/RK6v4) recurses to a
   StackOverflow on `NaNMath.sqrt(::VectorizationBase.Vec{2,Float64})`
   when the RHS calls `sqrt` — which is exactly the ND Kepler family.
   Split out a `setups_nd` without SIMD-RK for the ND section of
   `EnrightPryce_wpd.jmd`. NA/NB/NC don't hit `sqrt` (or skip the one
   problem that does), so SIMD-RK stays in `setups` for them.

Also: `EnrightPryce_wpd.jmd` referenced `NC_PROBLEMS[5]`, but `nc5prob`
is commented out in `enright_pryce.jl` (TODO: MTK v10 N-body). Dropped
the NC5 chunk.

Fix:
- `Pkg.update()` on `benchmarks/NonStiffODE/` (Project.toml unchanged):
  SymbolicUtils 4.26.0 -> 4.30.1, plus the usual transitive bumps
  (ModelingToolkit 11.24 -> 11.26, SciMLBase 3.7 -> 3.13,
   OrdinaryDiffEq* 2.0 -> 2.x.y, LinearSolve 3.75 -> 3.80, etc.).
- Edit `enright_pryce.jl` bracket typo and ε removal.
- Edit `EnrightPryce_wpd.jmd` to drop NC5 and use `setups_nd` for ND.
- Add `verbose = SciMLLogging.None()` to every IRKGL16-containing
  WorkPrecisionSet in Lotka/Pleiades/RigidBody/ThreeBody.

Local verification (julia 1.11.9, --project=benchmarks/NonStiffODE):
- `Pkg.update()` clean; all packages precompile.
- `weave_file(..., (:script,))` succeeds for all 7 .jmd files.
- EnrightPryce smoke run (numruns=3): NA1/2/4/5, NB1/2/3/5, NC1/2/3/4
  pass with full setups (incl. SIMD-RK); ND1-5 pass with setups_nd.
- LotkaVolterra full weave (`(:github,)`) re-run with the IRKGL16
  verbose patch: the previously-erroring chunk now completes.
- Direct IRKGL16 + `verbose=SciMLLogging.None()` WPSet call on
  LotkaVolterra returns clean.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
ChrisRackauckas and others added 2 commits June 10, 2026 09:47
Root cause of the 6 remaining .jmd failures in CI (run 26699704480):
LSODA.jl v1.0.0 does `if verbose` (a Bool test) in __solve
(LSODA/src/common.jl:41), but under the v7 stack the `verbose` kwarg
arriving from DiffEqBase is either the default `DEVerbosity()` struct
or the chunk-level `SciMLLogging.None()` added for IRKGL16, raising

    ERROR: TypeError: non-boolean (DiffEqBase.DEVerbosity{...}) used in boolean context
    ERROR: TypeError: non-boolean (SciMLLogging.None) used in boolean context

in FitzhughNagumo, LotkaVolterra, Pleiades, RigidBody, ThreeBody and
linear (EnrightPryce has no lsoda and passed).

A chunk-level `verbose = false` is not an option: DiffEqBase 7.5.0
throws "Passing a `Bool` for `verbose` is no longer supported in
OrdinaryDiffEq v7" for the OrdinaryDiffEq / ODEInterface / IRKGL16
solvers in the same WorkPrecisionSet. Instead use the per-setup kwarg
mechanism of DiffEqDevTools (setup-dict keys in
DiffEqBase.allowedkeywords are splatted after the chunk kwargs and
override them): `Dict(:alg=>lsoda(), :verbose=>false)`.

Verified locally on the pinned manifest (Julia 1.11):
- solve(prob, lsoda()) and lsoda + verbose=None() reproduce the TypeError
- solve(prob, lsoda(); verbose=false) succeeds
- WorkPrecisionSet with Dict(:alg=>lsoda(), :verbose=>false) passes both
  with chunk-level verbose=SciMLLogging.None() and with the default
- ddeabm/odex/dop853/ARKODE/CVODE_Adams all pass with the default
  DEVerbosity, so the solvers ordered after lsoda in these chunks are fine

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	benchmarks/NonStiffODE/enright_pryce.jl
@ChrisRackauckas

Copy link
Copy Markdown
Member

CI failure diagnosis and fix (run 26699704480, job 80471466039)

The previous run got through EnrightPryce_wpd.jmd cleanly, then failed 6 of the 7 files — FitzhughNagumo, LotkaVolterra, Pleiades, RigidBody, ThreeBody, linear — all with the same error class, always in the chunk whose WorkPrecisionSet contains lsoda():

ERROR: TypeError: non-boolean (DiffEqBase.DEVerbosity{...}) used in boolean context
ERROR: TypeError: non-boolean (SciMLLogging.None) used in boolean context
  ...
  [1] __solve(prob::..., alg::LSODA.lsoda, ...)
    @ LSODA ~/.julia/packages/LSODA/dEJVs/src/common.jl:41

Root cause

LSODA.jl v1.0.0 (latest release, master identical) does a plain Bool test if verbose in its __solve. Under the v7 stack the verbose kwarg that reaches it is never a Bool:

  • in chunks without a verbose kwarg, DiffEqBase 7.5.0's default DEVerbosity() struct flows through (FitzhughNagumo, RigidBody, linear);
  • in the chunks where this PR added verbose = SciMLLogging.None() for IRKGL16, that None() flows through to LSODA too (LotkaVolterra, Pleiades, ThreeBody).

A chunk-level verbose = false is not an option either — DiffEqBase 7.5.0 throws ArgumentError: Passing a Bool for verbose is no longer supported in OrdinaryDiffEq v7 for every OrdinaryDiffEq/ODEInterface/IRKGL16 solver in the same set. LSODA wants a Bool; everything else refuses one.

Fix (commit a21a93d)

Use DiffEqDevTools' per-setup kwarg mechanism: setup-dict keys in DiffEqBase.allowedkeywords are splatted after the chunk-level kwargs and override them per solver. In all 6 files:

Dict(:alg=>lsoda(), :verbose=>false) # LSODA.jl requires a Bool verbose

Verified locally against the pinned manifest (Julia 1.11):

  • solve(prob, lsoda()) and lsoda + verbose=None() reproduce the exact CI TypeError; solve(prob, lsoda(); verbose=false) succeeds.
  • WorkPrecisionSet with Dict(:alg=>lsoda(), :verbose=>false) passes both with chunk-level verbose=SciMLLogging.None() and with the default verbosity.
  • ddeabm/odex/dop853/ARKODE/CVODE_Adams (the solvers ordered after lsoda in these chunks, some never reached in CI) all pass with the default DEVerbosity.

Long-term, LSODA.jl should accept the v7 verbosity types upstream; this keeps lsoda in the benchmark in the meantime.

Merge with master (commit b94b815)

While this was in flight, master moved (#1583/#1584/#1586/#1599) and the PR became CONFLICTING, which is why the first push (a21a93d) produced no CI run — GitHub skips pull_request runs when no merge ref exists. Merged upstream/master in; the only conflict was enright_pryce.jl (this PR's removal of the stray ε parameter vs. master's Runic reformat). Resolved keeping both: Runic style, no ε, SF1 (...) typo fix intact. The merged enright_pryce.jl loads cleanly under the pinned manifest (all *_PROBLEMS arrays build).

Status

Benchmarks workflow retriggered on b94b815: https://github.com/SciML/SciMLBenchmarks.jl/actions/runs/27268572622

🤖 Generated with Claude Code

@ChrisRackauckas ChrisRackauckas merged commit 881d2ff into SciML:master Jun 10, 2026
4 of 5 checks passed
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