Skip to content

Commit 49f8edf

Browse files
committed
push event progress
1 parent 9183006 commit 49f8edf

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

src/reactionsystem.jl

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,15 @@ function find_event_vars!(ps, us, events::Vector, ivs, vars)
214214
end
215215
# For a single event, adds quantities from its condition and affect expression(s) to `ps` and `us`.
216216
# Applies `findvars!` to the event's condition (`event[1])` and affec (`event[2]`).
217-
function find_event_vars!(ps, us, event, ivs, vars)
217+
# Two dispatches required, and the event can be given as a MTK structure of a Pair of symbolic expressions/equations.
218+
function find_event_vars!(ps, us, event::Pair, ivs, vars)
218219
findvars!(ps, us, event[1], ivs, vars)
219220
findvars!(ps, us, event[2], ivs, vars)
220221
end
222+
function find_event_vars!(ps, us, event::MT.AbstractCallback, ivs, vars)
223+
findvars!(ps, us, event.conditions, ivs, vars)
224+
findvars!(ps, us, event.affect, ivs, vars)
225+
end
221226

222227
### ReactionSystem Structure ###
223228

@@ -479,7 +484,8 @@ function ReactionSystem(eqs, iv, unknowns, ps;
479484
end
480485

481486
# Creates the continuous and discrete events.
482-
continuous_events, discrete_events = MT.create_symbolic_events(continuous_events, discrete_events)
487+
continuous_events = create_symbolic_events(MT.SymbolicContinuousCallback, continuous_events)
488+
discrete_events = create_symbolic_events(MT.SymbolicDiscreteCallback, discrete_events)
483489

484490
# handles system metadata.
485491
metadata === nothing ? Base.ImmutableDict{Symbol,Any}() : metadata
@@ -501,6 +507,43 @@ function ReactionSystem(iv; kwargs...)
501507
ReactionSystem(Reaction[], iv, [], []; kwargs...)
502508
end
503509

510+
# handles that events can be a single event or a vector.
511+
create_symbolic_events(type, events::Vector) = [create_symbolic_event(type, event) for event in events]
512+
create_symbolic_events(type, event) = [create_symbolic_event(type, event)]
513+
514+
# Converts an input event into a form which ModelingToolkit can handle.
515+
create_symbolic_event(type, event::ModelingToolkit.AbstractCallback) = event
516+
function create_symbolic_event(type, event)
517+
discrete_parameters = find_disc_pars(event[2])
518+
return type(event; discrete_parameters)
519+
end
520+
521+
# Currently, ModelingToolkit requires all parameters which are updated in an event to be specified
522+
# in the event using the `discrete_parameters` keyword argument. Currently, this can only be
523+
# done by manually creating the event using `SymbolicContinuousCallback`/`SymbolicDiscreteCallback`.
524+
# This routines preserves the old behaviour until a new interface have been implemented in MTK.
525+
function find_disc_pars(affects)
526+
discrete_parameters = Set()
527+
for affect in affects
528+
num_disc_pars = length(discrete_parameters)
529+
infer_discrete_parameters!(discrete_parameters, affect.lhs)
530+
infer_discrete_parameters!(discrete_parameters, affect.rhs)
531+
(length(discrete_parameters) > num_disc_pars + 1) && error("Currently, Catalyst only supports having a single parameter outside of a `Pre` statement in event affects.")
532+
end
533+
return collect(discrete_parameters)
534+
end
535+
536+
# Find all `expr`'s parameters that occur *outside* of a Pre(...) statement. Add these to `discrete_parameters`.
537+
function infer_discrete_parameters!(discrete_parameters, expr)
538+
expr_pre_removed = Symbolics.replacenode(expr, precall_to_1)
539+
dynamic_symvars = Symbolics.get_variables(expr_pre_removed)
540+
# Change this coming line to a Symbolic append type of thing.
541+
union!(discrete_parameters, filter(ModelingToolkit.isparameter, dynamic_symvars))
542+
end
543+
# Functions for replacing a Pre-call with a `1.0` (removing its content from an expression).
544+
is_precall(expr) = iscall(expr) ? operation(expr) isa Pre : false
545+
precall_to_1(expr) = (is_precall(expr) ? 1.0 : expr)
546+
504547
# Called internally (whether DSL-based or programmatic model creation is used).
505548
# Creates a sorted reactions + equations vector, also ensuring reaction is first in this vector.
506549
# Extracts potential species, variables, and parameters from the input (if not provided as part of

test/reactionsystem_core/events.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ let
142142
rs2 = ReactionSystem(rxs, t; continuous_events = [ce], discrete_events = de, name = :rs)
143143
rs3 = ReactionSystem(rxs, t; continuous_events = ce, discrete_events = [de], name = :rs)
144144
rs4 = ReactionSystem(rxs, t; continuous_events = [ce], discrete_events = [de], name = :rs)
145-
@test_broken rs1 == rs2 == rs3 == rs4
145+
@test_broken rs1 == rs2 == rs3 == rs4 # https://github.com/SciML/ModelingToolkit.jl/issues/3907
146146
end
147147

148148
# Checks that various various erroneous forms yield errors.
@@ -236,7 +236,7 @@ end
236236
rn_prog = complete(rn_prog)
237237

238238
# Tests that approaches yield identical results.
239-
@test isequal(rn_dsl, rn_prog)
239+
@test isequal(rn_dsl, rn_prog) # https://github.com/SciML/ModelingToolkit.jl/issues/3907
240240

241241
u0 = [X => 6.0, Y => 4.5, Z => 5.5]
242242
tspan = (0.0, 20.0)

0 commit comments

Comments
 (0)