Hi there,
I am trying to build a ReactionSystem
with time-varying parameters using ReactionNetworkImporters.jl
function loadrxnetwork()
. I want to initialize the network with placeholder time-varying kinetic parameters and load the time-varying kinetic functions at the time of solving the system. I’ve tried a couple different versions with no success - can anybody help me out?
Here is an example:
using Catalyst, ModelingToolkit, DataInterpolations, OrdinaryDiffEq, Plots, Latexify
# Step 1: Symbolics
@variables t
@species S(t)[1:3] # S₁(t), S₂(t), S₃(t)
@parameters k[1:5](..) # time-varying kinetic parameters: k₁(t), ..., k₅(t)
# Step 2: Stoichiometry
substoich = [2 0 1 0 0;
0 1 1 0 0;
0 0 0 1 3]
prodstoich = [0 2 0 1 3;
1 0 0 1 0;
0 0 1 0 0]
# Step 3: MatrixNetwork
species_vec = collect(S)
param_vec = collect(k)
mn = MatrixNetwork(param_vec, substoich, prodstoich; species = species_vec, params = param_vec)
prn = loadrxnetwork(mn)
rn = complete(prn.rn)
At this point, ideally we would have a ReactionSystem
that can take in time-varying kinetic parameters k1..5(t)
. However, this fails due to
ArgumentError: k[1] is not a parameter.
From poking around it seems that loading a network in this way will only allow symbolic variables, not functions to be parameters. However, if you start by defining k1..5
as symbolic variables you cannot later swap them out to be time-dependent.
The ideal use case would look something like the code below. This would allow users to generate more general ReactionSystems
and later add custom kinetic functions.
# Step 4: Initial conditions
u0 = [S[1] => 1.0, S[2] => 0.0, S[3] => 0.0]
tspan = (0.0, 10.0)
# Step 5: Time-dependent parameter definitions using DataInterpolations
t_vals = range(tspan[1], tspan[2], length=101)
light_curves = [rand(length(t_vals)) for _ in 1:5] # some time-varying input that impacts kinetics, perhaps a response to light
k_funcs = [LinearInterpolation(c, t_vals) for c in light_curves] # k_i(t) = interpolated time series
# Step 6: Build ODEProblem
ps = Dict(k[i](t) => k_funcs[i] for i in 1:5) # <- Assign time-dependent functions to symbolic time-dependent params
prob = ODEProblem(rn, u0, tspan, ps)
sol = solve(prob)
# Step 7: Plot
plot(sol)
Am I missing something? I haven’t been able to find useful examples where time varying kinetics are updated after the system is built, though it seems that constant parameters can be fairly easily updated following a similar pattern. I’ve attempted a couple of versions trying to construct the network by interpolating the variables into the network, but I havent been able to get the $
syntax to work.
This code draws on the examples here:
loading from a matrix representation
interpolating a time varying parameter
using a custom kinetic function
interpolating variables into the DSL