# Multiple Condition for DifferentialEquations callback

I am solving an IVP with the DifferentialEquations package and I am looking to find n events with a specific condition. The issue rises from the fact that my events require 2 conditions to be satisfied. I am using ContinuousCallback since I want to find the exact moment when the event occurs.

Previously, if I needed to terminate at the conditions, x=0 and \dot{x}>0 I would use

# Stopping conditions:
condition(u, t, integrator) = u[1] # when x=0

function affect!(integrator)
# if xdot > 0, terminate the integration
integrator.u[4] > 0 ? terminate!(integrator) : nothing
end


However, in my new case, I want to find the first n events which satisfy these conditions. My current solution is to keep condition(u,t,integrator) the same and have affect!(integrator) be

function affect!(integrator)
# extract counter from the "cache"
event_num = integrator.p[2]
# if xdot > 0, add a crossing, else keep the same
integrator.u[4] > 0 ? event_num += 1 : event_num
# if crossings > n_crossings, terminate, else nothing
event_num == n_cross ? terminate!(integrator) : nothing
# update the "cache" value
integrator.p[2] = event_num
end


Here, as suggested in another post (also here), I use one of my user-defined variables as a “cache” which counts the amount of desired events, and then I set the termination! once I reach the desired amount of events.

However, when I set the options save_everystep=false, save_start=false, and save_end=false in solve, I can see that the returned states show x-axis crossings when \dot{x} is both positive AND negative. It seems to return the states when only the condition() is satisfied. Would there be a way to have condition() only consider an event when \dot{x} > 0? I know the difficulty rises from this having to be a function which is zero at the event.

Yes, I know that there is a post-processing approach which I could use to filter out the undesired states. But I would like to keep this contained if possible.

Thank you all for your time.

So as it turns out, one can differentiate between up-crossings (negative to positive) and down-crossings (positive to negative). Since I am only interested in up-crossings, I can set up the following to meet my needs:

# Stopping conditions:
condition(u, t, integrator) = u[1] # when x=0

function affect!(integrator)
# extract counter from the "cache"
event_num = integrator.p[2]
# update crossing amount
event_num += 1
# if crossings = n_crossings, terminate, else nothing
event_num == n_cross ? terminate!(integrator) : nothing
# update the "cache" value
integrator.p[2] = event_num
end

cb = ContinuousCallback(condition, affect!;
affect_neg! = nothing)