@@ -11,7 +11,7 @@ struct SymbolicAffect
1111end
1212
1313function 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))
3232end
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+
3466struct 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