DifferentialEquations.jl with a Float32 tspan


There is a nice blog post here on using DE.jl with different number types.

In Julia v1.9 the following MWE errors:

using DifferentialEquations

function some_arbitrary_function!(du,u,p,τ)
    du = u/100
    nothing #function returns nothing

NF = Float32                   # Number format 
u = NF[0.0, 100.0, π/2.0, 0.0] #Initial conditions e.g. t, r θ, ϕ
params = NF[0.1, 3.5f-7]  #Some arbitrary parameters, unused in this example, just a placeholder
tspan = (zero(NF),NF(1e3)) #integrate from t=0 to t = 1000

ode_prob = ODEProblem(some_arbitrary_function!,u,tspan,params)
ode_solution = solve(ode_prob,DifferentialEquations.RK4())

with a No matching function wrapper was found!. However if we change the end of tspan to a Float64:

tspan = (zero(NF),Float64(1e3))

then everything works ok. This seems like it could be related to this question. The MWE does work on Julia v1.7.

Is this expected behaviour? What is the workaround / best practice?

Open an issue. More specifically, the promotion rules missed the case where tspan is Float32 but state is Float64. Making both Float32 or both Float64 works, and having Float32 state with Float64 time correctly errors, though this is a combination that technically could work.

You could work around the function wrapper via:

ode_prob = ODEProblem{true, SciMLBase.FullSpecialize}(some_arbitrary_function!,u,tspan,params)

Thanks @ChrisRackauckas. Could you clarify re “…but state is Float64”. Which part of the MWE is Float64?

I will open an issue.

Oh, looks like you found a bug in the Float32 time handling in RK4. Fixed in:

The residual adaptivity points were calculated via σ₁ = 1 / 2 - sqrt(3) / 6 but should be in the type of t, i.e. σ₁ = convert(typeof(t), 1 // 2) - sqrt(convert(typeof(t),3)) / 6. That fixes it and tests a bunch more RKs for this.

(As a side note, I wouldn’t recommend RK4 for most things which aren’t DDEs which need residual controls, and even for that I would recommend the OwrenZen methods, but that’s a bit of a side note and this’ll get fixed anyways).