Skip to content

Commit ffb24c4

Browse files
committed
update Smoluchowski tutorial
1 parent 035e059 commit ffb24c4

File tree

2 files changed

+47
-35
lines changed

2 files changed

+47
-35
lines changed

docs/pages.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pages = Any[
1919
"model_creation/examples/basic_CRN_library.md",
2020
"model_creation/examples/programmatic_generative_linear_pathway.md",
2121
"model_creation/examples/hodgkin_huxley_equation.md",
22-
#"model_creation/examples/smoluchowski_coagulation_equation.md"
22+
"model_creation/examples/smoluchowski_coagulation_equation.md"
2323
]
2424
],
2525
"Model simulation" => Any[
@@ -32,7 +32,7 @@ pages = Any[
3232
"Steady state analysis" => Any[
3333
"steady_state_functionality/homotopy_continuation.md",
3434
"steady_state_functionality/nonlinear_solve.md",
35-
"steady_state_functionality/steady_state_stability_computation.md",
35+
"steady_state_functionality/steady_state_stability_computation.md",
3636
"steady_state_functionality/bifurcation_diagrams.md",
3737
"steady_state_functionality/dynamical_systems.md"
3838
],

docs/src/model_creation/examples/smoluchowski_coagulation_equation.md

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,47 +6,58 @@ The Smoluchowski coagulation equation describes a system of reactions in which m
66
We begin by importing some necessary packages.
77
```julia
88
using ModelingToolkit, Catalyst, LinearAlgebra
9-
using DiffEqBase, JumpProcesses
9+
using JumpProcesses
1010
using Plots, SpecialFunctions
1111
```
1212
Suppose the maximum cluster size is `N`. We assume an initial concentration of monomers, `Nₒ`, and let `uₒ` denote the initial number of monomers in the system. We have `nr` total reactions, and label by `V` the bulk volume of the system (which plays an important role in the calculation of rate laws since we have bimolecular reactions). Our basic parameters are then
1313
```julia
14-
## Parameter
15-
N = 10 # maximum cluster size
16-
Vₒ = (4π/3)*(10e-06*100)^3 # volume of a monomers in cm³
17-
Nₒ = 1e-06/Vₒ # initial conc. = (No. of init. monomers) / bulk volume
18-
uₒ = 10000 # No. of monomers initially
19-
V = uₒ/Nₒ # Bulk volume of system in cm³
20-
21-
integ(x) = Int(floor(x))
22-
n = integ(N/2)
23-
nr = N%2 == 0 ? (n*(n + 1) - n) : (n*(n + 1)) # No. of forward reactions
14+
# maximum cluster size
15+
N = 10
16+
17+
# volume of a monomers in cm³
18+
Vₒ = (4π / 3) * (10e-06 * 100)^3
19+
20+
# initial conc. = (No. of init. monomers) / bulk volume
21+
Nₒ = 1e-06 / Vₒ
22+
23+
# No. of monomers initially
24+
uₒ = 10000
25+
26+
# Bulk volume of system in cm³
27+
V = uₒ / Nₒ
28+
n = floor(Int, N / 2)
29+
30+
# No. of forward reactions
31+
nr = ((N % 2) == 0) ? (n*(n + 1) - n) : (n*(n + 1))
2432
```
2533
The [Smoluchowski coagulation equation](https://en.wikipedia.org/wiki/Smoluchowski_coagulation_equation) Wikipedia page illustrates the set of possible reactions that can occur. We can easily enumerate the `pair`s of multimer reactants that can combine when allowing a maximal cluster size of `N` monomers. We initialize the volumes of the reactant multimers as `volᵢ` and `volⱼ`
2634

2735
```julia
2836
# possible pairs of reactant multimers
29-
pair = []
37+
pair = Int[]
3038
for i = 2:N
31-
push!(pair, [1:integ(i/2) i .- (1:integ(i/2))])
39+
halfi = floor(Int, i/2)
40+
push!(pair, [(1:halfi) (i .- (1:halfi))])
3241
end
3342
pair = vcat(pair...)
34-
vᵢ = @view pair[:,1] # Reactant 1 indices
35-
vⱼ = @view pair[:,2] # Reactant 2 indices
36-
volᵢ = Vₒ*vᵢ # cm⁻³
37-
volⱼ = Vₒ*vⱼ # cm⁻³
43+
vᵢ = @view pair[:, 1] # Reactant 1 indices
44+
vⱼ = @view pair[:, 2] # Reactant 2 indices
45+
volᵢ = Vₒ * vᵢ # cm⁻³
46+
volⱼ = Vₒ * vⱼ # cm⁻³
3847
sum_vᵢvⱼ = @. vᵢ + vⱼ # Product index
3948
```
4049
We next specify the rates (i.e. kernel) at which reactants collide to form products. For simplicity, we allow a user-selected additive kernel or constant kernel. The constants(`B` and `C`) are adopted from Scott's paper [2](https://journals.ametsoc.org/view/journals/atsc/25/1/1520-0469_1968_025_0054_asocdc_2_0_co_2.xml)
4150
```julia
4251
# set i to 1 for additive kernel, 2 for constant
4352
i = 1
44-
if i==1
45-
B = 1.53e03 # s⁻¹
46-
kv = @. B*(volᵢ + volⱼ)/V # dividing by volume as its a bi-molecular reaction chain
53+
if i == 1
54+
B = 1.53e03 # s⁻¹
55+
56+
# dividing by volume as it is a bimolecular reaction chain
57+
kv = @. B * (volᵢ + volⱼ) / V
4758
elseif i==2
48-
C = 1.84e-04 # cm³ s⁻¹
49-
kv = fill(C/V, nr)
59+
C = 1.84e-04 # cm³ s⁻¹
60+
kv = fill(C / V, nr)
5061
end
5162
```
5263
We'll store the reaction rates in `pars` as `Pair`s, and set the initial condition that only monomers are present at ``t=0`` in `u₀map`.
@@ -58,9 +69,9 @@ pars = Pair.(collect(k), kv)
5869

5970
# time-span
6071
if i == 1
61-
tspan = (0. ,2000.)
72+
tspan = (0.0, 2000.0)
6273
elseif i == 2
63-
tspan = (0. ,350.)
74+
tspan = (0.0, 350.0)
6475
end
6576

6677
# initial condition of monomers
@@ -82,19 +93,20 @@ for n = 1:nr
8293
end
8394
end
8495
@named rs = ReactionSystem(rx, t, collect(X), collect(k))
96+
rs = complete(rs)
8597
```
8698
We now convert the [`ReactionSystem`](@ref) into a `ModelingToolkit.JumpSystem`, and solve it using Gillespie's direct method. For details on other possible solvers (SSAs), see the [DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/types/jump_types/) documentation
8799
```julia
88100
# solving the system
89101
jumpsys = convert(JumpSystem, rs)
90102
dprob = DiscreteProblem(jumpsys, u₀map, tspan, pars)
91-
jprob = JumpProblem(jumpsys, dprob, Direct(), save_positions=(false,false))
92-
jsol = solve(jprob, SSAStepper(), saveat = tspan[2]/30)
103+
jprob = JumpProblem(jumpsys, dprob, Direct(), save_positions = (false, false))
104+
jsol = solve(jprob, SSAStepper(), saveat = tspan[2] / 30)
93105
```
94106
Lets check the results for the first three polymers/cluster sizes. We compare to the analytical solution for this system:
95107
```julia
96108
# Results for first three polymers...i.e. monomers, dimers and trimers
97-
v_res = [1;2;3]
109+
v_res = [1; 2; 3]
98110

99111
# comparison with analytical solution
100112
# we only plot the stochastic solution at a small number of points
@@ -114,15 +126,15 @@ elseif i == 2
114126
end
115127

116128
# plotting normalised concentration vs analytical solution
117-
default(lw=2, xlabel="Time (sec)")
118-
scatter(ϕ, jsol(t)[1,:]/uₒ, label="X1 (monomers)", markercolor=:blue)
129+
default(lw = 2, xlabel = "Time (sec)")
130+
scatter(ϕ, jsol(t)[1,:] / uₒ, label = "X1 (monomers)", markercolor = :blue)
119131
plot!(ϕ, sol[1,:]/Nₒ, line = (:dot,4,:blue), label="Analytical sol--X1")
120132

121-
scatter!(ϕ, jsol(t)[2,:]/uₒ, label="X2 (dimers)", markercolor=:orange)
122-
plot!(ϕ, sol[2,:]/Nₒ, line = (:dot,4,:orange), label="Analytical sol--X2")
133+
scatter!(ϕ, jsol(t)[2,:] / uₒ, label = "X2 (dimers)", markercolor = :orange)
134+
plot!(ϕ, sol[2,:] / Nₒ, line = (:dot, 4, :orange), label = "Analytical sol--X2")
123135

124-
scatter!(ϕ, jsol(t)[3,:]/uₒ, label="X3 (trimers)", markercolor=:purple)
125-
plot!(ϕ, sol[3,:]/Nₒ, line = (:dot,4,:purple), label="Analytical sol--X3",
136+
scatter!(ϕ, jsol(t)[3,:] / uₒ, label = "X3 (trimers)", markercolor = :purple)
137+
plot!(ϕ, sol[3,:] / Nₒ, line = (:dot, 4, :purple), label = "Analytical sol--X3",
126138
ylabel = "Normalized Concentration")
127139
```
128140
For the **additive kernel** we find

0 commit comments

Comments
 (0)