|  | 
| 1 | 1 | abstract type AbstractCallback end | 
| 2 | 2 | 
 | 
| 3 |  | -struct FunctionalAffect | 
| 4 |  | -    f::Any | 
| 5 |  | -    sts::Vector | 
| 6 |  | -    sts_syms::Vector{Symbol} | 
| 7 |  | -    pars::Vector | 
| 8 |  | -    pars_syms::Vector{Symbol} | 
| 9 |  | -    discretes::Vector | 
| 10 |  | -    ctx::Any | 
| 11 |  | -end | 
| 12 |  | - | 
| 13 |  | -function FunctionalAffect(f, sts, pars, discretes, ctx = nothing) | 
| 14 |  | -    # sts & pars contain either pairs: resistor.R => R, or Syms: R | 
| 15 |  | -    vs = [x isa Pair ? x.first : x for x in sts] | 
| 16 |  | -    vs_syms = Symbol[x isa Pair ? Symbol(x.second) : getname(x) for x in sts] | 
| 17 |  | -    length(vs_syms) == length(unique(vs_syms)) || error("Variables are not unique") | 
| 18 |  | - | 
| 19 |  | -    ps = [x isa Pair ? x.first : x for x in pars] | 
| 20 |  | -    ps_syms = Symbol[x isa Pair ? Symbol(x.second) : getname(x) for x in pars] | 
| 21 |  | -    length(ps_syms) == length(unique(ps_syms)) || error("Parameters are not unique") | 
| 22 |  | - | 
| 23 |  | -    FunctionalAffect(f, vs, vs_syms, ps, ps_syms, discretes, ctx) | 
| 24 |  | -end | 
| 25 |  | - | 
| 26 |  | -function FunctionalAffect(; f, sts, pars, discretes, ctx = nothing) | 
| 27 |  | -    FunctionalAffect(f, sts, pars, discretes, ctx) | 
| 28 |  | -end | 
| 29 |  | - | 
| 30 |  | -func(a::FunctionalAffect) = a.f | 
| 31 |  | -context(a::FunctionalAffect) = a.ctx | 
| 32 |  | -parameters(a::FunctionalAffect) = a.pars | 
| 33 |  | -parameters_syms(a::FunctionalAffect) = a.pars_syms | 
| 34 |  | -unknowns(a::FunctionalAffect) = a.sts | 
| 35 |  | -unknowns_syms(a::FunctionalAffect) = a.sts_syms | 
| 36 |  | -discretes(a::FunctionalAffect) = a.discretes | 
| 37 |  | - | 
| 38 |  | -function Base.:(==)(a1::FunctionalAffect, a2::FunctionalAffect) | 
| 39 |  | -    isequal(a1.f, a2.f) && isequal(a1.sts, a2.sts) && isequal(a1.pars, a2.pars) && | 
| 40 |  | -        isequal(a1.sts_syms, a2.sts_syms) && isequal(a1.pars_syms, a2.pars_syms) && | 
| 41 |  | -        isequal(a1.ctx, a2.ctx) | 
| 42 |  | -end | 
| 43 |  | - | 
| 44 |  | -function Base.hash(a::FunctionalAffect, s::UInt) | 
| 45 |  | -    s = hash(a.f, s) | 
| 46 |  | -    s = hash(a.sts, s) | 
| 47 |  | -    s = hash(a.sts_syms, s) | 
| 48 |  | -    s = hash(a.pars, s) | 
| 49 |  | -    s = hash(a.pars_syms, s) | 
| 50 |  | -    s = hash(a.discretes, s) | 
| 51 |  | -    hash(a.ctx, s) | 
| 52 |  | -end | 
| 53 |  | - | 
| 54 | 3 | function has_functional_affect(cb) | 
| 55 |  | -    (affects(cb) isa FunctionalAffect || affects(cb) isa ImperativeAffect) | 
|  | 4 | +    affects(cb) isa ImperativeAffect | 
| 56 | 5 | end | 
| 57 | 6 | 
 | 
| 58 | 7 | struct AffectSystem | 
| @@ -97,7 +46,7 @@ function Base.hash(a::AffectSystem, s::UInt) | 
| 97 | 46 |     hash(aff_to_sys(a), s) | 
| 98 | 47 | end | 
| 99 | 48 | 
 | 
| 100 |  | -function vars!(vars, aff::Union{FunctionalAffect, AffectSystem}; op = Differential) | 
|  | 49 | +function vars!(vars, aff::AffectSystem; op = Differential) | 
| 101 | 50 |     for var in Iterators.flatten((unknowns(aff), parameters(aff), discretes(aff))) | 
| 102 | 51 |         vars!(vars, var) | 
| 103 | 52 |     end | 
|  | 
| 161 | 110 | ############################### | 
| 162 | 111 | ###### Continuous events ###### | 
| 163 | 112 | ############################### | 
| 164 |  | -const Affect = Union{AffectSystem, FunctionalAffect, ImperativeAffect} | 
|  | 113 | +const Affect = Union{AffectSystem, ImperativeAffect} | 
| 165 | 114 | 
 | 
| 166 | 115 | """ | 
| 167 | 116 |     SymbolicContinuousCallback(eqs::Vector{Equation}, affect = nothing, iv = nothing;  | 
| @@ -233,7 +182,7 @@ struct SymbolicContinuousCallback <: AbstractCallback | 
| 233 | 182 |         conditions = (conditions isa AbstractVector) ? conditions : [conditions] | 
| 234 | 183 | 
 | 
| 235 | 184 |         if isnothing(reinitializealg) | 
| 236 |  | -            if any(a -> (a isa FunctionalAffect || a isa ImperativeAffect), | 
|  | 185 | +            if any(a -> a isa ImperativeAffect, | 
| 237 | 186 |                 [affect, affect_neg, initialize, finalize]) | 
| 238 | 187 |                 reinitializealg = SciMLBase.CheckInit() | 
| 239 | 188 |             else | 
| @@ -263,8 +212,8 @@ function SymbolicContinuousCallback(cb::Tuple, args...; kwargs...) | 
| 263 | 212 | end | 
| 264 | 213 | 
 | 
| 265 | 214 | make_affect(affect::Nothing; kwargs...) = nothing | 
| 266 |  | -make_affect(affect::Tuple; kwargs...) = FunctionalAffect(affect...) | 
| 267 |  | -make_affect(affect::NamedTuple; kwargs...) = FunctionalAffect(; affect...) | 
|  | 215 | +make_affect(affect::Tuple; kwargs...) = ImperativeAffect(affect...) | 
|  | 216 | +make_affect(affect::NamedTuple; kwargs...) = ImperativeAffect(; affect...) | 
| 268 | 217 | make_affect(affect::Affect; kwargs...) = affect | 
| 269 | 218 | 
 | 
| 270 | 219 | function make_affect(affect::Vector{Equation}; discrete_parameters = Any[], | 
| @@ -446,7 +395,7 @@ struct SymbolicDiscreteCallback <: AbstractCallback | 
| 446 | 395 |         c = is_timed_condition(condition) ? condition : value(scalarize(condition)) | 
| 447 | 396 | 
 | 
| 448 | 397 |         if isnothing(reinitializealg) | 
| 449 |  | -            if any(a -> (a isa FunctionalAffect || a isa ImperativeAffect), | 
|  | 398 | +            if any(a -> a isa ImperativeAffect, | 
| 450 | 399 |                 [affect, initialize, finalize]) | 
| 451 | 400 |                 reinitializealg = SciMLBase.CheckInit() | 
| 452 | 401 |             else | 
|  | 
| 498 | 447 | ############################################ | 
| 499 | 448 | ########## Namespacing Utilities ########### | 
| 500 | 449 | ############################################ | 
| 501 |  | -function namespace_affects(affect::FunctionalAffect, s) | 
| 502 |  | -    FunctionalAffect(func(affect), | 
| 503 |  | -        renamespace.((s,), unknowns(affect)), | 
| 504 |  | -        unknowns_syms(affect), | 
| 505 |  | -        renamespace.((s,), parameters(affect)), | 
| 506 |  | -        parameters_syms(affect), | 
| 507 |  | -        renamespace.((s,), discretes(affect)), | 
| 508 |  | -        context(affect)) | 
| 509 |  | -end | 
| 510 |  | - | 
| 511 | 450 | function namespace_affects(affect::AffectSystem, s) | 
| 512 | 451 |     AffectSystem(renamespace(s, system(affect)), | 
| 513 | 452 |         renamespace.((s,), unknowns(affect)), | 
| @@ -652,36 +591,6 @@ function compile_condition( | 
| 652 | 591 |     return CompiledCondition{is_discrete(cbs)}(fs) | 
| 653 | 592 | end | 
| 654 | 593 | 
 | 
| 655 |  | -""" | 
| 656 |  | -Compile user-defined functional affect. | 
| 657 |  | -""" | 
| 658 |  | -function compile_functional_affect(affect::FunctionalAffect, sys; kwargs...) | 
| 659 |  | -    dvs = unknowns(sys) | 
| 660 |  | -    ps = parameters(sys) | 
| 661 |  | -    dvs_ind = Dict(reverse(en) for en in enumerate(dvs)) | 
| 662 |  | -    v_inds = map(sym -> dvs_ind[sym], unknowns(affect)) | 
| 663 |  | - | 
| 664 |  | -    if has_index_cache(sys) && (ic = get_index_cache(sys)) !== nothing | 
| 665 |  | -        p_inds = [(pind = parameter_index(sys, sym)) === nothing ? sym : pind | 
| 666 |  | -                  for sym in parameters(affect)] | 
| 667 |  | -    else | 
| 668 |  | -        ps_ind = Dict(reverse(en) for en in enumerate(ps)) | 
| 669 |  | -        p_inds = map(sym -> get(ps_ind, sym, sym), parameters(affect)) | 
| 670 |  | -    end | 
| 671 |  | -    # HACK: filter out eliminated symbols. Not clear this is the right thing to do | 
| 672 |  | -    # (MTK should keep these symbols) | 
| 673 |  | -    u = filter(x -> !isnothing(x[2]), collect(zip(unknowns_syms(affect), v_inds))) |> | 
| 674 |  | -        NamedTuple | 
| 675 |  | -    p = filter(x -> !isnothing(x[2]), collect(zip(parameters_syms(affect), p_inds))) |> | 
| 676 |  | -        NamedTuple | 
| 677 |  | - | 
| 678 |  | -    let u = u, p = p, user_affect = func(affect), ctx = context(affect) | 
| 679 |  | -        (integ) -> begin | 
| 680 |  | -            user_affect(integ, u, p, ctx) | 
| 681 |  | -        end | 
| 682 |  | -    end | 
| 683 |  | -end | 
| 684 |  | - | 
| 685 | 594 | is_discrete(cb::AbstractCallback) = cb isa SymbolicDiscreteCallback | 
| 686 | 595 | is_discrete(cb::Vector{<:AbstractCallback}) = eltype(cb) isa SymbolicDiscreteCallback | 
| 687 | 596 | 
 | 
| @@ -837,7 +746,7 @@ function compile_affect( | 
| 837 | 746 |     elseif aff isa AffectSystem | 
| 838 | 747 |         f = compile_equational_affect(aff, sys; kwargs...) | 
| 839 | 748 |         wrap_save_discretes(f, save_idxs) | 
| 840 |  | -    elseif aff isa FunctionalAffect || aff isa ImperativeAffect | 
|  | 749 | +    elseif aff isa ImperativeAffect | 
| 841 | 750 |         f = compile_functional_affect(aff, sys; kwargs...) | 
| 842 | 751 |         wrap_save_discretes(f, save_idxs) | 
| 843 | 752 |     end | 
| @@ -946,7 +855,8 @@ function compile_equational_affect( | 
| 946 | 855 |         end | 
| 947 | 856 |     else | 
| 948 | 857 |         return let dvs_to_update = dvs_to_update, aff_map = aff_map, sys_map = sys_map, | 
| 949 |  | -            affsys = affsys, ps_to_update = ps_to_update, aff = aff, sys = sys | 
|  | 858 | +            affsys = affsys, ps_to_update = ps_to_update, aff = aff, sys = sys, | 
|  | 859 | +            reset_jumps = reset_jumps | 
| 950 | 860 | 
 | 
| 951 | 861 |             dvs_to_access = [aff_map[u] for u in unknowns(affsys)] | 
| 952 | 862 |             ps_to_access = [unPre(p) for p in parameters(affsys)] | 
| @@ -979,6 +889,8 @@ function compile_equational_affect( | 
| 979 | 889 | 
 | 
| 980 | 890 |                 u_setter!(integ, u_getter(affsol)) | 
| 981 | 891 |                 p_setter!(integ, p_getter(affsol)) | 
|  | 892 | + | 
|  | 893 | +                reset_jumps && reset_aggregated_jumps!(integ) | 
| 982 | 894 |             end | 
| 983 | 895 |         end | 
| 984 | 896 |     end | 
|  | 
0 commit comments