Skip to content

Unify ode/sde_determine_initdt into single implementation#3137

Merged
ChrisRackauckas merged 3 commits intoSciML:masterfrom
ChrisRackauckas-Claude:phase15-initdt-dead-code-resize
Mar 17, 2026
Merged

Unify ode/sde_determine_initdt into single implementation#3137
ChrisRackauckas merged 3 commits intoSciML:masterfrom
ChrisRackauckas-Claude:phase15-initdt-dead-code-resize

Conversation

@ChrisRackauckas-Claude
Copy link
Copy Markdown
Contributor

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Mar 16, 2026

Summary

  • Unifies ode_determine_initdt and sde_determine_initdt into a single implementation
  • Internal _ode_initdt_iip / _ode_initdt_oop functions accept optional g (diffusion) and noise_prototype parameters
  • When g is not nothing, diffusion terms are folded into d1 and d2 estimates
  • When g is nothing, ODE SIMD optimizations are preserved unchanged
  • New AbstractRODEProblem entry points extract prob.f.g, compute order + 1//2, and delegate

Details

The stochastic Hairer-Wanner initial timestep algorithm adds noise terms to the standard ODE estimate:

  1. d1: uses max(|f0 +/- 3g0|)/sk instead of |f0|/sk
  2. d2: uses max(|df +/- dgMax|)/sk instead of |df|/sk
  3. order: uses order + 1/2 for stochastic convergence rate
  4. Jump shortcut: _get_P(integrator) !== nothing -> dtmax/1e6 (in RODE entry points)

Also fixes a bug in the original SDE iip code where d2 was computed at (u0, t) instead of (u1, t + dt0).

Net: -55 lines (131 insertions, 186 deletions).

Companion PR: SciML/StochasticDiffEq.jl#697

Part of Phase 15 SDE/ODE unification.

Test plan

  • OrdinaryDiffEqCore tests pass
  • SDE Interface1 tests pass (152/152)
  • SDE Interface2 tests pass
  • SDE Interface3 tests pass
  • SDE initdt smoke tests pass (EM, SOSRI, SRIW1 -- oop + iip)

Move the SDE initial timestep determination algorithm (stochastic
Hairer-Wanner with diffusion terms) from StochasticDiffEq into
OrdinaryDiffEqCore's initdt.jl. This adds two methods dispatching on
AbstractRODEProblem{uType,tType,true/false} that handle both in-place
and out-of-place SDE problems.

The _determine_initdt hook remains extensible — SDE overrides it to
call sde_determine_initdt with the correct alg_order.

Bump version to 3.22.0.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Replace separate sde_determine_initdt with unified internal functions
_ode_initdt_iip and _ode_initdt_oop that conditionally fold diffusion
terms into the Hairer-Wanner initial timestep estimate when g !== nothing.

- d₁ uses max(|f₀±3g₀|)/sk instead of f₀/sk when noise present
- d₂ uses max(|Δf±ΔgMax|)/sk instead of Δf/sk when noise present
- Order correction (+1/2) applied via entry point dispatch
- Fixes bug in old iip SDE code: f₁/g₁ were evaluated at (u0,t) instead of (u₁,t+dt₀)
- RODE/SDE entry points handle jump shortcut (P !== nothing → dtmax/1e6)
- ODE SIMD optimizations preserved in no-noise path
- Net -55 lines: 2 separate SDE functions → conditional branches in shared code

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas-Claude ChrisRackauckas-Claude changed the title Add sde_determine_initdt to OrdinaryDiffEqCore Unify ode/sde_determine_initdt into single implementation Mar 17, 2026
JET's typo mode flagged g₀ as potentially undefined because it was
assigned inside one `if g !== nothing` block and used in a separate
`if g !== nothing` block. Pre-initialize to nothing so JET can see
the variable is always defined.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas ChrisRackauckas merged commit 90d0d5f into SciML:master Mar 17, 2026
269 of 275 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