DifferentialEquations: Change parameter in ODE after some time

Hello everyone,

I hope that this question belongs here, since my problem is mostly about the DifferentialEquations package.

I have the following dynamical system:

using DifferentialEquations
function some_dynamics(u,p,t)
    du = zeros(length(u))
    for i in 1:length(u)
        for j in 1:length(u)
            du[i] += p[i,j]*u[j]*u[i]
        end
    end
    return du
end

with some initial conditions:

p = rand(4,4)
u0 = zeros(length(p[1,:])) .+ 0.1
tspan = (0.,1.)

I can solve the ODE using:

prob = ODEProblem(some_dynamics,u0,tspan,p)
sol = solve(prob)

Is it possible to change the parameter p at some point before tspan[end]?
In pseudo code, I would like to be able to plug in something like
if t == 0.5 -> p = ones(4,4)

Thanks in advance!

Hi,

you can use callbacks for this. That would entail adding something like

condition(u, t, integrator) = t - 0.5
affect!(integrator) = (integrator.p .= ones(4, 4))
callback = ContinuousCallback(condition, affect!)

...

solve(prob; callback = callback)

Happy coding!

3 Likes

You may want to try the new PresetTimeCallback, now added by popular request! Just add the time that you want the callback to deploy at and then the affect! on the integrator goes as expected. Use a vector of times if you want multiple call times.

using OrdinaryDiffEq, DiffEqCallbacks, Test

function some_dynamics(u,p,t)
    du = zeros(length(u))
    for i in 1:length(u)
        for j in 1:length(u)
            du[i] += p[i,j]*u[j]*u[i]
        end
    end
    return du
end

p = rand(4,4)
startp = copy(p)

u0 = zeros(length(p[1,:])) .+ 0.1
tspan = (0.,1.)
prob = ODEProblem(some_dynamics,u0,tspan,p)
cb = PresetTimeCallback(0.5,integrator -> integrator.p .= rand(4,4))
sol = solve(prob,Tsit5(),callback = cb)

prob = ODEProblem(some_dynamics,u0,tspan,p)
cb = PresetTimeCallback([0.3,0.6],integrator -> integrator.p .= rand(4,4))
sol = solve(prob,Tsit5(),callback = cb)
4 Likes

That is exactly what I needed. Thank you so much!