Adaptive GPUTsit5 accepts an initial step past tf and reports an incorrect final state
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 327
- Forks
- 42
- Avg merge
- 14h 13m
- Merged PRs (30d)
- 34
Description
On clean master https://github.com/SciML/DiffEqGPU.jl/commit/f1d1f81a2d2a756bd7352c935cc6f1756c8a9af9, adaptive GPUTsit5 can accept an initial step larger than the entire integration interval, then report the final time without correcting the computed state.
Public API reproducer
Julia 1.10.12 (LTS), CPU kernel backend, local environment with DiffEqGPU developed at the clean commit above plus SciMLBase, StaticArrays, and KernelAbstractions:
using DiffEqGPU, SciMLBase, StaticArrays, KernelAbstractions, Test
rhs(u,p,t)=SVector(-u[1],-100*u[2])
prob=ODEProblem{false}(rhs,SVector(1f0,1f0),(0f0,.01f0),SVector(1f0))
sol=solve(EnsembleProblem(prob;prob_func=(prob,ctx)->remake(prob)),GPUTsit5(),EnsembleGPUKernel(CPU(),0.0);trajectories=2,adaptive=true,dt=.1f0,abstol=1f-5,reltol=1f-2,save_everystep=false)
println((t=sol.u[1].t,u=sol.u[1].u,exact=exp.(-SVector(1f0,100f0)*.01f0)))
@test sol.u[1].u[end] ≈ exp.(-SVector(1f0,100f0)*.01f0) rtol=1f-2
Run: julia +lts --project=scratch/short-base-env scratch/short_public_probe.jl.
Two trajectories intentionally exercise EnsembleGPUKernel; the single-trajectory path delegates to an ordinary solver.
Observed, exit status 1:
(t = Float32[0.0, 0.01], u = SVector{2, Float32}[[1.0, 1.0], [0.98403025, 0.20528531]], exact = Float32[0.99004984, 0.36787945])
Test Failed:
Expression: sol.u[1].u[end] ≈ exp.(-SVector(1f0,100f0)*.01f0) rtol=1f-2
Evaluated: Float32[0.98403025, 0.20528531] ≈ Float32[0.99004984, 0.36787945] (rtol=0.01)
A direct integrator probe reports accepted dt = 0.016098652f0 but t = 0.01f0. The initial proposal is 0.1f0; local error rejection reduces it but not enough to fit the interval.
Cause and source history
The adaptive step! reads dt = integ.dtnew without limiting it to tf - t before stage evaluation. Acceptance only limits the next proposal, and if (tf - t - dt) < tolerance sets integ.t = tf while retaining the oversized-step state.
A source-history search traces this structure to the original adaptive Tsit5 kernel added in https://github.com/SciML/DiffEqGPU.jl/commit/c537f8159d168de4f21dd7d6f45bce95b7417c0f and preserved in the integrator extraction https://github.com/SciML/DiffEqGPU.jl/commit/9cc16ac3f949ee267e8585b4d31ca0bcf4ee3e72. This is source provenance, not a completed historical runtime bisect: the original kernel uses CUDA block/thread APIs, and I did not run that 2022 GPU environment. No earlier passing runtime baseline was established.
Diagnostic repair
In an isolated worktree, adding dt = min(dt, tf - t) immediately after loading tf in the adaptive Tsit5 step makes the identical public test pass (exit status 0):
(t = Float32[0.0, 0.01], u = SVector{2, Float32}[[1.0, 1.0], [0.99004984, 0.3680994]], exact = Float32[0.99004984, 0.36787945])
This establishes the forward-time fix direction. A production repair should handle time direction consistently and audit the other adaptive kernels with the same acceptance structure. Only CPU GPUTsit5 was executed here; GPU hardware, reverse-time cases, other solvers, and the full suite were not tested. No main feature worktree was changed.
AI investigation: Codex (harness version unknown; exact model ID unknown). Local session ID: 01a07fcc-1c4f-7ee3-9a1e-51eaab7df293; no shareable conversation URL exposed.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the adaptive GPUTsit5 step entry point and reproduce the failure using scratch/short_public_probe.jl with the command given in the issue. Ensure an accepted step cannot overshoot the final time while preserving correct state handling, then verify the public probe passes and inspect other adaptive kernels with the same acceptance structure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- backend, testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100