Skip to content

Commit 4bb8c59

Browse files
committed
more test fixes
1 parent 7b8eae1 commit 4bb8c59

File tree

6 files changed

+60
-52
lines changed

6 files changed

+60
-52
lines changed

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
4949
SciMLStructures = "53ae85a6-f571-4167-b2af-e1d143709226"
5050
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
5151
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
52+
SimpleImplicitDiscreteSolve = "3263718b-31ed-49cf-8a0f-35a466e8af96"
5253
SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7"
5354
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
5455
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
@@ -156,8 +157,8 @@ julia = "1.9"
156157
[extras]
157158
AmplNLWriter = "7c4d4715-977e-5154-bfe0-e096adeac482"
158159
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
159-
BoundaryValueDiffEqMIRK = "1a22d4ce-7765-49ea-b6f2-13c8438986a6"
160160
BoundaryValueDiffEqAscher = "7227322d-7511-4e07-9247-ad6ff830280e"
161+
BoundaryValueDiffEqMIRK = "1a22d4ce-7765-49ea-b6f2-13c8438986a6"
161162
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
162163
DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
163164
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"

src/doc

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/systems/callbacks.jl

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -203,68 +203,79 @@ struct SymbolicContinuousCallback <: AbstractCallback
203203

204204
function SymbolicContinuousCallback(
205205
conditions::Union{Equation, Vector{Equation}},
206-
affect = nothing;
206+
affect = nothing, iv = nothing;
207207
affect_neg = affect,
208208
initialize = nothing,
209209
finalize = nothing,
210-
rootfind = SciMLBase.LeftRootFind)
210+
rootfind = SciMLBase.LeftRootFind,
211+
algeeqs = Equation[])
211212

213+
affect isa AbstractVector && isnothing(iv) && @warn "No independent variable specified. If t appears in an affect equation explicitly, like x ~ t + 1, then this must be specified. Otherwise this can be disregarded."
212214
conditions = (conditions isa AbstractVector) ? conditions : [conditions]
213-
new(conditions, make_affect(affect), make_affect(affect_neg),
214-
initialize, finalize, rootfind)
215+
new(conditions, make_affect(affect, iv; algeeqs), make_affect(affect_neg, iv; algeeqs),
216+
make_affect(initialize, iv; algeeqs), make_affect(finalize, iv; algeeqs), rootfind)
215217
end # Default affect to nothing
216218
end
217219

218220
SymbolicContinuousCallback(p::Pair) = SymbolicContinuousCallback(p[1], p[2])
219221
SymbolicContinuousCallback(cb::SymbolicContinuousCallback, args...) = cb
220222

221-
make_affect(affect::Nothing) = nothing
222-
make_affect(affect::Tuple) = FunctionalAffect(affect...)
223-
make_affect(affect::NamedTuple) = FunctionalAffect(; affect...)
224-
make_affect(affect::FunctionalAffect) = affect
225-
make_affect(affect::AffectSystem) = affect
223+
make_affect(affect::Nothing, iv; kwargs...) = nothing
224+
make_affect(affect::Tuple, iv; kwargs...) = FunctionalAffect(affect...)
225+
make_affect(affect::NamedTuple, iv; kwargs...) = FunctionalAffect(; affect...)
226+
make_affect(affect::FunctionalAffect, iv; kwargs...) = affect
227+
make_affect(affect::AffectSystem, iv; kwargs...) = affect
228+
229+
function make_affect(affect::Vector{Equation}, iv; algeeqs = Equation[])
230+
isempty(affect) && return nothing
231+
isempty(algeeqs) && @warn "No algebraic equations were found. If the system has no algebraic equations, this can be disregarded. Otherwise consider passing in `algeeqs` to the SymbolicContinuousCallbacks constructor."
226232

227-
function make_affect(affect::Vector{Equation}; warn = true)
228233
affect = scalarize(affect)
229-
unknowns = OrderedSet()
234+
dvs = OrderedSet()
230235
params = OrderedSet()
231-
232236
for eq in affect
233-
!haspre(eq) && warn &&
234-
@warn "Equation $eq has no `Pre` operator. As such it will be interpreted as an algebraic equation to be satisfied after the callback. If you intended to use the value of a variable x before the affect, use Pre(x)."
235-
collect_vars!(unknowns, params, eq, nothing; op = Pre)
237+
!haspre(eq) &&
238+
@warn "Affect equation $eq has no `Pre` operator. As such it will be interpreted as an algebraic equation to be satisfied after the callback. If you intended to use the value of a variable x before the affect, use Pre(x)."
239+
collect_vars!(dvs, params, eq, iv; op = Pre)
240+
end
241+
for eq in algeeqs
242+
collect_vars!(dvs, params, eq, iv)
243+
end
244+
if isnothing(iv)
245+
iv = isempty(dvs) ? iv : only(arguments(dvs[1]))
236246
end
237-
iv = isempty(unknowns) ? t_nounits : only(arguments(unknowns[1]))
238247

239248
# System parameters should become unknowns in the ImplicitDiscreteSystem.
240249
cb_params = Any[]
241250
discretes = Any[]
242-
p_as_unknowns = Any[]
251+
p_as_dvs = Any[]
243252
for p in params
244253
if iscall(p) && (operation(p) isa Pre)
245254
push!(cb_params, p)
246255
elseif iscall(p) && length(arguments(p)) == 1 &&
247256
isequal(only(arguments(p)), iv)
248257
push!(discretes, p)
249-
push!(p_as_unknowns, tovar(p))
258+
push!(p_as_dvs, tovar(p))
250259
else
251260
push!(discretes, p)
252261
name = iscall(p) ? nameof(operation(p)) : nameof(p)
253262
p = wrap(Sym{FnType{Tuple{symtype(iv)}, Real}}(name)(iv))
254263
p = setmetadata(p, Symbolics.VariableSource, (:variables, name))
255-
push!(p_as_unknowns, p)
264+
push!(p_as_dvs, p)
256265
end
257266
end
258-
aff_map = Dict(zip(p_as_unknowns, discretes))
267+
aff_map = Dict(zip(p_as_dvs, discretes))
259268
rev_map = Dict([v => k for (k, v) in aff_map])
260269
affect = Symbolics.substitute(affect, rev_map)
261-
@mtkbuild affectsys = ImplicitDiscreteSystem(affect, iv, collect(union(unknowns, p_as_unknowns)), cb_params)
270+
@mtkbuild affectsys = ImplicitDiscreteSystem(vcat(affect, algeeqs), iv, collect(union(dvs, p_as_dvs)), cb_params)
271+
# get accessed parameters p from Pre(p) in the callback parameters
262272
params = filter(isparameter, map(x -> only(arguments(unwrap(x))), cb_params))
263-
for u in unknowns
273+
# add unknowns to the map
274+
for u in unknowns(affectsys)
264275
aff_map[u] = u
265276
end
266277

267-
return AffectSystem(affectsys, collect(unknowns), params, discretes, aff_map)
278+
return AffectSystem(affectsys, unknowns(affectsys), params, discretes, aff_map)
268279
end
269280

270281
function make_affect(affect)
@@ -274,7 +285,7 @@ end
274285
"""
275286
Generate continuous callbacks.
276287
"""
277-
function SymbolicContinuousCallbacks(events, algeeqs::Vector{Equation} = Equation[])
288+
function SymbolicContinuousCallbacks(events, algeeqs::Vector{Equation} = Equation[], iv = nothing)
278289
callbacks = SymbolicContinuousCallback[]
279290
isnothing(events) && return callbacks
280291

@@ -283,10 +294,7 @@ function SymbolicContinuousCallbacks(events, algeeqs::Vector{Equation} = Equatio
283294

284295
for event in events
285296
cond, affs = event isa Pair ? (event[1], event[2]) : (event, nothing)
286-
if affs isa AbstractVector
287-
affs = vcat(affs, algeeqs)
288-
end
289-
affect = make_affect(affs)
297+
affect = make_affect(affs, iv; algeeqs)
290298
push!(callbacks, SymbolicContinuousCallback(cond, affect))
291299
end
292300
callbacks
@@ -391,6 +399,8 @@ struct SymbolicDiscreteCallback <: AbstractCallback
391399
condition, affect = nothing;
392400
initialize = nothing, finalize = nothing)
393401
c = is_timed_condition(condition) ? condition : value(scalarize(condition))
402+
403+
isnothing(iv) && @warn "No independent variable specified. If t appears in an affect equation explicitly, like x ~ t + 1, then this must be specified. Otherwise this can be disregarded."
394404
new(c, make_affect(affect), make_affect(initialize),
395405
make_affect(finalize))
396406
end # Default affect to nothing
@@ -399,7 +409,7 @@ end
399409
"""
400410
Generate discrete callbacks.
401411
"""
402-
function SymbolicDiscreteCallbacks(events, algeeqs::Vector{Equation} = Equation[])
412+
function SymbolicDiscreteCallbacks(events, algeeqs::Vector{Equation} = Equation[], iv = nothing)
403413
callbacks = SymbolicDiscreteCallback[]
404414

405415
isnothing(events) && return callbacks
@@ -408,10 +418,7 @@ function SymbolicDiscreteCallbacks(events, algeeqs::Vector{Equation} = Equation[
408418

409419
for event in events
410420
cond, affs = event isa Pair ? (event[1], event[2]) : (event, nothing)
411-
if affs isa AbstractVector
412-
affs = vcat(affs, algeeqs)
413-
end
414-
affect = make_affect(affs)
421+
affect = make_affect(affs, iv; algeeqs)
415422
push!(callbacks, SymbolicDiscreteCallback(cond, affect))
416423
end
417424
callbacks
@@ -813,6 +820,7 @@ function compile_affect(
813820

814821
affsol = init(affprob, SimpleIDSolve())
815822
for u in unknowns(aff)
823+
@show u
816824
integrator[u] = affsol[sys_map[u]]
817825
end
818826
for p in discretes(aff)

src/systems/diffeqs/odesystem.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ function ODESystem(deqs::AbstractVector{<:Equation}, iv, dvs, ps;
305305
end
306306

307307
alg_eqs = filter(eq -> eq.lhs isa Union{Symbolic, Number} && !isdiffeq(eq), deqs)
308-
cont_callbacks = SymbolicContinuousCallbacks(continuous_events, alg_eqs)
309-
disc_callbacks = SymbolicDiscreteCallbacks(discrete_events, alg_eqs)
308+
cont_callbacks = SymbolicContinuousCallbacks(continuous_events, alg_eqs, iv)
309+
disc_callbacks = SymbolicDiscreteCallbacks(discrete_events, alg_eqs, iv)
310310

311311
if is_dde === nothing
312312
is_dde = _check_if_dde(deqs, iv′, systems)

src/systems/diffeqs/sdesystem.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,8 @@ function SDESystem(deqs::AbstractVector{<:Equation}, neqs::AbstractArray, iv, dv
265265
Wfact_t = RefValue(EMPTY_JAC)
266266

267267
alg_eqs = filter(eq -> eq.lhs isa Union{Symbolic, Number} && !isdiffeq(eq), deqs)
268-
cont_callbacks = SymbolicContinuousCallbacks(continuous_events, alg_eqs)
269-
disc_callbacks = SymbolicDiscreteCallbacks(discrete_events, alg_eqs)
268+
cont_callbacks = SymbolicContinuousCallbacks(continuous_events, alg_eqs, iv)
269+
disc_callbacks = SymbolicDiscreteCallbacks(discrete_events, alg_eqs, iv)
270270
if is_dde === nothing
271271
is_dde = _check_if_dde(deqs, iv′, systems)
272272
end

test/symbolic_events.jl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -420,19 +420,19 @@ end
420420

421421
# issue https://github.com/SciML/ModelingToolkit.jl/issues/1386
422422
# tests that it works for ODAESystem
423-
#@testset "ODAESystem" begin
424-
# @variables vs(t) v(t) vmeasured(t)
425-
# eq = [vs ~ sin(2pi * t)
426-
# D(v) ~ vs - v
427-
# D(vmeasured) ~ 0.0]
428-
# ev = [sin(20pi * t) ~ 0.0] => [vmeasured ~ Pre(v)]
429-
# @named sys = ODESystem(eq, t, continuous_events = ev)
430-
# sys = structural_simplify(sys)
431-
# prob = ODEProblem(sys, zeros(2), (0.0, 5.1))
432-
# sol = solve(prob, Tsit5())
433-
# @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
434-
# @test sol([0.25])[vmeasured][] == sol([0.23])[vmeasured][] # test the hold property
435-
#end
423+
@testset "ODAESystem" begin
424+
@variables vs(t) v(t) vmeasured(t)
425+
eq = [vs ~ sin(2pi * t)
426+
D(v) ~ vs - v
427+
D(vmeasured) ~ 0.0]
428+
ev = [sin(20pi * t) ~ 0.0] => [vmeasured ~ Pre(v)]
429+
@named sys = ODESystem(eq, t, continuous_events = ev)
430+
sys = structural_simplify(sys)
431+
prob = ODEProblem(sys, zeros(2), (0.0, 5.1))
432+
sol = solve(prob, Tsit5())
433+
@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
434+
@test sol([0.25])[vmeasured][] == sol([0.23])[vmeasured][] # test the hold property
435+
end
436436

437437
## https://github.com/SciML/ModelingToolkit.jl/issues/1528
438438
@testset "Handle Empty Events" begin

0 commit comments

Comments
 (0)