@@ -92,60 +92,76 @@ funcdict = Dict{Symbol, Function}() #Stores user def
92
92
93
93
# Coordination function, actually does all the work of the macro.
94
94
function coordinate (name, ex:: Expr , p, scale_noise)
95
- reactions = get_reactions (ex) :: Vector{ReactionStruct}
96
- reactants = get_reactants (reactions) :: OrderedDict{Symbol,Int}
97
- parameters = get_parameters (p) :: OrderedDict{Symbol,Int}
95
+
96
+ # minimal reaction network components
97
+ (reactions, reactants, parameters, syms, params) = get_minnetwork (ex, p)
98
+
99
+ # expressions for ODEs
100
+ (f_expr, f, f_rhs, symjac, f_symfuncs) = genode_exprs (reactions, reactants, parameters, syms)
101
+ odefun = :(ODEFunction (f; syms= $ syms))
98
102
99
- syms = collect ( keys (reactants))
100
- params = collect ( keys ( parameters) )
101
- ( in ( :t , union (syms,params))) && error ( " t is reserved for the time variable and may neither be used as a reactant nor a parameter " )
103
+ # expressions for SDEs
104
+ (g_expr, g, g_funcs, p_matrix) = gensde_exprs (reactions, reactants, parameters, scale_noise )
105
+ sdefun = :( SDEFunction (f, g; syms = $ syms) )
102
106
103
- update_reaction_info (reactions,syms)
107
+ # expressions for jumps
108
+ (jump_rate_expr, jump_affect_expr, jumps, regular_jumps) = get_jumps (reactions, reactants, parameters)
104
109
105
- f_expr = get_f (reactions, reactants)
106
- f = make_func (f_expr, reactants, parameters)
110
+ # Build the type
111
+ exprs = Vector {Expr} (undef,0 )
112
+ typeex,constructorex = maketype (DiffEqBase. AbstractReactionNetwork, name, f, f_rhs, f_symfuncs, g, g_funcs, jumps, regular_jumps, Meta. quot (jump_rate_expr), Meta. quot (jump_affect_expr), p_matrix, syms, scale_noise; params= params, reactions= reactions, symjac= symjac, syms_to_ints= reactants, params_to_ints= parameters, odefun= odefun, sdefun= sdefun)
113
+ push! (exprs,typeex)
114
+ push! (exprs,constructorex)
107
115
108
- g_expr = get_g (reactions, reactants, scale_noise)
109
- g = make_func (g_expr, reactants, parameters)
110
- p_matrix = zeros (length (reactants), length (reactions))
116
+ # add type functions
117
+ append! (exprs, gentypefun_exprs (name))
111
118
112
- (jump_rate_expr, jump_affect_expr, jumps, regular_jumps) = get_jumps (reactions, reactants, parameters)
119
+ # return as one expression block
120
+ expr_arr_to_block (exprs)
121
+ end
113
122
114
- f_rhs = [element. args[2 ] for element in f_expr]
115
- symjac = Expr (:quote , calculate_jac (deepcopy (f_rhs), syms))
116
- f_symfuncs = hcat ([SymEngine. Basic (f) for f in f_rhs])
123
+ # min_reaction_network coordination function, actually does all the work of the macro.
124
+ function min_coordinate (name, ex:: Expr , p, scale_noise)
125
+
126
+ # minimal reaction network components
127
+ (reactions, reactants, parameters, syms, params) = get_minnetwork (ex, p)
117
128
118
129
# Build the type
119
130
exprs = Vector {Expr} (undef,0 )
120
-
121
- # # only get the right-hand-side of the equations.
122
- f_funcs = [element. args[2 ] for element in f_expr]
123
- g_funcs = [element. args[2 ] for element in g_expr]
124
-
125
- odefun = :(ODEFunction (f; syms= $ syms))
126
- sdefun = :(SDEFunction (f, g; syms= $ syms))
127
- typeex,constructorex = maketype (DiffEqBase. AbstractReactionNetwork, name, f, f_funcs, f_symfuncs, g, g_funcs, jumps, regular_jumps, Meta. quot (jump_rate_expr), Meta. quot (jump_affect_expr), p_matrix, syms, scale_noise; params= params, reactions= reactions, symjac= symjac, syms_to_ints= reactants, params_to_ints= parameters, odefun= odefun, sdefun= sdefun)
128
-
131
+ typeex,constructorex = maketype (DiffEqBase. AbstractReactionNetwork, name, nothing , nothing , nothing , nothing , nothing , nothing , nothing , nothing , nothing , nothing , syms, scale_noise; params= params, reactions= reactions, symjac= nothing , syms_to_ints= reactants, params_to_ints= parameters)
129
132
push! (exprs,typeex)
130
133
push! (exprs,constructorex)
131
134
132
- # # Overload the type so that it can act as a function.
133
- overloadex = :(((f:: $name ))(du, u, p, t:: Number ) = f. f (du, u, p, t)) |> esc
134
- push! (exprs,overloadex)
135
+ # add type functions
136
+ append! (exprs, gentypefun_exprs (name, gen_inplace= false , gen_outofplace= false ))
135
137
136
- # # Add a method which allocates the `du` and returns it instead of being inplace
137
- overloadex = :(((f :: $name ))(u,p,t :: Number ) = (du = similar (u); f (du,u,p,t); du)) |> esc
138
- push! (exprs,overloadex)
138
+ # return as one expression block
139
+ expr_arr_to_block (exprs)
140
+ end
139
141
140
- # export type constructor
141
- def_const_ex = :(($ name)()) |> esc
142
- push! (exprs,def_const_ex)
142
+ # SDE expressions
143
+ function gensde_exprs (reactions, reactants, parameters, scale_noise)
144
+ g_expr = get_g (reactions, reactants, scale_noise)
145
+ g = make_func (g_expr, reactants, parameters)
146
+ g_funcs = [element. args[2 ] for element in g_expr]
147
+ p_matrix = zeros (length (reactants), length (reactions))
143
148
144
- expr_arr_to_block (exprs )
149
+ (g_expr,g,g_funcs,p_matrix )
145
150
end
146
151
147
- # min_reaction_network coordination function, actually does all the work of the macro.
148
- function min_coordinate (name, ex:: Expr , p, scale_noise)
152
+ # ODE expressions
153
+ function genode_exprs (reactions, reactants, parameters, syms)
154
+ f_expr = get_f (reactions, reactants)
155
+ f = make_func (f_expr, reactants, parameters)
156
+ f_rhs = [element. args[2 ] for element in f_expr]
157
+ symjac = Expr (:quote , calculate_jac (deepcopy (f_rhs), syms))
158
+ f_symfuncs = hcat ([SymEngine. Basic (f) for f in f_rhs])
159
+
160
+ (f_expr,f,f_rhs,symjac,f_symfuncs)
161
+ end
162
+
163
+ # generate the minimal network components
164
+ function get_minnetwork (ex:: Expr , p)
149
165
reactions = get_reactions (ex) :: Vector{ReactionStruct}
150
166
reactants = get_reactants (reactions) :: OrderedDict{Symbol,Int}
151
167
parameters = get_parameters (p) :: OrderedDict{Symbol,Int}
@@ -156,18 +172,7 @@ function min_coordinate(name, ex::Expr, p, scale_noise)
156
172
157
173
update_reaction_info (reactions,syms)
158
174
159
- # Build the type
160
- exprs = Vector {Expr} (undef,0 )
161
- typeex,constructorex = maketype (DiffEqBase. AbstractReactionNetwork, name, nothing , nothing , nothing , nothing , nothing , nothing , nothing , nothing , nothing , nothing , syms, scale_noise; params= params, reactions= reactions, symjac= nothing , syms_to_ints= reactants, params_to_ints= parameters)
162
-
163
- push! (exprs,typeex)
164
- push! (exprs,constructorex)
165
-
166
- # export type constructor
167
- def_const_ex = :(($ name)()) |> esc
168
- push! (exprs,def_const_ex)
169
-
170
- expr_arr_to_block (exprs)
175
+ (reactions,reactants,parameters,syms,params)
171
176
end
172
177
173
178
# Generates a vector containing a number of reaction structures, each containing the infromation about one reaction.
@@ -362,7 +367,7 @@ function make_func(func_expr::Vector{Expr},reactants::OrderedDict{Symbol,Int}, p
362
367
end
363
368
364
369
# Creates expressions for jump affects and rates. Also creates and array with MassAction, ConstantRate and VariableRate Jumps.
365
- function get_jumps (reactions:: Vector{ReactionStruct} , reactants:: OrderedDict{Symbol,Int} , parameters:: OrderedDict{Symbol,Int} )
370
+ function get_jumps (reactions:: Vector{ReactionStruct} , reactants:: OrderedDict{Symbol,Int} , parameters:: OrderedDict{Symbol,Int} ; minimal_jumps = false )
366
371
rates = Vector {Any} (undef,length (reactions))
367
372
affects = Vector {Vector{Expr}} (undef,length (reactions))
368
373
jumps = Expr (:tuple )
@@ -375,17 +380,19 @@ function get_jumps(reactions::Vector{ReactionStruct}, reactants::OrderedDict{Sym
375
380
reactant_set = union (getfield .(reaction. products, :reactant ),getfield .(reaction. substrates, :reactant ))
376
381
foreach (r -> push! (affects[idx],:(@inbounds integrator. u[$ (reactants[r])] += $ (get_stoch_diff (reaction,r)))), reactant_set)
377
382
syntax_rate = recursive_replace! (deepcopy (rates[idx]), (reactants,:internal_var___u ), (parameters, :internal_var___p ))
378
- # if reaction.is_pure_mass_action
383
+
384
+ if minimal_jumps && reaction. is_pure_mass_action
385
+ recursive_contains (:t ,rates[idx]) && push! (jumps. args,Expr (:call ,:VariableRateJump ))
379
386
# ma_sub_stoch = :(reactant_stoich = [[]])
380
387
# ma_stoch_change = :(reactant_stoich = [[]])
381
388
# foreach(sub -> push!(ma_sub_stoch.args[2].args[1].args),:($(reactants[sub.reactant])=>$(sub.stoichiometry)),reaction.substrates)
382
389
# foreach(reactant -> push!(ma_stoch_change.args[2].args[1].args),:($(reactants[reactant.reactant])=>$(get_stoch_diff(reaction,reactant))),reaction.substrates)
383
390
# push!(jumps.args,:(MassActionJump($(reaction.rate_org),$(ma_sub_stoch),$(ma_stoch_change))))
384
- # else
391
+ else
385
392
recursive_contains (:t ,rates[idx]) ? push! (jumps. args,Expr (:call ,:VariableRateJump )) : push! (jumps. args,Expr (:call ,:ConstantRateJump ))
386
393
push! (jumps. args[idx]. args, :((internal_var___u,internal_var___p,t) -> $ syntax_rate))
387
394
push! (jumps. args[idx]. args, :(integrator -> $ (expr_arr_to_block (deepcopy (affects[idx])))))
388
- # end
395
+ end
389
396
push! (reg_rates. args,:(internal_var___out[$ idx]= $ syntax_rate))
390
397
foreach (r -> push! (reg_c. args,:(internal_var___dc[$ (reactants[r]),$ idx]= $ (get_stoch_diff (reaction,r)))), reactant_set)
391
398
end
0 commit comments