Skip to content

Commit ab62626

Browse files
authored
Merge pull request #1566 from SciML/fb/eventfix
handle empty events
2 parents 7dbf18c + db458ae commit ab62626

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

src/systems/abstractsystem.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ struct SymbolicContinuousCallback
170170
end
171171

172172
Base.:(==)(e1::SymbolicContinuousCallback, e2::SymbolicContinuousCallback) = isequal(e1.eqs, e2.eqs) && isequal(e1.affect, e2.affect)
173+
Base.isempty(cb::SymbolicContinuousCallback) = isempty(cb.eqs)
173174

174175
to_equation_vector(eq::Equation) = [eq]
175176
to_equation_vector(eqs::Vector{Equation}) = eqs
@@ -482,11 +483,13 @@ end
482483

483484
function continuous_events(sys::AbstractSystem)
484485
obs = get_continuous_events(sys)
486+
filter(!isempty, obs)
485487
systems = get_systems(sys)
486-
[obs;
487-
reduce(vcat,
488+
cbs = [obs;
489+
reduce(vcat,
488490
(map(o->namespace_equation(o, s), continuous_events(s)) for s in systems),
489491
init=SymbolicContinuousCallback[])]
492+
filter(!isempty, cbs)
490493
end
491494

492495
Base.@deprecate default_u0(x) defaults(x) false

test/root_equations.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ affect = [v ~ -v]
211211
@test getfield(ball, :continuous_events)[] == SymbolicContinuousCallback(Equation[x ~ 0], Equation[v ~ -v])
212212
ball = structural_simplify(ball)
213213

214+
@test length(ModelingToolkit.continuous_events(ball)) == 1
215+
214216
tspan = (0.0,5.0)
215217
prob = ODEProblem(ball, Pair[], tspan)
216218
sol = solve(prob,Tsit5())
@@ -305,3 +307,52 @@ prob = ODAEProblem(sys, zeros(2), (0.0, 5.1))
305307
sol = solve(prob, Tsit5())
306308
@test all(minimum((0:0.1:5) .- sol.t', dims=2) .< 0.0001) # test that the solver stepped every 0.1s as dictated by event
307309
@test sol([0.25])[vmeasured][] == sol([0.23])[vmeasured][] # test the hold property
310+
311+
312+
313+
## https://github.com/SciML/ModelingToolkit.jl/issues/1528
314+
Dₜ = Differential(t)
315+
316+
@parameters u(t) [input=true] # Indicate that this is a controlled input
317+
@parameters y(t) [output=true] # Indicate that this is a measured output
318+
319+
function Mass(; name, m = 1.0, p = 0, v = 0)
320+
ps = @parameters m=m
321+
sts = @variables pos(t)=p vel(t)=v
322+
eqs = Dₜ(pos) ~ vel
323+
ODESystem(eqs, t, [pos, vel], ps; name)
324+
end
325+
function Spring(; name, k = 1e4)
326+
ps = @parameters k=k
327+
@variables x(t)=0 # Spring deflection
328+
ODESystem(Equation[], t, [x], ps; name)
329+
end
330+
function Damper(; name, c = 10)
331+
ps = @parameters c=c
332+
@variables vel(t)=0
333+
ODESystem(Equation[], t, [vel], ps; name)
334+
end
335+
function SpringDamper(; name, k=false, c=false)
336+
spring = Spring(; name=:spring, k)
337+
damper = Damper(; name=:damper, c)
338+
compose(
339+
ODESystem(Equation[], t; name),
340+
spring, damper)
341+
end
342+
connect_sd(sd, m1, m2) = [sd.spring.x ~ m1.pos - m2.pos, sd.damper.vel ~ m1.vel - m2.vel]
343+
sd_force(sd) = -sd.spring.k * sd.spring.x - sd.damper.c * sd.damper.vel
344+
@named mass1 = Mass(; m=1)
345+
@named mass2 = Mass(; m=1)
346+
@named sd = SpringDamper(; k=1000, c=10)
347+
function Model(u, d=0)
348+
eqs = [
349+
connect_sd(sd, mass1, mass2)
350+
Dₜ(mass1.vel) ~ ( sd_force(sd) + u) / mass1.m
351+
Dₜ(mass2.vel) ~ (-sd_force(sd) + d) / mass2.m
352+
]
353+
@named _model = ODESystem(eqs, t; observed=[y~mass2.pos])
354+
@named model = compose(_model, mass1, mass2, sd)
355+
end
356+
model = Model(sin(30t))
357+
sys = structural_simplify(model)
358+
@test isempty(ModelingToolkit.continuous_events(sys))

0 commit comments

Comments
 (0)