@@ -52,7 +52,6 @@ function get_netstoich(subs, prods, sstoich, pstoich)
5252 ns
5353end
5454
55-
5655struct ReactionSystem <: AbstractSystem
5756 eqs:: Vector{Reaction}
5857 iv:: Variable
@@ -121,46 +120,56 @@ function assemble_diffusion(rs)
121120 eqs
122121end
123122
124- function assemble_jumps (rs)
125- eqs = Vector {Union{ConstantRateJump, MassActionJump, VariableRateJump}} ()
126-
127- for rx in rs. eqs
128- rl = jumpratelaw (rx)
129- affect = Vector {Equation} ()
130- for (spec,stoich) in rx. netstoich
131- push! (affect,var2op (spec) ~ var2op (spec) + stoich)
132- end
133- if any (isequal .(var2op (rs. iv),get_variables (rx. rate)))
134- push! (eqs,VariableRateJump (rl,affect))
135- elseif rx. only_use_rate || any ([isequal (state,r_op) for state in rs. states, r_op in getfield .(get_variables (rx. rate),:op )])
136- push! (eqs,ConstantRateJump (rl,affect))
137- else
138- reactant_stoch = isempty (rx. substoich) ? [0 => 1 ] : Pair .(var2op .(getfield .(rx. substrates,:op )),rx. substoich)
139- net_stoch = map (p -> Pair (var2op (p[1 ]),p[2 ]),rx. netstoich)
140- push! (eqs,MassActionJump (rx. rate, reactant_stoch, net_stoch))
141- end
142- end
143- eqs
123+ function var2op (var)
124+ Operation (var,Vector {Expression} ())
144125end
145126
146127# Calculate the Jump rate law (like ODE, but uses X instead of X(t).
147128# The former generates a "MethodError: objects of type Int64 are not callable" when trying to solve the problem.
148- function jumpratelaw (rx)
129+ function jumpratelaw (rx; rxvars = get_variables (rx . rate) )
149130 @unpack rate, substrates, substoich, only_use_rate = rx
150- rl = deepcopy ( rate)
151- for op in get_variables (rx . rate)
152- rl = substitute (rl,op => var2op (op. op))
131+ rl = rate
132+ for op in rxvars
133+ rl = substitute (rl, op => var2op (op. op))
153134 end
154135 if ! only_use_rate
155136 for (i,stoich) in enumerate (substoich)
156- rl *= isone (stoich) ? var2op (substrates[i]. op) : Operation (binomial,[var2op (substrates[i]. op),stoich])
137+ rl *= isone (stoich) ? var2op (substrates[i]. op) : Operation (binomial,[var2op (substrates[i]. op),stoich])
157138 end
158139 end
159140 rl
160141end
161142
162- function var2op (var)
163- Operation (var,Vector {Expression} ())
143+ # if haveivdep=false then time dependent rates will still be classified as mass action
144+ function ismassaction (rx, rs; rxvars = get_variables (rx. rate),
145+ haveivdep = any (var -> isequal (rs. iv,convert (Variable,var)), rxvars))
146+ return ! (haveivdep || rx. only_use_rate || any (convert (Variable,rxv) in states (rs) for rxv in rxvars))
147+ end
148+
149+ function assemble_jumps (rs)
150+ eqs = Vector {Union{ConstantRateJump, MassActionJump, VariableRateJump}} ()
151+
152+ for rx in equations (rs)
153+ rxvars = get_variables (rx. rate)
154+ haveivdep = any (var -> isequal (rs. iv,convert (Variable,var)), rxvars)
155+ if ismassaction (rx, rs; rxvars= rxvars, haveivdep= haveivdep)
156+ reactant_stoch = isempty (rx. substoich) ? [0 => 1 ] : [var2op (sub. op) => stoich for (sub,stoich) in zip (rx. substrates,rx. substoich)]
157+ net_stoch = [Pair (var2op (p[1 ]),p[2 ]) for p in rx. netstoich]
158+ push! (eqs, MassActionJump (rx. rate, reactant_stoch, net_stoch))
159+ else
160+ rl = jumpratelaw (rx, rxvars= rxvars)
161+ affect = Vector {Equation} ()
162+ for (spec,stoich) in rx. netstoich
163+ push! (affect, var2op (spec) ~ var2op (spec) + stoich)
164+ end
165+ if haveivdep
166+ push! (eqs, VariableRateJump (rl,affect))
167+ else
168+ push! (eqs, ConstantRateJump (rl,affect))
169+ end
170+ end
171+ end
172+ eqs
164173end
165174
166175function Base. convert (:: Type{<:ODESystem} ,rs:: ReactionSystem )
0 commit comments