@@ -88,6 +88,11 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem
88
88
"""
89
89
connector_type:: Any
90
90
"""
91
+ A `Vector{SymbolicContinuousCallback}` that model events.
92
+ The integrator will use root finding to guarantee that it steps at each zero crossing.
93
+ """
94
+ continuous_events:: Vector{SymbolicContinuousCallback}
95
+ """
91
96
A `Vector{SymbolicDiscreteCallback}` that models events. Symbolic
92
97
analog to `SciMLBase.DiscreteCallback` that executes an affect when a given condition is
93
98
true at the end of an integration step. Note, one must make sure to call
@@ -120,8 +125,7 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem
120
125
121
126
function JumpSystem {U} (
122
127
tag, ap:: U , iv, unknowns, ps, var_to_name, observed, name, description,
123
- systems,
124
- defaults, connector_type, devents, parameter_dependencies,
128
+ systems, defaults, connector_type, cevents, devents, parameter_dependencies,
125
129
metadata = nothing , gui_metadata = nothing ,
126
130
complete = false , index_cache = nothing , isscheduled = false ;
127
131
checks:: Union{Bool, Int} = true ) where {U <: ArrayPartition }
@@ -136,8 +140,8 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractTimeDependentSystem
136
140
end
137
141
new {U} (tag, ap, iv, unknowns, ps, var_to_name,
138
142
observed, name, description, systems, defaults,
139
- connector_type, devents, parameter_dependencies, metadata, gui_metadata ,
140
- complete, index_cache, isscheduled)
143
+ connector_type, cevents, devents, parameter_dependencies, metadata,
144
+ gui_metadata, complete, index_cache, isscheduled)
141
145
end
142
146
end
143
147
function JumpSystem (tag, ap, iv, states, ps, var_to_name, args... ; kwargs... )
@@ -194,26 +198,28 @@ function JumpSystem(eqs, iv, unknowns, ps;
194
198
# this and the treatment of continuous events are the only part
195
199
# unique to JumpSystems
196
200
eqs = scalarize .(eqs)
197
- ap = ArrayPartition (MassActionJump[], ConstantRateJump[], VariableRateJump[])
201
+ ap = ArrayPartition (
202
+ MassActionJump[], ConstantRateJump[], VariableRateJump[], Equation[])
198
203
for eq in eqs
199
204
if eq isa MassActionJump
200
205
push! (ap. x[1 ], eq)
201
206
elseif eq isa ConstantRateJump
202
207
push! (ap. x[2 ], eq)
203
208
elseif eq isa VariableRateJump
204
209
push! (ap. x[3 ], eq)
210
+ elseif eq isa Equation
211
+ push! (ap. x[4 ], eq)
205
212
else
206
- error (" JumpSystem equations must contain MassActionJumps, ConstantRateJumps, or VariableRateJumps ." )
213
+ error (" JumpSystem equations must contain MassActionJumps, ConstantRateJumps, VariableRateJumps, or Equations ." )
207
214
end
208
215
end
209
216
210
- (continuous_events === nothing ) ||
211
- error (" JumpSystems currently only support discrete events." )
217
+ cont_callbacks = SymbolicContinuousCallbacks (continuous_events)
212
218
disc_callbacks = SymbolicDiscreteCallbacks (discrete_events)
213
219
214
220
JumpSystem {typeof(ap)} (Threads. atomic_add! (SYSTEM_COUNT, UInt (1 )),
215
221
ap, iv′, us′, ps′, var_to_name, observed, name, description, systems,
216
- defaults, connector_type, disc_callbacks, parameter_dependencies,
222
+ defaults, connector_type, cont_callbacks, disc_callbacks, parameter_dependencies,
217
223
metadata, gui_metadata, checks = checks)
218
224
end
219
225
245
251
has_massactionjumps (js:: JumpSystem ) = ! isempty (equations (js). x[1 ])
246
252
has_constantratejumps (js:: JumpSystem ) = ! isempty (equations (js). x[2 ])
247
253
has_variableratejumps (js:: JumpSystem ) = ! isempty (equations (js). x[3 ])
254
+ has_equations (js:: JumpSystem ) = ! isempty (equations (js). x[4 ])
248
255
249
256
function generate_rate_function (js:: JumpSystem , rate)
250
257
consts = collect_constants (rate)
@@ -281,7 +288,7 @@ function assemble_vrj(
281
288
outputidxs = [unknowntoid[var] for var in outputvars]
282
289
affect = eval_or_rgf (generate_affect_function (js, vrj. affect!, outputidxs);
283
290
eval_expression, eval_module)
284
- VariableRateJump (rate, affect)
291
+ VariableRateJump (rate, affect; save_positions = vrj . save_positions )
285
292
end
286
293
287
294
function assemble_vrj_expr (js, vrj, unknowntoid)
@@ -390,6 +397,11 @@ function DiffEqBase.DiscreteProblem(sys::JumpSystem, u0map, tspan::Union{Tuple,
390
397
if ! iscomplete (sys)
391
398
error (" A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`" )
392
399
end
400
+
401
+ if has_equations (sys) || (! isempty (continuous_events (sys)))
402
+ error (" The passed in JumpSystem contains `Equation`s or continuous events, please use a problem type that supports these features, such as ODEProblem." )
403
+ end
404
+
393
405
_, u0, p = process_SciMLProblem (EmptySciMLFunction, sys, u0map, parammap;
394
406
t = tspan === nothing ? nothing : tspan[1 ], use_union, tofloat = false , check_length = false )
395
407
f = DiffEqBase. DISCRETE_INPLACE_DEFAULT
@@ -478,14 +490,24 @@ function DiffEqBase.ODEProblem(sys::JumpSystem, u0map, tspan::Union{Tuple, Nothi
478
490
error (" A completed `JumpSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `DiscreteProblem`" )
479
491
end
480
492
481
- _, u0, p = process_SciMLProblem (EmptySciMLFunction, sys, u0map, parammap;
482
- t = tspan === nothing ? nothing : tspan[1 ], use_union, tofloat = false , check_length = false )
483
-
484
- observedfun = ObservedFunctionCache (sys; eval_expression, eval_module)
485
-
486
- f = (du, u, p, t) -> (du .= 0 ; nothing )
487
- df = ODEFunction (f; sys, observed = observedfun)
488
- ODEProblem (df, u0, tspan, p; kwargs... )
493
+ # forward everything to be an ODESystem but the jumps and discrete events
494
+ if has_equations (sys)
495
+ osys = ODESystem (equations (sys). x[4 ], get_iv (sys), unknowns (sys), parameters (sys);
496
+ observed = observed (sys), name = nameof (sys), description = description (sys),
497
+ systems = get_systems (sys), defaults = defaults (sys),
498
+ parameter_dependencies = parameter_dependencies (sys),
499
+ metadata = get_metadata (sys), gui_metadata = get_gui_metadata (sys))
500
+ osys = complete (osys)
501
+ return ODEProblem (osys, u0map, tspan, parammap; check_length = false , kwargs... )
502
+ else
503
+ _, u0, p = process_SciMLProblem (EmptySciMLFunction, sys, u0map, parammap;
504
+ t = tspan === nothing ? nothing : tspan[1 ], use_union, tofloat = false ,
505
+ check_length = false )
506
+ f = (du, u, p, t) -> (du .= 0 ; nothing )
507
+ observedfun = ObservedFunctionCache (sys; eval_expression, eval_module)
508
+ df = ODEFunction (f; sys, observed = observedfun)
509
+ return ODEProblem (df, u0, tspan, p; kwargs... )
510
+ end
489
511
end
490
512
491
513
"""
@@ -521,8 +543,11 @@ function JumpProcesses.JumpProblem(js::JumpSystem, prob,
521
543
for j in eqs. x[2 ]]
522
544
vrjs = VariableRateJump[assemble_vrj (js, j, unknowntoid; eval_expression, eval_module)
523
545
for j in eqs. x[3 ]]
524
- ((prob isa DiscreteProblem) && ! isempty (vrjs)) &&
525
- error (" Use continuous problems such as an ODEProblem or a SDEProblem with VariableRateJumps" )
546
+ if prob isa DiscreteProblem
547
+ if (! isempty (vrjs) || has_equations (js) || ! isempty (continuous_events (js)))
548
+ error (" Use continuous problems such as an ODEProblem or a SDEProblem with VariableRateJumps, coupled differential equations, or continuous events." )
549
+ end
550
+ end
526
551
jset = JumpSet (Tuple (vrjs), Tuple (crjs), nothing , majs)
527
552
528
553
# dep graphs are only for constant rate jumps
0 commit comments