Looking for findfirst or similar for sol objects of DifferentialEquations


I’m doing some control systems work and wanting to find things like risetime of responses, so I want to find where a simulation variable crosses some value. findfirst works but it searches among the simulation points rather than finding where the interpolation crosses the desired point, which if things are smooth might be some distance from the point I would like to find.

I suspect someone has crossed this bridge already, but I’m struggling to find it.

I could do it using callbacks, but that seems a bit overkill for what feels more natural to be done with analysis after the simulation has been run.

Thanks for any pointers.

This is a root-finding problem – try Roots.jl maybe? (Untested)

Note that you can call the DiffEq solution object as if it were a function.

That would certainly work. I was just trying to find out if someone had done the work before me.

There’s no work to do, you just call the relevant function from Roots.jl (I believe).

@klaff Here’s an example using the first code from the DiffEq docs:

using DifferentialEquations
f(u, p, t) = 1.01 * u
u0 = 1 / 2
tspan = (0.0, 1.0)
prob = ODEProblem(f, u0, tspan)
sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8)

julia> using Roots

julia> initial = 3.0;

julia> desired = 5.0;

julia> root = fzero(x -> sol(x) - desired, initial)

julia> sol(root)

Thanks, this works nicely.

"find 10-90 risetime of sol in interval ti to tf, 100% step from yi to yf; n(th) state var"
function findTr(sol, ti, tf, yi, yf, n=1)
    v10,v90 = [0.1,0.9].*(yf-yi).+yi
    t10 = fzero(t -> sol(t)[n] - v10, [ti,tf])
    t90 = fzero(t -> sol(t)[n] - v90, [ti,tf])
    return t90-t10
1 Like