I’m trying to detect multiple events in a system of ODEs. Basically, as soon as any variable crosses a threshold, the value of that variable is changed. I know I can achieve this by explicitly coding up these conditions within @continuous_events. This is fine for a small number of equations (there are 3 in the MWE below), but it’s not feasible for large systems with hundreds of equations. I tried a for-loop like
for i in 1:N
[x[i] ~ 0.5] => [x[i] ~ 1.0]
end
in the @continuous_events block, but that gave an error message. I’m hoping that these event conditions can be vectorised in the same way as the equations in @equations. Does anyone know how to achieve this?
Here is the MWE
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
using DifferentialEquations
A = [1.0 -2.0 3.0;
-4.0 2.3 5.2;
2.1 3.5 -1.7]
As = -A'*A
N = size(As,1)
@mtkmodel LinODEsys begin
@parameters begin
Ω[1:N,1:N]
end
@variables begin
x(t)[1:N]
end
@equations begin
collect(D.(x) .~ Ω*x)
end
@continuous_events begin
[x[1] ~ 0.5] => [x[1] ~ 1.0]
[x[2] ~ 0.5] => [x[2] ~ 1.0]
[x[3] ~ 0.5] => [x[3] ~ 1.0]
end
end
@mtkcompile linODEsys = LinODEsys()
u0 = [1.0, 1.0, 1.0]
u0_p = [linODEsys.x => u0]
Ω_p = [linODEsys.Ω[i,j] => As[i,j] for i in 1:N, j in 1:N] |> vec
u0_params = vcat(u0_p, Ω_p)
prob_sys = ODEProblem(linODEsys, u0_params, (0.0, 1.0))
sol_sys = solve(prob_sys)