2

I have an object, when it reaches a threshold, it will enter a silence period, which I use a parameter (I call it ode_status) flipping between 1 and 0 to determine whether performing the ODE or not.

The threshold is implemented by ContinuousCallback.

fucntion condition(u, t, integrator)
    u[1] - threshold
end

function affect!(integrator)
    integrator.p[1] = 0  # integrator.p[1] represents ode_status
    flip_back_time[1] = integrator.t + 5  # define silence period = 5s
end

ContinuousCallback(condition, affect!)

Next, I want to flip back ode_status after 5s, so I use DiscreteCallback.

function condition(u, t, integrator)
    integrator.p[1] == 0 &&
    integrator.t >= flip_back_time[1]
end

function affect!(integrator)
    integrator.p[1] = 1
end

DiscreteCallback(condition, affect!)

However, the result is not what I think. The time that ode_status flips back is not exactly after 5s. It is at 5.107... or 5.879 in another trial.

I think I misuse these callback functions. Would anyone tell me how to solve this? Thanks in advance!

Pei Huang
  • 344
  • 1
  • 6

1 Answers1

3

This is because the next step is not exactly at the 5 seconds later time. Remember, DiscreteCallback fires only at step times, so you need to insert a tstop to tell it to stop exactly 5 seconds in the future.

function affect!(integrator)
    integrator.p[1] = 0  # integrator.p[1] represents ode_status
    flip_back_time[1] = integrator.t + 5  # define silence period = 5s
    add_tstop!(integrator,integrator.t + 5)
end
Chris Rackauckas
  • 18,645
  • 3
  • 50
  • 81