@@ -269,7 +269,8 @@ const Affect = Union{AffectSystem, ImperativeAffect}
269269
270270"""
271271 SymbolicContinuousCallback(eqs::Vector{Equation}, affect = nothing, iv = nothing;
272- affect_neg = affect, initialize = nothing, finalize = nothing, rootfind = SciMLBase.LeftRootFind)
272+ affect_neg = affect, initialize = nothing, finalize = nothing,
273+ rootfind = SciMLBase.LeftRootFind, initialize_save_discretes = true)
273274
274275A [`ContinuousCallback`](@ref SciMLBase.ContinuousCallback) specified symbolically. Takes a vector of equations `eq`
275276as well as the positive-edge `affect` and negative-edge `affect_neg` that apply when *any* of `eq` are satisfied.
@@ -313,6 +314,9 @@ Affects (i.e. `affect` and `affect_neg`) can be specified as either:
313314- Symbolic affects have reinitialization built in. In this case the algorithm will default to SciMLBase.NoInit(), and should **not** be provided.
314315- Functional and imperative affects will default to SciMLBase.CheckInit(), which will error if the system is not properly reinitialized after the callback. If your system is a DAE, pass in an algorithm like SciMLBase.BrownBasicFullInit() to properly re-initialize.
315316
317+ `initialize_save_discretes` is a flag indicating whether the discrete variables modified by this
318+ callback should be saved at the start of the integration (when the `initialize` runs).
319+
316320Initial and final affects can also be specified identically to positive and negative edge affects. Initialization affects
317321will run as soon as the solver starts, while finalization affects will be executed after termination.
318322"""
@@ -325,6 +329,7 @@ struct SymbolicContinuousCallback <: AbstractCallback
325329 rootfind:: Union{Nothing, SciMLBase.RootfindOpt}
326330 reinitializealg:: SciMLBase.DAEInitializationAlgorithm
327331 zero_crossing_id:: Symbol
332+ initialize_save_discretes:: Bool
328333end
329334
330335function SymbolicContinuousCallback (
@@ -336,6 +341,7 @@ function SymbolicContinuousCallback(
336341 rootfind = SciMLBase. LeftRootFind,
337342 reinitializealg = nothing ,
338343 zero_crossing_id = gensym (),
344+ initialize_save_discretes = true ,
339345 kwargs...
340346 )
341347 conditions = (conditions isa AbstractVector) ? conditions : [conditions]
@@ -357,7 +363,7 @@ function SymbolicContinuousCallback(
357363 SymbolicAffect (initialize; kwargs... ), SymbolicAffect (
358364 finalize; kwargs...
359365 ),
360- rootfind, reinitializealg, zero_crossing_id
366+ rootfind, reinitializealg, zero_crossing_id, initialize_save_discretes
361367 )
362368end # Default affect to nothing
363369
@@ -378,7 +384,8 @@ function complete(cb::SymbolicContinuousCallback; kwargs...)
378384 return SymbolicContinuousCallback (
379385 cb. conditions, make_affect (cb. affect; kwargs... ),
380386 make_affect (cb. affect_neg; kwargs... ), make_affect (cb. initialize; kwargs... ),
381- make_affect (cb. finalize; kwargs... ), cb. rootfind, cb. reinitializealg, cb. zero_crossing_id
387+ make_affect (cb. finalize; kwargs... ), cb. rootfind, cb. reinitializealg,
388+ cb. zero_crossing_id, cb. initialize_save_discretes
382389 )
383390end
384391
@@ -489,12 +496,13 @@ struct SymbolicDiscreteCallback <: AbstractCallback
489496 initialize:: Union{Affect, SymbolicAffect, Nothing}
490497 finalize:: Union{Affect, SymbolicAffect, Nothing}
491498 reinitializealg:: SciMLBase.DAEInitializationAlgorithm
499+ initialize_save_discretes:: Bool
492500end
493501
494502function SymbolicDiscreteCallback (
495503 condition:: Union{SymbolicT, Number, Vector{<:Number}} , affect = nothing ;
496504 initialize = nothing , finalize = nothing ,
497- reinitializealg = nothing , kwargs...
505+ reinitializealg = nothing , initialize_save_discretes = true , kwargs...
498506 )
499507 # Manual error check (to prevent events like `[X < 5.0] => [X ~ Pre(X) + 10.0]` from being created).
500508 (condition isa Vector) && (eltype (condition) <: Num ) &&
@@ -516,7 +524,8 @@ function SymbolicDiscreteCallback(
516524 return SymbolicDiscreteCallback (
517525 c, SymbolicAffect (affect; kwargs... ),
518526 SymbolicAffect (initialize; kwargs... ),
519- SymbolicAffect (finalize; kwargs... ), reinitializealg
527+ SymbolicAffect (finalize; kwargs... ), reinitializealg,
528+ initialize_save_discretes
520529 )
521530end # Default affect to nothing
522531
@@ -537,7 +546,8 @@ function complete(cb::SymbolicDiscreteCallback; kwargs...)
537546 return SymbolicDiscreteCallback (
538547 cb. conditions, make_affect (cb. affect; kwargs... ),
539548 make_affect (cb. initialize; kwargs... ),
540- make_affect (cb. finalize; kwargs... ), cb. reinitializealg
549+ make_affect (cb. finalize; kwargs... ), cb. reinitializealg,
550+ cb. initialize_save_discretes
541551 )
542552end
543553
@@ -758,15 +768,15 @@ function generate_continuous_callbacks(
758768 cbs = continuous_events (sys)
759769 isempty (cbs) && return nothing
760770 cb_classes = Dict{
761- Tuple{SciMLBase. RootfindOpt, SciMLBase. DAEInitializationAlgorithm},
771+ Tuple{SciMLBase. RootfindOpt, SciMLBase. DAEInitializationAlgorithm, Bool },
762772 Vector{SymbolicContinuousCallback},
763773 }()
764774
765775 # Sort the callbacks by their rootfinding method
766776 for cb in cbs
767777 _cbs = get! (
768778 () -> SymbolicContinuousCallback[],
769- cb_classes, (cb. rootfind, cb. reinitializealg)
779+ cb_classes, (cb. rootfind, cb. reinitializealg, cb . initialize_save_discretes )
770780 )
771781 push! (_cbs, cb)
772782 end
@@ -876,7 +886,7 @@ function generate_callback(cbs::Vector{SymbolicContinuousCallback}, sys; kwargs.
876886 return VectorContinuousCallback (
877887 trigger, affect, affect_neg, length (eqs); initialize, finalize,
878888 rootfind = cbs[1 ]. rootfind, initializealg = cbs[1 ]. reinitializealg,
879- saved_clock_partitions
889+ saved_clock_partitions, initialize_save_discretes = cbs[ 1 ] . initialize_save_discretes
880890 )
881891end
882892
@@ -913,23 +923,26 @@ function generate_callback(cb, sys; kwargs...)
913923 if is_timed && conditions (cb) isa AbstractVector
914924 return PresetTimeCallback (
915925 trigger, affect; initialize,
916- finalize, initializealg = cb. reinitializealg, saved_clock_partitions
926+ finalize, initializealg = cb. reinitializealg, saved_clock_partitions,
927+ initialize_save_discretes = cb. initialize_save_discretes
917928 )
918929 elseif is_timed
919930 return PeriodicCallback (
920931 affect, trigger; initialize, finalize, initializealg = cb. reinitializealg,
921- saved_clock_partitions
932+ saved_clock_partitions, initialize_save_discretes = cb . initialize_save_discretes
922933 )
923934 else
924935 return DiscreteCallback (
925936 trigger, affect; initialize,
926- finalize, initializealg = cb. reinitializealg, saved_clock_partitions
937+ finalize, initializealg = cb. reinitializealg, saved_clock_partitions,
938+ initialize_save_discretes = cb. initialize_save_discretes
927939 )
928940 end
929941 else
930942 return ContinuousCallback (
931943 trigger, affect, affect_neg; initialize, finalize,
932- rootfind = cb. rootfind, initializealg = cb. reinitializealg, saved_clock_partitions
944+ rootfind = cb. rootfind, initializealg = cb. reinitializealg, saved_clock_partitions,
945+ initialize_save_discretes = cb. initialize_save_discretes
933946 )
934947 end
935948end
0 commit comments