DifferentialEquations simple usage not working

Hi there,
I have a very simple ODE problem defined by:

f_norm(x, α) = x - α*(1 - exp(-x))
f_norm_prime(x, α) = 1 - α*exp(-x)
f_norm_dprime(x, α) = α*exp(-x)
function dxdN!(dx, x, α, N)
    f = f_norm(x, α)
    fx = f_norm_prime(x, α)
    fxx = f_norm_dprime(x, α)
    dx = 3*(2*f - x*fx)/(x*fxx - fx)
end
using DifferentialEquations
prob = ODEProblem(dxdN!, x0, Nspan, α)

Up until here everything seems to work fine and the ODE initial value problem seems to be accepted and well understood by the DifferentialEquations.jl package. However, when I run:

sol =solve(prob)

I get the following error:

ERROR: MethodError: no method matching similar(::Float64, ::Type{Float64})
Closest candidates are:
  similar(::Union{LinearAlgebra.Adjoint{T, var"#s832"}, LinearAlgebra.Transpose{T, var"#s832"}} where {T, var"#s832"<:(AbstractVector{T} where T)}, ::Type{T}) where T at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/adjtrans.jl:230
  similar(::Union{LinearAlgebra.Adjoint{T, S}, LinearAlgebra.Transpose{T, S}} where {T, S}, ::Type{T}) where T at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/adjtrans.jl:234
  similar(::Union{LinearAlgebra.Adjoint{T, S}, LinearAlgebra.Transpose{T, S}} where {T, S}, ::Type{T}, ::Tuple{Vararg{Int64, N}}) where {T, N} at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/adjtrans.jl:235

What happens? I guess it must be something very silly of me and I thank you in advance.

Hi, the following works:

using DifferentialEquations
f_norm(x, α) = x - α*(1 - exp(-x))
f_norm_prime(x, α) = 1 - α*exp(-x)
f_norm_dprime(x, α) = α*exp(-x)
function dxdN(x, α, N)
    f = f_norm(x, α)
    fx = f_norm_prime(x, α)
    fxx = f_norm_dprime(x, α)
    dx = 3*(2*f - x*fx)/(x*fxx - fx)
end
using DifferentialEquations

Nspan = (0.0,10.0)
α = 0.5
x0 = 1.0
prob = ODEProblem(dxdN, x0, Nspan, α)

sol = solve(prob)

There are two forms for an ODE function, dxdN(x,alpha,N) and dxdN!(dx,x,alpha,N). The second version is what is called mutating, meaning that you should alter the first argument and not have the function return anything like this:

function dxdN!(dx, x, α, N)
    f = f_norm(x, α)
    fx = f_norm_prime(x, α)
    fxx = f_norm_dprime(x, α)
    dx[1] = 3*(2*f - x*fx)/(x*fxx - fx)
    return nothing
end

However, for this version you have to alter your f_norm etc to take vector arguments, or call each function like f_norm( x[1] , alpha ).

Dear Jonas,

Could you give some more references (tutorials, manuals) about those differences between dxdN(x, alpha, N) and dxdN!(dx, x, alpha, N). It seems to me this is not a specific issue for DifferentialEquations.jl, but for mutating functions in general, right? Also could you dwell a little bit more on making sense of all this right from the error message, if possible at all?

Thanks a lot!

https://tutorials.sciml.ai/html/introduction/03-optimizing_diffeq_code.html describes it in detail.

Thanks a lot Chris.