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!

From http://docs.juliadiffeq.org/latest/basics/integrator.html,

`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)
```

Thank you for your help,

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).