@@ -79,6 +79,62 @@ function continuous_events(sys::AbstractSystem)
79
79
filter (! isempty, cbs)
80
80
end
81
81
82
+ # ################################### continuous events #####################################
83
+
84
+ struct SymbolicDiscreteCallback
85
+ condition
86
+ affects:: Vector{Equation}
87
+ function SymbolicDiscreteCallback (condition, affects = NULL_AFFECT)
88
+ c = value (scalarize (condition))
89
+ a = scalarize (affects)
90
+ new (c, a)
91
+ end # Default affect to nothing
92
+ end
93
+
94
+ SymbolicDiscreteCallback (p:: Pair ) = SymbolicDiscreteCallback (p[1 ], p[2 ])
95
+ SymbolicDiscreteCallback (cb:: SymbolicDiscreteCallback ) = cb # passthrough
96
+
97
+ function Base. show (io:: IO , db:: SymbolicDiscreteCallback )
98
+ println (io, " condition: " , db. condition)
99
+ println (io, " affects:" )
100
+ for affect in db. affects
101
+ println (io, " " , affect)
102
+ end
103
+ end
104
+
105
+ function Base.:(== )(e1:: SymbolicDiscreteCallback , e2:: SymbolicDiscreteCallback )
106
+ isequal (e1. condition, e2. condition) && isequal (e1. affects, e2. affects)
107
+ end
108
+ function Base. hash (cb:: SymbolicDiscreteCallback , s:: UInt )
109
+ s = foldr (hash, cb. condition, init = s)
110
+ foldr (hash, cb. affects, init = s)
111
+ end
112
+
113
+ condition (cb:: SymbolicDiscreteCallback ) = cb. condition
114
+ function conditions (cbs:: Vector{<:SymbolicDiscreteCallback} )
115
+ reduce (vcat, condition (cb) for cb in cbs)
116
+ end
117
+
118
+ affect_equations (cb:: SymbolicDiscreteCallback ) = cb. affects
119
+ function affect_equations (cbs:: Vector{SymbolicDiscreteCallback} )
120
+ reduce (vcat, affect_equations (cb) for cb in cbs)
121
+ end
122
+ function namespace_equation (cb:: SymbolicDiscreteCallback , s):: SymbolicDiscreteCallback
123
+ SymbolicDiscreteCallback (namespace_expr (condition (cb), s),
124
+ namespace_equation .(affect_equations (cb), Ref (s)))
125
+ end
126
+
127
+ function discrete_events (sys:: AbstractSystem )
128
+ obs = get_discrete_events (sys)
129
+ systems = get_systems (sys)
130
+ cbs = [obs;
131
+ reduce (vcat,
132
+ (map (o -> namespace_equation (o, s), discrete_events (s)) for s in systems),
133
+ init = SymbolicDiscreteCallback[])]
134
+ filter (! isempty, cbs)
135
+ end
136
+
137
+
82
138
# ################################ compilation functions ####################################
83
139
84
140
# handles ensuring that affect! functions work with integrator arguments
@@ -91,6 +147,26 @@ function add_integrator_header()
91
147
expr. body)
92
148
end
93
149
150
+ """
151
+ compile_condition(cb::SymbolicDiscreteCallback, sys, dvs, ps; expression, kwargs...)
152
+
153
+ Returns a function `condition(u,p,t)` returning the `condition(cb)`.
154
+
155
+ Notes
156
+ - `expression = Val{true}`, causes the generated function to be returned as an expression.
157
+ If set to `Val{false}` a `RuntimeGeneratedFunction` will be returned.
158
+ - `kwargs` are passed through to `Symbolics.build_function`.
159
+ """
160
+ function compile_condition (cb:: SymbolicDiscreteCallback , sys, dvs, ps;
161
+ expression = Val{true }, kwargs... )
162
+
163
+ u = map (x -> time_varying_as_func (value (x), sys), dvs)
164
+ p = map (x -> time_varying_as_func (value (x), sys), ps)
165
+ t = get_iv (sys)
166
+ condit = condition (cb)
167
+ build_function (condit, u, p, t; expression, kwargs... )
168
+ end
169
+
94
170
function compile_affect (cb:: SymbolicContinuousCallback , args... ; kwargs... )
95
171
compile_affect (affect_equations (cb), args... ; kwargs... )
96
172
end
0 commit comments