Skip to content

Commit 9e69861

Browse files
committed
up
1 parent 48847d4 commit 9e69861

File tree

3 files changed

+70
-21
lines changed

3 files changed

+70
-21
lines changed

src/spatial_reaction_systems/spatial_ODE_systems.jl

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ struct LatticeTransportODEf{S,T}
88
num_verts::Int64
99
"""The number of species."""
1010
num_species::Int64
11+
"""The indexes of the vertex parameters in the parameter vector (`parameters(lrs)`)."""
12+
vert_p_idxs::Vector{Int64}
13+
"""The indexes of the edge parameters in the parameter vector (`parameters(lrs)`)."""
14+
edge_p_idxs::Vector{Int64}
15+
"""
16+
The non-spatial `ReactionSystem` which was used to create the `LatticeReactionSystem` contain
17+
a set of parameters (either identical to, or a sub set of, `parameters(lrs)`). This vector
18+
contain the indexes of the non-spatial system's parameters in `parameters(lrs)`. These are
19+
required to manage the non-spatial ODEFunction in the spatial call.
20+
"""
21+
nonspatial_rs_p_idxs::Vector{Int64}
1122
"""The values of the parameters that are tied to vertices."""
1223
vert_ps::Vector{Vector{T}}
1324
"""
@@ -17,10 +28,10 @@ struct LatticeTransportODEf{S,T}
1728
the parameter values in a new vertex. To avoid relocating these values repeatedly, we write them
1829
to this vector.
1930
"""
20-
work_vert_ps::Vector{T}
31+
work_ps::Vector{T}
2132
"""
2233
For each parameter in vert_ps, its value is a vector with a length of either num_verts or 1.
23-
To know whenever a parameter's value needs expanding to the work_vert_ps array, its length needs checking.
34+
To know whenever a parameter's value needs expanding to the work_ps array, its length needs checking.
2435
This check is done once, and the value is stored in this array. True means a uniform value.
2536
"""
2637
v_ps_idx_types::Vector{Bool}
@@ -55,7 +66,13 @@ struct LatticeTransportODEf{S,T}
5566
# Records which parameters and rates are uniform and which are not.
5667
v_ps_idx_types = map(vp -> length(vp[2]) == 1, vert_ps)
5768
t_rate_idx_types = map(tr -> size(tr[2]) == (1,1), transport_rates)
58-
69+
70+
# Computes the indexes of various parameters in in the `parameters(lrs)` vector.
71+
vert_p_idxs = subset_indexes_of(vertex_parameters(lrs), parameters(lrs))
72+
edge_p_idxs = subset_indexes_of(edge_parameters(lrs), parameters(lrs))
73+
nonspatial_rs_p_idxs = subset_indexes_of(parameters(reactionsystem(lrs)), parameters(lrs))
74+
75+
# Computes the indexes of the vertex parameters in the vector of parameters.
5976
# Input `vert_ps` is a vector map taking each parameter symbolic to its value (potentially a
6077
# vector). This vector is already sorted according to the order of the parameters. Here, we extract
6178
# its values only and put them into `vert_ps`.
@@ -70,11 +87,12 @@ struct LatticeTransportODEf{S,T}
7087
end
7188
end
7289

73-
# Declares `work_vert_ps` (used as storage during computation) and the edge iterator.
74-
work_vert_ps = zeros(length(vert_ps))
90+
# Declares `work_ps` (used as storage during computation) and the edge iterator.
91+
work_ps = zeros(length(parameters(lrs)))
7592
edge_iterator = Catalyst.edge_iterator(lrs)
76-
new{S,T}(ofunc, num_verts(lrs), num_species(lrs), vert_ps, work_vert_ps,
77-
v_ps_idx_types, transport_rates, t_rate_idx_types, leaving_rates, edge_iterator)
93+
new{S,T}(ofunc, num_verts(lrs), num_species(lrs), vert_p_idxs, edge_p_idxs,
94+
nonspatial_rs_p_idxs, vert_ps, work_ps, v_ps_idx_types, transport_rates,
95+
t_rate_idx_types, leaving_rates, edge_iterator)
7896
end
7997
end
8098

@@ -86,6 +104,17 @@ struct LatticeTransportODEjac{R,S,T}
86104
num_verts::Int64
87105
"""The number of species."""
88106
num_species::Int64
107+
"""The indexes of the vertex parameters in the parameter vector (`parameters(lrs)`)."""
108+
vert_p_idxs::Vector{Int64}
109+
"""The indexes of the edge parameters in the parameter vector (`parameters(lrs)`)."""
110+
edge_p_idxs::Vector{Int64}
111+
"""
112+
The non-spatial `ReactionSystem` which was used to create the `LatticeReactionSystem` contain
113+
a set of parameters (either identical to, or a sub set of, `parameters(lrs)`). This vector
114+
contain the indexes of the non-spatial system's parameters in `parameters(lrs)`. These are
115+
required to manage the non-spatial ODEFunction in the spatial call.
116+
"""
117+
nonspatial_rs_p_idxs::Vector{Int64}
89118
"""The values of the parameters that are tied to vertices."""
90119
vert_ps::Vector{Vector{S}}
91120
"""
@@ -95,10 +124,10 @@ struct LatticeTransportODEjac{R,S,T}
95124
the parameter values in a new vertex. To avoid relocating these values repeatedly, we write them
96125
to this vector.
97126
"""
98-
work_vert_ps::Vector{S}
127+
work_ps::Vector{S}
99128
"""
100129
For each parameter in vert_ps, its value is a vector with a length of either num_verts or 1.
101-
To know whenever a parameter's value needs expanding to the work_vert_ps array, its length needs checking.
130+
To know whenever a parameter's value needs expanding to the work_ps array, its length needs checking.
102131
This check is done once, and the value is stored in this array. True means a uniform value.
103132
"""
104133
v_ps_idx_types::Vector{Bool}
@@ -110,18 +139,30 @@ struct LatticeTransportODEjac{R,S,T}
110139
function LatticeTransportODEjac(ofunc::R, vert_ps::Vector{Pair{BasicSymbolic{Real},Vector{S}}},
111140
jac_transport::Union{Nothing, SparseMatrixCSC{Float64, Int64}},
112141
lrs::LatticeReactionSystem, sparse::Bool) where {R,S}
142+
143+
# Computes the indexes of various parameters in in the `parameters(lrs)` vector.
144+
vert_p_idxs = subset_indexes_of(vertex_parameters(lrs), parameters(lrs))
145+
edge_p_idxs = subset_indexes_of(edge_parameters(lrs), parameters(lrs))
146+
nonspatial_rs_p_idxs = subset_indexes_of(parameters(reactionsystem(lrs)), parameters(lrs))
147+
113148
# Input `vert_ps` is a vector map taking each parameter symbolic to its value (potentially a
114149
# vector). This vector is already sorted according to the order of the parameters. Here, we extract
115150
# its values only and put them into `vert_ps`.
116151
vert_ps = [vp[2] for vp in vert_ps]
117152

118-
work_vert_ps = zeros(num_verts(lrs))
153+
work_ps = zeros(length(parameters(lrs)))
119154
v_ps_idx_types = map(vp -> length(vp) == 1, vert_ps)
120-
new{R,S,typeof(jac_transport)}(ofunc, num_verts(lrs), num_species(lrs) , vert_ps,
121-
work_vert_ps, v_ps_idx_types, sparse, jac_transport)
155+
new{R,S,typeof(jac_transport)}(ofunc, num_verts(lrs), num_species(lrs) , vert_p_idxs,
156+
edge_p_idxs, nonspatial_rs_p_idxs, vert_ps,
157+
work_ps, v_ps_idx_types, sparse, jac_transport)
122158
end
123159
end
124160

161+
# For each symbolic in syms1, returns a vector with their indexes in syms2.
162+
function subset_indexes_of(syms1, syms2)
163+
[findfirst(isequal(sym1, sym2) for sym2 in syms2) for sym1 in syms1]
164+
end
165+
125166
### ODEProblem ###
126167

127168
# Creates an ODEProblem from a LatticeReactionSystem.
@@ -155,7 +196,8 @@ function DiffEqBase.ODEProblem(lrs::LatticeReactionSystem, u0_in, tspan,
155196
combinatoric_ratelaws, remove_conserved, checks)
156197

157198
# Combines `vert_ps` and `edge_ps` to a single vector with values only (not a map). Creates ODEProblem.
158-
ps = [p[2] for p in [vert_ps; edge_ps]]
199+
pval_dict = Dict([vert_ps; edge_ps])
200+
ps = [pval_dict[p] for p in parameters(lrs)]
159201
return ODEProblem(ofun, u0, tspan, ps, args...; kwargs...)
160202
end
161203

@@ -288,7 +330,7 @@ function (f_func::LatticeTransportODEf)(du, u, p, t)
288330
update_work_vert_ps!(f_func, p, vert_i)
289331

290332
# Evaluate reaction contributions to du at vert_i.
291-
f_func.ofunc((@view du[idxs]), (@view u[idxs]), f_func.work_vert_ps, t)
333+
f_func.ofunc((@view du[idxs]), (@view u[idxs]), nonspatial_ps(f_func), t)
292334
end
293335

294336
# s_idx is the species index among transport species, s is the index among all species.
@@ -316,7 +358,7 @@ function (jac_func::LatticeTransportODEjac)(J, u, p, t)
316358
for vert_i in 1:(jac_func.num_verts)
317359
idxs = get_indexes(vert_i, jac_func.num_species)
318360
update_work_vert_ps!(jac_func, p, vert_i)
319-
jac_func.ofunc.jac((@view J[idxs, idxs]), (@view u[idxs]), jac_func.work_vert_ps, t)
361+
jac_func.ofunc.jac((@view J[idxs, idxs]), (@view u[idxs]), nonspatial_ps(jac_func), t)
320362
end
321363

322364
# Updates for the spatial reactions (adds the Jacobian values from the transportation reactions).

src/spatial_reaction_systems/utility.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,21 +268,28 @@ function get_transport_rate(trans_s_idx::Int64, f_func::LatticeTransportODEf, ed
268268
get_transport_rate(f_func.transport_rates[trans_s_idx][2], edge, f_func.t_rate_idx_types[trans_s_idx])
269269
end
270270

271-
# Updates the internal work_vert_ps vector for a given vertex.
271+
# Updates the internal work_ps vector for a given vertex. Updates only the parameters that
272+
# actually are vertex parameters.
272273
# To this vector, we write the system's parameter values at the specific vertex.
273-
function update_work_vert_ps!(work_vert_ps::Vector{S}, all_ps::Vector{T}, vert::Int64,
274-
vert_ps_idx_types::Vector{Bool}) where {S,T}
274+
function update_work_vert_ps!(work_ps::Vector{S}, vert_p_idxs::Vector{Int64}, all_ps::Vector{T},
275+
vert::Int64, vert_ps_idx_types::Vector{Bool}) where {S,T}
275276
# Loops through all parameters.
276277
for (idx,loc_type) in enumerate(vert_ps_idx_types)
277278
# If the parameter is uniform across the spatial structure, it will have a length-1 value vector
278279
# (which value we write to the work vector).
279280
# Else, we extract it value at the specific location.
280-
work_vert_ps[idx] = (loc_type ? all_ps[idx][1] : all_ps[idx][vert])
281+
work_ps[vert_p_idxs[idx]] = (loc_type ? all_ps[vert_p_idxs[idx]][1] : all_ps[vert_p_idxs[idx]][vert])
281282
end
282283
end
283284
# Input is either a LatticeTransportODEf or LatticeTransportODEjac function (which fields we pass on).
284285
function update_work_vert_ps!(lt_ode_func, all_ps::Vector{T}, vert::Int64) where {T}
285-
return update_work_vert_ps!(lt_ode_func.work_vert_ps, all_ps, vert, lt_ode_func.v_ps_idx_types)
286+
return update_work_vert_ps!(lt_ode_func.work_ps, lt_ode_func.vert_p_idxs, all_ps, vert, lt_ode_func.v_ps_idx_types)
287+
end
288+
289+
# Fetches the parameter values that currently are in the work parameter vector and which
290+
# corresponds to the parameters of the non-spatial `ReactionSystem` stored in the `ReactionSystem`.
291+
function nonspatial_ps(lt_ode_func)
292+
return @view lt_ode_func.work_ps[lt_ode_func.nonspatial_rs_p_idxs]
286293
end
287294

288295
# Expands a u0/p information stored in Vector{Vector{}} for to Matrix form

test/spatial_reaction_systems/lattice_reaction_systems_ODEs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ end
8989
# Checks that non-spatial brusselator simulation is identical to all on an unconnected lattice.
9090
let
9191
lrs = LatticeReactionSystem(brusselator_system, brusselator_srs_1, unconnected_graph)
92-
u0 = [:X => 2.0 + 2.0 * rand(rng), :Y => 10.0 + 10.0 * rand(rng)]
92+
u0 = [:X => 2.0 + 2.0 * rand(rng), :Y => 10.0 * (1.0 * rand(rng))]
9393
pV = brusselator_p
9494
pE = [:dX => 0.2]
9595
oprob_nonspatial = ODEProblem(brusselator_system, u0, (0.0, 100.0), pV)

0 commit comments

Comments
 (0)