DiffEqBase.jl
DiffEqBase.jl copied to clipboard
VectorContinuousCallback with duplicate events causes infinite loop
MWE:
using OrdinaryDiffEq
f = function (u, p, t)
-u + sin(-t)
end
prob = ODEProblem(f, 1.0, (0.0, -10.0))
condition(out, u, t, integrator) = out[:] = [-t - 2.95, -t - 2.95]
function affect!(integrator, idx)
@show integrator, idx
integrator.u = integrator.u + 2
end
callback = VectorContinuousCallback(condition, affect!, 2)
sol = solve(prob, Tsit5(), callback = callback)
Of course for trivial cases the answer is "don't do that" but when different components or computations end up with the same event, this causes problems.
I've been looking into it a little bit and it seems that find_callback_time gets a vector of all the callbacks that changed sign, so I imagine it should check if after the rootfinding it can "check off" multiple events and move on, but I don't fully understand the code yet, and maybe it's a lot more complicated than that, judging by all the comment about floating point details.
I think the main discussion regarding handling of simulteaneous events is in #519 as of now, linking it to connect the discussions (and maybe use this MWE for a test in the future). FWIW, this example kind of works as of DiffEqBase 6.164.2 with right-sided rootfinding (but it will only detect a triggering event instead of both of them, which would be the correct behavior).
callback = VectorContinuousCallback(condition, affect!, 2, rootfind=SciMLBase.RightRootFind)
Ben has a PR that should be coming rather soon, like in the next few weeks.