-
-
Notifications
You must be signed in to change notification settings - Fork 82
Description
Describe the bug 🐞
Me again. I am simulating Lotka-Volterra systems, and have recently jumped back on Catalyst.jl for the flexibility and comparison with other solvers (SDEs, SSAs, etc.) other than solving ODEs. However, I find that creating (not solving) the ODEProblem from a ReactionSystem that is sufficiently large takes an incredible amount of time. The time it takes reaches the point where trying to create a problem of medium sizes (~50 species) basically does not finish. Additionally, when using an ODESystem using ModelingToolkit.jl directly, and creating the ODEProblem does not seem to have this issue.
Minimal Reproducible Example 👇
To illustrate, consider the following functions, one using Catalyst.jl, and one using ModelingToolkit.jl. They both create a simple Lotka-Volterra system, that is
Using Catalyst.jl
(note: if there are other/better ways to generate the ReactionSystem, let me know!)
function create_rs(S::Int)
t = default_t()
@parameters r[1:S] A[1:S,1:S]
@species (x(t))[1:S]
#/ Allocate and fill
growthrxs = Array{Reaction}(undef, S)
interactionrxs = Array{Reaction}(undef, S, S)
for i in 1:S
#~ Growth
growthrxs[i] = Reaction(r[i], [x[i]], [x[i]], [1], [2])
#~ Diagonal terms
interactionrxs[i,i] = Reaction(r[i]*A[i,i], [x[i]], [x[i]], [2], [1])
for j in (i+1):S
#~ Off-diagonal terms
interactionrxs[i,j] = Reaction(r[i]*A[i,j], [x[i], x[j]], [x[j]], [1, 1], [1])
interactionrxs[j,i] = Reaction(r[i]*A[j,i], [x[j], x[i]], [x[i]], [1, 1], [1])
end
end
#/ Gather reactions
rxs = [growthrxs..., interactionrxs...]
@named glvrs = ReactionSystem(rxs, t, combinatoric_ratelaws=false)
return Catalyst.complete(glvrs)
endUsing ModelingToolkit.jl
function create_ODESystem(S::Int)
#/ Define variables and parameters
@variables (x(t))[1:S]
@parameters r[1:S] A[1:S,1:S]
eqns = [D(x[i]) ~ r[i]*x[i]*(1.0 - sum([A[i,j]*x[j] for j in 1:S])) for i in 1:S]
@named odesys = ODESystem(eqns, t)
return ModelingToolkit.complete(odesys)
endThen, running the following:
julia> using BenchmarkTools
julia> S = 16;
julia> rs = create_rs(S);
julia> osys = create_ODESystem(S);
julia> rsprob = create_ODEProblem(rs);
julia> osprob = create_ODEProblem(osys);
julia> @btime rsprob = create_ODEProblem(rs);
2.235 s (4388516 allocations: 242.32 MiB)
julia> @btime rsprob = create_ODEProblem(rs);
2.241 s (4388516 allocations: 242.32 MiB)
julia> @btime osprob = create_ODEProblem(osys);
13.086 ms (163580 allocations: 9.05 MiB)
julia> @btime osprob = create_ODEProblem(osys);
13.267 ms (163580 allocations: 9.05 MiB)From this the problem is already apparent; about two orders of magnitude longer time is needed to create the ODEProblem from the ReactionSystem. This issue is even more pressing the larger the no. of species S.
Now, I know I have read somewhere that it is expected to take a bit longer. But even converting the ReactionSystem to an ODESystem, i.e. using convert(ODESystem, rs), and then making the ODEProblem does not change anything for me.
Can someone explain to me what is going on? Am I missing something? Why does creating the ODEProblem takes so much time (and memory)? Why is this different from the ModelingToolkit.jl implementation?
I would like to learn how to do this properly, as I really would like to use the ReactionSystem to create other types of problems, such as SDEProblem, and JumpProblem -- which I think is one of the main selling points for using Catalyst.jl.
Any help or comments are greatly appreciated!
Environment (please complete the following information):
Details
[c7e460c6] ArgParse v1.2.0
[ec485272] ArnoldiMethod v0.4.0
[6e4b80f9] BenchmarkTools v1.5.0
[336ed68f] CSV v0.10.14
[13f3f980] CairoMakie v0.12.9
[479239e8] Catalyst v14.4.1
[5ae59095] Colors v0.12.11
[861a8166] Combinatorics v1.0.2
[a93c6f00] DataFrames v1.6.1
[0c46a032] DifferentialEquations v7.14.0
[31c24e10] Distributions v0.25.111
[ffbed154] DocStringExtensions v0.9.3
[e30172f5] Documenter v1.7.0
[d872a56f] ElectronDisplay v1.0.1
[d4d017d3] ExponentialUtilities v1.26.1
[68837c9b] FHist v0.11.6
[86223c79] Graphs v1.11.2
[033835bb] JLD2 v0.5.1
[ccbc3e58] JumpProcesses v9.13.7
[b964fa9f] LaTeXStrings v1.3.1
[23fbe1c1] Latexify v0.16.5
[2fda8390] LsqFit v0.15.0
[961ee093] ModelingToolkit v9.39.1
[2774e3e8] NLsolve v4.5.1
[77ba4419] NaNMath v1.0.2
[67456a42] OhMyThreads v0.6.0
[1dea7af3] OrdinaryDiffEq v6.89.0
[91a5bcdd] Plots v1.40.8
[1fd47b50] QuadGK v2.11.0
[0bca4576] SciMLBase v2.53.0
[a9a3c162] SparseArrayKit v0.3.1
[276daf66] SpecialFunctions v2.4.0
[0c5d862f] Symbolics v6.11.0
[bd369af6] Tables v1.12.0
[3a884ed6] UnPack v1.0.2
[8ba89e20] Distributed
[37e2e46d] LinearAlgebra
[9a3f8284] Random
[2f01184e] SparseArrays v1.10.0
[10745b16] Statistics v1.10.0julia> versioninfo()
Julia Version 1.10.4
Commit 48d4fd48430 (2024-06-04 10:41 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 12 × 12th Gen Intel(R) Core(TM) i5-1235U
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-15.0.7 (ORCJIT, alderlake)
Threads: 8 default, 0 interactive, 4 GC (on 12 virtual cores)
Environment:
JULIA_NUM_THREADS = 4