Skip to content

Pass explicit MethodOfSteps(Tsit5()) in DDE test#177

Merged
ChrisRackauckas merged 3 commits into
SciML:claude/investigate-diffeqpy-175-4PIFsfrom
ChrisRackauckas-Claude:fix-dde-test-default
May 13, 2026
Merged

Pass explicit MethodOfSteps(Tsit5()) in DDE test#177
ChrisRackauckas merged 3 commits into
SciML:claude/investigate-diffeqpy-175-4PIFsfrom
ChrisRackauckas-Claude:fix-dde-test-default

Conversation

@ChrisRackauckas-Claude
Copy link
Copy Markdown

This is a sub-PR targeting PR #176's branch (claude/investigate-diffeqpy-175-4PIFs).

Context

PR #176's CI is failing on all four matrix jobs (ubuntu/macos × py3.10/3.13) at test_dde.py:

juliacall.JuliaError: MethodError: Cannot `convert` an object of type
  OrdinaryDiffEqRosenbrock.Rosenbrock23Cache{...}

The failure also reproduces on master (it long predates this PR) — see diffeqpy #172 for the original tracking, where the failing test was identified.

Root cause (upstream, in SciML/OrdinaryDiffEq.jl)

In the v7-coupled stack the default-algorithm selectors are inconsistent across problem types:

Problem Default in lib/OrdinaryDiffEqDefault/src/default_alg.jl
ODEProblem DefaultODEAlgorithm(autodiff = AutoFiniteDiff())
DAEProblem DFBDF(autodiff = AutoFiniteDiff())
DDEProblem (lib/DelayDiffEq/src/DelayDiffEq.jl:89) MethodOfSteps(DefaultODEAlgorithm()) — no autodiff override

The DDE path constructs DefaultODEAlgorithm() without autodiff = AutoFiniteDiff(), so when DelayDiffEq later builds the Rosenbrock23 cache against an ODEFunctionWrapper the ForwardDiff.Tag flows in inconsistently between the history-integrator cache and the main-integrator cache (Tag{OrdinaryDiffEqTag, Float64} vs Tag{..., Nothing}), producing the Cannot convert Rosenbrock23Cache{...} MethodError.

A proper upstream fix would just match the ODE/DAE pattern in lib/DelayDiffEq/src/DelayDiffEq.jl, but until that lands and a new DelayDiffEq release ships, diffeqpy CI is blocked.

Change

Pass de.MethodOfSteps(de.Tsit5()) explicitly in diffeqpy/tests/test_dde.py. This is the canonical DelayDiffEq tutorial form and exercises the same DDE-solve / interpolation / saveat plumbing — only the default-selector codepath is bypassed.

After merging

Once this lands on claude/investigate-diffeqpy-175-4PIFs, PR #176's CI matrix should go green on the DDE test. The other failing-test surfaces (none observed in the last run; DAE/ODE/SDE all passed) are unaffected.

🤖 Generated with Claude Code

Co-Authored-By: Chris Rackauckas accounts@chrisrackauckas.com

The default DDE-solve path (`MethodOfSteps(DefaultODEAlgorithm())`)
currently raises `MethodError: Cannot convert ... Rosenbrock23Cache{...}`
on the v7-coupled OrdinaryDiffEq stack. The asymmetry is upstream in
SciML/OrdinaryDiffEq.jl — the ODE/DAE default selectors pass
`autodiff = AutoFiniteDiff()` whereas the DDE default selector at
`lib/DelayDiffEq/src/DelayDiffEq.jl` constructs `DefaultODEAlgorithm()`
without an autodiff override, so when DelayDiffEq later builds the
composite Rosenbrock23 cache against the `ODEFunctionWrapper` the
ForwardDiff tag flows in inconsistently between the history- and
main-integrator caches. Tracked in diffeqpy SciML#172.

Switch the test to the canonical `MethodOfSteps(Tsit5())` invocation
so PR SciML#176's CI is not blocked on the upstream regression while the
diffeqpy stack converges on v7/v8. The test still exercises the
DDEProblem construction and the DelayDiffEq solve path; only the
default-selector codepath is bypassed.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
DifferentialEquations.jl v8 trimmed its re-exports down to SciMLBase +
OrdinaryDiffEq, so symbols from the sub-solver packages (MethodOfSteps,
IDA, CVODE_BDF, SOSRI, EM, etc.) are no longer accessible via
`de.<name>` when `de` is just a reference to the DifferentialEquations
module. The previous shape — `de = loaded[0]` — passes the smoke test
but breaks the moment a user (or one of our tests) reaches for a name
that used to come transitively through DifferentialEquations.

Concretely, `de.MethodOfSteps(de.Tsit5())` now fails with
`UndefVarError: MethodOfSteps not defined in DifferentialEquations` —
the Julia error helpfully prints "a global variable of this name also
exists in DelayDiffEq" — and the same shape will bite any caller using
`de.IDA`, `de.SOSRI`, etc.

Build a fresh `_diffeqpy_de` module in Main that `using`s each sublib
(`DifferentialEquations, OrdinaryDiffEq, OrdinaryDiffEqDefault,
StochasticDiffEq, DelayDiffEq, Sundials, DiffEqCallbacks,
ModelingToolkit`) and point `de` at that. `using` brings each sublib's
exports — and the sublib module name itself — into `_diffeqpy_de`'s
scope, so `de.<name>` resolves uniformly for everything `from diffeqpy
import de` users used to get pre-v8.

Drop the `Main.ModelingToolkit.` prefix from the jit hackery since
`ModelingToolkit` is now visible as a bare name inside `_diffeqpy_de`
via the `using ModelingToolkit` line.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas ChrisRackauckas marked this pull request as ready for review May 13, 2026 18:59
Comment thread diffeqpy/tests/test_dde.py Outdated
@ChrisRackauckas ChrisRackauckas merged commit 90d5faf into SciML:claude/investigate-diffeqpy-175-4PIFs May 13, 2026
4 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