Skip to content

Commit f50214e

Browse files
committed
add manually throw error for wrong input
1 parent cd9dcdb commit f50214e

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

src/systems/callbacks.jl

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ struct SymbolicAffect
1111
end
1212

1313
function SymbolicAffect(affect::Vector{Equation}; alg_eqs = Equation[],
14-
discrete_parameters = Any[], kwargs...)
14+
discrete_parameters = infer_discrete_parameters(affect), kwargs...)
1515
if !(discrete_parameters isa AbstractVector)
1616
discrete_parameters = Any[discrete_parameters]
1717
elseif !(discrete_parameters isa Vector{Any})
@@ -31,6 +31,38 @@ function Symbolics.fast_substitute(aff::SymbolicAffect, rules)
3131
map(substituter, aff.discrete_parameters))
3232
end
3333

34+
# The discrete parameters (i.e. parameters that are updated in an event) can be inferred as
35+
# those that occur in an affect equation *outside* of a `Pre(...)` operator.
36+
function infer_discrete_parameters(affects)
37+
discrete_parameters = Set()
38+
for affect in affects
39+
if affect isa Equation
40+
infer_discrete_parameters!(discrete_parameters, affect.lhs)
41+
infer_discrete_parameters!(discrete_parameters, affect.rhs)
42+
elseif affect isa NamedTuple
43+
haskey(affect, :modified) && union!(discrete_parameters, affect.modified)
44+
end
45+
end
46+
return collect(discrete_parameters)
47+
end
48+
49+
# Find all `expr`'s parameters that occur *outside* of a Pre(...) statement. Add these to `discrete_parameters`.
50+
function infer_discrete_parameters!(discrete_parameters, expr)
51+
expr_pre_removed = Symbolics.replacenode(expr, precall_to_1)
52+
dynamic_symvars = Symbolics.get_variables(expr_pre_removed)
53+
# Change this coming line to a Symbolic append type of thing.
54+
union!(discrete_parameters, filter(ModelingToolkit.isparameter, dynamic_symvars))
55+
end
56+
57+
# When updating vector variables, the affect side can be a vector.
58+
function infer_discrete_parameters!(discrete_parameters, expr_vec::Vector)
59+
foreach(expr -> infer_discrete_parameters!(discrete_parameters, expr), expr_vec)
60+
end
61+
62+
# Functions for replacing a Pre-call with a `1.0` (removing its content from an expression).
63+
is_precall(expr) = iscall(expr) ? operation(expr) isa Pre : false
64+
precall_to_1(expr) = (is_precall(expr) ? 1.0 : expr)
65+
3466
struct AffectSystem
3567
"""The internal implicit discrete system whose equations are solved to obtain values after the affect."""
3668
system::AbstractSystem
@@ -438,8 +470,10 @@ function SymbolicDiscreteCallback(
438470
condition::Union{Symbolic{Bool}, Number, Vector{<:Number}}, affect = nothing;
439471
initialize = nothing, finalize = nothing,
440472
reinitializealg = nothing, kwargs...)
441-
c = is_timed_condition(condition) ? condition : value(scalarize(condition))
473+
# Manual error check (to prevent events like `[X < 5.0] => [X ~ Pre(X) + 10.0]` from being created).
474+
(condition isa Vector) && (eltype(condition) <: Num) && error("Vectors of symbolic conditions are not allowed for `SymbolicDiscreteCallback`.")
442475

476+
c = is_timed_condition(condition) ? condition : value(scalarize(condition))
443477
if isnothing(reinitializealg)
444478
if any(a -> a isa ImperativeAffect,
445479
[affect, initialize, finalize])

0 commit comments

Comments
 (0)