@@ -110,8 +110,13 @@ Contains a single callback whose `condition` is a continuous function. The callb
110110 `affect!` satisfies the constraints (or else errors). It is not recommended that `NoInit()` is
111111 used as that will lead to an unstable step following initialization. This warning can be
112112 ignored for non-DAE ODEs.
113+
114+ # Extended help
115+
116+ - `discrete_save_idxs`: An iterable of timeseries indexes to save after the callback triggers. MTK-only
117+ API
113118"""
114- struct ContinuousCallback{F1, F2, F3, F4, F5, T, T2, T3, T4, I, R} < :
119+ struct ContinuousCallback{F1, F2, F3, F4, F5, T, T2, T3, T4, I, R, DSI } < :
115120 AbstractContinuousCallback
116121 condition:: F1
117122 affect!:: F2
@@ -127,20 +132,20 @@ struct ContinuousCallback{F1, F2, F3, F4, F5, T, T2, T3, T4, I, R} <:
127132 reltol:: T2
128133 repeat_nudge:: T3
129134 initializealg:: T4
135+ discrete_save_idxs:: DSI
130136 function ContinuousCallback (condition:: F1 , affect!:: F2 , affect_neg!:: F3 ,
131137 initialize:: F4 , finalize:: F5 , idxs:: I , rootfind,
132138 interp_points, save_positions, dtrelax:: R , abstol:: T ,
133- reltol:: T2 ,
134- repeat_nudge:: T3 ,
135- initializealg:: T4 = nothing ) where {F1, F2, F3, F4, F5, T, T2, T3, T4, I, R
139+ reltol:: T2 , repeat_nudge:: T3 , initializealg:: T4 = nothing ,
140+ discrete_save_idxs:: DSI = ()) where {F1, F2, F3, F4, F5, T, T2, T3, T4, I, R, DSI
136141 }
137142 _condition = prepare_function (condition)
138- new {typeof(_condition), F2, F3, F4, F5, T, T2, T3, T4, I, R} (_condition,
143+ new {typeof(_condition), F2, F3, F4, F5, T, T2, T3, T4, I, R, DSI } (_condition,
139144 affect!, affect_neg!,
140145 initialize, finalize, idxs, rootfind,
141146 interp_points,
142147 BitArray (collect (save_positions)),
143- dtrelax, abstol, reltol, repeat_nudge, initializealg)
148+ dtrelax, abstol, reltol, repeat_nudge, initializealg, discrete_save_idxs )
144149 end
145150end
146151
@@ -154,12 +159,13 @@ function ContinuousCallback(condition, affect!, affect_neg!;
154159 dtrelax = 1 ,
155160 abstol = 10 eps (), reltol = 0 ,
156161 repeat_nudge = 1 // 100 ,
157- initializealg = nothing )
162+ initializealg = nothing ,
163+ discrete_save_idxs = ())
158164 ContinuousCallback (condition, affect!, affect_neg!, initialize, finalize,
159165 idxs,
160166 rootfind, interp_points,
161167 save_positions,
162- dtrelax, abstol, reltol, repeat_nudge, initializealg)
168+ dtrelax, abstol, reltol, repeat_nudge, initializealg, discrete_save_idxs )
163169end
164170
165171function ContinuousCallback (condition, affect!;
@@ -172,11 +178,11 @@ function ContinuousCallback(condition, affect!;
172178 interp_points = 10 ,
173179 dtrelax = 1 ,
174180 abstol = 10 eps (), reltol = 0 , repeat_nudge = 1 // 100 ,
175- initializealg = nothing )
181+ initializealg = nothing , discrete_save_idxs = () )
176182 ContinuousCallback (condition, affect!, affect_neg!, initialize, finalize, idxs,
177183 rootfind, interp_points,
178184 collect (save_positions),
179- dtrelax, abstol, reltol, repeat_nudge, initializealg)
185+ dtrelax, abstol, reltol, repeat_nudge, initializealg, discrete_save_idxs )
180186end
181187
182188"""
@@ -219,8 +225,13 @@ multiple events.
219225 - `len`: Number of callbacks chained. This is compulsory to be specified.
220226
221227Rest of the arguments have the same meaning as in [`ContinuousCallback`](@ref).
228+
229+ # Extended help
230+
231+ - `discrete_save_idxs`: An iterable of `len` elements, where the `i`th element is an iterable of timeseries
232+ indexes to save when the `i`th event triggers. MTK-only API.
222233"""
223- struct VectorContinuousCallback{F1, F2, F3, F4, F5, T, T2, T3, T4, I, R} < :
234+ struct VectorContinuousCallback{F1, F2, F3, F4, F5, T, T2, T3, T4, I, R, DSI } < :
224235 AbstractContinuousCallback
225236 condition:: F1
226237 affect!:: F2
@@ -237,21 +248,24 @@ struct VectorContinuousCallback{F1, F2, F3, F4, F5, T, T2, T3, T4, I, R} <:
237248 reltol:: T2
238249 repeat_nudge:: T3
239250 initializealg:: T4
251+ discrete_save_idxs:: DSI
240252 function VectorContinuousCallback (
241253 condition:: F1 , affect!:: F2 , affect_neg!:: F3 , len:: Int ,
242254 initialize:: F4 , finalize:: F5 , idxs:: I , rootfind,
243255 interp_points, save_positions, dtrelax:: R ,
244- abstol:: T , reltol:: T2 ,
245- repeat_nudge :: T3 ,
246- initializealg :: T4 = nothing ) where {F1, F2, F3, F4, F5, T, T2,
247- T3, T4, I, R}
256+ abstol:: T , reltol:: T2 , repeat_nudge :: T3 ,
257+ initializealg :: T4 = nothing ,
258+ discrete_save_idxs :: DSI = () ) where {F1, F2, F3, F4, F5, T, T2,
259+ T3, T4, I, R, DSI }
248260 _condition = prepare_function (condition)
249- new {typeof(_condition), F2, F3, F4, F5, T, T2, T3, T4, I, R} (_condition,
261+ new {typeof(_condition), F2, F3, F4, F5, T, T2, T3, T4, I, R, DSI} (
262+ _condition,
250263 affect!, affect_neg!, len,
251264 initialize, finalize, idxs, rootfind,
252265 interp_points,
253266 BitArray (collect (save_positions)),
254- dtrelax, abstol, reltol, repeat_nudge, initializealg)
267+ dtrelax, abstol, reltol, repeat_nudge, initializealg,
268+ discrete_save_idxs)
255269 end
256270end
257271
@@ -264,13 +278,13 @@ function VectorContinuousCallback(condition, affect!, affect_neg!, len;
264278 interp_points = 10 ,
265279 dtrelax = 1 ,
266280 abstol = 10 eps (), reltol = 0 , repeat_nudge = 1 // 100 ,
267- initializealg = nothing )
281+ initializealg = nothing , discrete_save_idxs = () )
268282 VectorContinuousCallback (condition, affect!, affect_neg!, len,
269283 initialize, finalize,
270284 idxs,
271285 rootfind, interp_points,
272286 save_positions, dtrelax,
273- abstol, reltol, repeat_nudge, initializealg)
287+ abstol, reltol, repeat_nudge, initializealg, discrete_save_idxs )
274288end
275289
276290function VectorContinuousCallback (condition, affect!, len;
@@ -283,12 +297,12 @@ function VectorContinuousCallback(condition, affect!, len;
283297 interp_points = 10 ,
284298 dtrelax = 1 ,
285299 abstol = 10 eps (), reltol = 0 , repeat_nudge = 1 // 100 ,
286- initializealg = nothing )
300+ initializealg = nothing , discrete_save_idxs = () )
287301 VectorContinuousCallback (condition, affect!, affect_neg!, len, initialize, finalize,
288302 idxs,
289303 rootfind, interp_points,
290304 collect (save_positions),
291- dtrelax, abstol, reltol, repeat_nudge, initializealg)
305+ dtrelax, abstol, reltol, repeat_nudge, initializealg, discrete_save_idxs )
292306end
293307
294308"""
@@ -339,31 +353,39 @@ DiscreteCallback(condition, affect!;
339353 `affect!` satisfies the constraints (or else errors). It is not recommended that `NoInit()` is
340354 used as that will lead to an unstable step following initialization. This warning can be
341355 ignored for non-DAE ODEs.
356+
357+ # Extended help
358+
359+ - `discrete_save_idxs`: An iterable of timeseries indexes to save after the callback triggers. MTK-only
360+ API
342361"""
343- struct DiscreteCallback{F1, F2, F3, F4, F5} <: AbstractDiscreteCallback
362+ struct DiscreteCallback{F1, F2, F3, F4, F5, DSI } <: AbstractDiscreteCallback
344363 condition:: F1
345364 affect!:: F2
346365 initialize:: F3
347366 finalize:: F4
348367 save_positions:: BitArray{1}
349368 initializealg:: F5
369+ discrete_save_idxs:: DSI
350370 function DiscreteCallback (condition:: F1 , affect!:: F2 ,
351371 initialize:: F3 , finalize:: F4 ,
352372 save_positions,
353- initializealg:: F5 = nothing ) where {F1, F2, F3, F4, F5}
373+ initializealg:: F5 = nothing ,
374+ discrete_save_idxs:: DSI = ()) where {F1, F2, F3, F4, F5, DSI}
354375 _condition = prepare_function (condition)
355- new {typeof(_condition), F2, F3, F4, F5} (_condition,
376+ new {typeof(_condition), F2, F3, F4, F5, DSI } (_condition,
356377 affect!, initialize, finalize,
357378 BitArray (collect (save_positions)),
358- initializealg)
379+ initializealg, discrete_save_idxs )
359380 end
360381end
361382function DiscreteCallback (condition, affect!;
362383 initialize = INITIALIZE_DEFAULT, finalize = FINALIZE_DEFAULT,
363384 save_positions = (true , true ),
364- initializealg = nothing )
385+ initializealg = nothing , discrete_save_idxs = () )
365386 DiscreteCallback (
366- condition, affect!, initialize, finalize, save_positions, initializealg)
387+ condition, affect!, initialize, finalize, save_positions, initializealg,
388+ discrete_save_idxs)
367389end
368390
369391"""
420442 split_callbacks ((cs... , d. continuous_callbacks... ), (ds... , d. discrete_callbacks... ),
421443 args... )
422444end
445+
446+ """
447+ $TYPEDSIGNATURES
448+
449+ Save the discrete variables associated with callback `cb` in `integrator`.
450+
451+ # Keyword arguments
452+
453+ - `skip_duplicates`: Skip saving variables that have already been saved at the current time.
454+ """
455+ function save_discretes! (integrator:: DEIntegrator , cb:: Union{ContinuousCallback, DiscreteCallback} ; skip_duplicates = false )
456+ isempty (cb. discrete_save_idxs) && return
457+ for idx in cb. discrete_save_idxs
458+ save_discretes! (integrator, idx; skip_duplicates)
459+ end
460+ end
461+
462+ function save_discretes! (integrator:: DEIntegrator , cb:: VectorContinuousCallback ; kw... )
463+ isempty (cb. discrete_save_idxs) && return
464+ for idx in eachindex (cb. discrete_save_idxs)
465+ save_discretes! (integrator, cb, idx; skip_duplicates = true )
466+ end
467+ end
468+
469+ function save_discretes! (integrator:: DEIntegrator , cb:: VectorContinuousCallback , i; skip_duplicates = false )
470+ isempty (cb. discrete_save_idxs) && return
471+ for idx in cb. discrete_save_idxs[i]
472+ save_discretes! (integrator, idx; skip_duplicates)
473+ end
474+ end
475+
476+ function _save_all_discretes! (integrator:: DEIntegrator , cb:: DECallback , cbs:: DECallback... )
477+ save_discretes! (integrator, cb; skip_duplicates = true )
478+ _save_all_discretes! (integrator, cbs... )
479+ end
480+
481+ _save_all_discretes! (:: DEIntegrator ) = nothing
482+
483+ function save_discretes! (integrator:: DEIntegrator , cb:: CallbackSet ; kw... )
484+ _save_all_discretes! (integrator, cb. continuous_callbacks... , cb. discrete_callbacks... )
485+ end
486+
487+ """
488+ $TYPEDSIGNATURES
489+
490+ Save the discrete variables associated with callback `cb` in `integrator` if the finalizer
491+ exists and `save_positions[2]` is `true`. Used to save the necessary values at the final
492+ time of the simulation, after the finalizer has run.
493+ """
494+ function save_final_discretes! (integrator:: DEIntegrator , cb:: Union{ContinuousCallback, VectorContinuousCallback, DiscreteCallback} )
495+ cb. finalize === FINALIZE_DEFAULT && return
496+ cb. save_positions[2 ] || return
497+ save_discretes! (integrator, cb; skip_duplicates = true )
498+ end
499+
500+ function _save_all_final_discretes! (integrator:: DEIntegrator , cb:: DECallback , cbs:: DECallback... )
501+ save_final_discretes! (integrator, cb)
502+ _save_all_final_discretes! (integrator, cbs... )
503+ end
504+
505+ _save_all_final_discretes! (:: DEIntegrator ) = nothing
506+
507+ function save_final_discretes! (integrator:: DEIntegrator , cb:: CallbackSet ; kw... )
508+ _save_all_final_discretes! (integrator, cb. continuous_callbacks... , cb. discrete_callbacks... )
509+ end
510+
511+ """
512+ $TYPEDSIGNATURES
513+
514+ Save the discrete variables associated with callback `cb` in `integrator` if
515+ `save_positions[2]` is `true`.
516+
517+ # Keyword arguments
518+
519+ - `skip_duplicates`: Skip saving variables that have already been saved at the current time.
520+ """
521+ function save_discretes_if_enabled! (integrator:: DEIntegrator , cb:: Union{ContinuousCallback, VectorContinuousCallback, DiscreteCallback} ; skip_duplicates = false )
522+ cb. save_positions[2 ] || return
523+ save_discretes! (integrator, cb; skip_duplicates)
524+ end
525+
526+ function _save_discretes_if_enabled! (integrator:: DEIntegrator , cb:: DECallback , cbs:: DECallback... ; kw... )
527+ save_discretes_if_enabled! (integrator, cb; kw... )
528+ _save_discretes_if_enabled! (integrator, cbs... ; kw... )
529+ end
530+
531+ _save_discretes_if_enabled! (:: DEIntegrator ; kw... ) = nothing
532+
533+ function save_discretes_if_enabled! (integrator:: DEIntegrator , cb:: CallbackSet ; kw... )
534+ _save_discretes_if_enabled! (integrator, cb. continuous_callbacks... , cb. discrete_callbacks... ; kw... )
535+ end
0 commit comments