DifferentialEquations: Callback which is only triggered the first time condition is satisfied

Is there an elegant way to define a ContinuousCallback which calls affect! only the first time that condition is satisfied (after which it does nothing)? For example, how could one modify the Bouncing Ball example (Event Handling and Callback Functions · DifferentialEquations.jl) so that the ball bounces the first time that y==0 but not subsequent times?

Yes, just have a parameter in the callback that you flip in the affect! that makes it so that it can never cross zero (say, make the condition always return 1).

Thanks! The following seems to work. Is this what you meant or is there a better way?

function f(du,u,p,t)
  du[1] = u[2]
  du[2] = -p

bounced = [0]

function condition(u,t,integrator)
  u[1] + bounced[1]*(1 - u[1])

function affect!(integrator, param=bounced)
    integrator.u[2] = -integrator.u[2]
    param[1] = 1

cb = ContinuousCallback(condition,affect!)

u0 = [50.0,0.0]
tspan = (0.0,15.0)
p = 9.8
prob = ODEProblem(f,u0,tspan,p)
sol = solve(prob,Tsit5(),callback=cb)

Yup. We might make a way to turn callbacks off more formally but that way is simple and works fine.

1 Like

I think this would be a good feature since a callback that does nothing still can add substantial time to the solve (since it still has to step to the right point)

Such a term inside of the callback would force the callback to be mutable though. I’m not worried about the allocations but then there would be some thread-safety issues. The way we usually handle that is to make all mutability contained within the integrator objects, so that would be what we’d do here: add to the callback interface some specific terms in the integrator for turning on and off callbacks. It is something we should do, but not the highest priority on my mind right now. But it would be a great contribution (hint hint)

1 Like