# Callback: Switch between dynamic models and time step depending on the region

Hello everyone,

I would like to solve an ODE in DifferentialEquations.jl where the right-hand side and the time step depend on the region where is located the particle.
The function `DiscreteCallBack` seems to be adequate for my problem.
But I don’t know how to change the right hand of the ODEProblem in the function affect!
`integrator.f` should be the function being solved

Here a simplified example of what I am trying to do:
We have a particle whose dynamic is governed by a first function `f1`. When `u[1]<0.0`, we want to switch to a second dynamic `f2` and change the time step

``````using OrdinaryDiffEq

# Model for the first region u[1=]>0
function f1(du,u,p,t)
du[1] = u[2]
du[2] = -p
end
# Model for the second region u[2]<0
function f2(du,u,p,t)
du[1] = -2*u[2]
du[2] = 0.5*p
end

function condition(u,t,integrator) # Switch model if u[1]<0.0
u[1]<0.0
end
function affect!(integrator)
integrator.f = f2
set_proposed_dt!(integrator,0.01)
end
cb = DiscreteCallback(condition,affect!)

u0 = [50.0,0.0]
tspan = (0.0,15.0)
p = 9.8
prob = ODEProblem(f1,u0,tspan,p)

sol = solve(prob,RK4(), dt = 0.1, callback=cb)

``````

You can make those both one function with a boolean that chooses which model to use. Then that boolean can be changed in the callback.

1 Like

Thank you again @ChrisRackauckas for your help.
Since my system will be switching back and forth between the two regions. Is there a way to define a `affect_neg!` for `DiscreteCallBack`, when the condition switches from True to False, and `affect!` will be used when the condition switches from False to True

Just check if the parameter is true or false in `integrator.p`.

I am not sure that I understand.

In the following example, my boolean `p` remains true once the callback has been activated and the solution have been in the negative region( where condition is true) and returned to the positive region ( where condition is false). Also the time step stays fixed to 0.5 for the rest of the simulation, and doesn’t return to 0.1 as I would expect in the region positive( where condition is false)

``````using DifferentialEquations
using OrdinaryDiffEq

# Model for the first region u[1=]>0
function f(du,u,p,t)
print(p)
if p == false
du[1] = -2.0
else
du[1] = 1.0
end
end
p = false

function condition(u,t,integrator) # Switch model if u[1]<0.0
u[1]<0.0
end
function affect!(integrator)
integrator.p = true
integrator.dtcache = 0.5
end

cb = DiscreteCallback(condition,affect!,save_positions=(false,true))

u0 = [1.0]
tspan = (0.0,5.0)
prob = ODEProblem(f,u0,tspan,p)

sol = solve(prob,RK4(), dt = 0.1,adaptive = false, callback=cb)
``````

Yes, and to switch back you can check if integrator.p and flip it.

Wait, why are you using a DiscreteCallback here instead of a Continuous callback?

I got it works, thank you. There was some conditions for the switch of regions which were hard to express using ContinuousCallBack. I had to switch the model at multiple of a time scale, which is easier to express with a boolean condition like ( mod(t, Tscale) =0).