Skip to content

Force dense=false for SDE/RODE solutions in InterpolationData#3274

Merged
ChrisRackauckas merged 1 commit intoSciML:masterfrom
ChrisRackauckas-Claude:fix-rode-dense-false
Mar 29, 2026
Merged

Force dense=false for SDE/RODE solutions in InterpolationData#3274
ChrisRackauckas merged 1 commit intoSciML:masterfrom
ChrisRackauckas-Claude:fix-rode-dense-false

Conversation

@ChrisRackauckas-Claude
Copy link
Copy Markdown
Contributor

Summary

SDE/RODE solvers never populate derivative stages (ks) because RODESolution has no .k field (_has_ks returns false, so save_dense_at_t! is a no-op). When a user passes dense=true to solve(), the InterpolationData was created with dense=true and empty ks, causing BoundsError in ode_interpolation! when it tries ks[i] for high-order interpolation.

Fix: Force dense=false when W !== nothing (SDE/RODE path) in _ode_init, right before InterpolationData construction. This makes ode_interpolation use linear_interpolant instead.

This fixes the BoundsError: attempt to access 0-element Vector{Vector{Vector{Float64}}} at index [50001] seen in SciMLSensitivity.jl's RODE InterpolatingAdjoint tests (SciML/SciMLSensitivity.jl#1398).

Test plan

  • Existing SDE/RODE tests pass (they already default to dense=false)
  • SciMLSensitivity RODE InterpolatingAdjoint tests pass (currently crash with BoundsError)

🤖 Generated with Claude Code

SDE/RODE solvers never populate derivative stages (ks) because
RODESolution has no .k field (_has_ks returns false). When a user
passes dense=true to solve(), the InterpolationData was created with
dense=true and empty ks, causing BoundsError in ode_interpolation!
when it tries to access ks[i] for high-order interpolation.

Force dense=false when W !== nothing (SDE/RODE) so that
ode_interpolation falls through to linear_interpolant instead.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChrisRackauckas-Claude pushed a commit to ChrisRackauckas-Claude/SciMLSensitivity.jl that referenced this pull request Mar 29, 2026
The RODE dense interpolation BoundsError is fixed at the source in
OrdinaryDiffEqCore (SciML/OrdinaryDiffEq.jl#3274): force dense=false
for SDE/RODE solutions so ode_interpolation uses linear interpolation.

Remove the _has_empty_ks workaround from ischeckpointing — the
solution will correctly have dense=false once the upstream fix lands.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ChrisRackauckas ChrisRackauckas merged commit 1fc789e into SciML:master Mar 29, 2026
199 of 220 checks passed
@ChrisRackauckas-Claude
Copy link
Copy Markdown
Contributor Author

Root cause of the Rodas3/ROS34PW3 interpolation bug

The consolidation PR (#3102) added a Hermite fallback in _ode_addsteps! for methods with empty H that computes:

k₁ = dt*f₀ - (u - uprev)
k₂ = 2*(u - uprev) - dt*(f₀ + f₁)

But the Hermite interpolation in generic_dense.jl expects k[1] = f₀ and k[2] = f₁ (raw derivative values), per the standard formula:

u(θ) = (1-θ)*y₀ + θ*y₁ + θ*-1)*((1-2θ)*(y₁-y₀) +-1)*dt*k[1] + θ*dt*k[2])

The fallback stored wrong coefficients, producing wildly inaccurate interpolation (e.g. u(0.15) = 3.97 vs correct 3.28). This caused wrong saveat values → wrong loss → wrong gradients in SciMLSensitivity tests.

Fix: Remove the incorrect Hermite fallback entirely. Methods with empty H fall through to the generic _ode_addsteps! in generic_dense.jl which correctly stores f₀ and f₁.

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