using MethodOfLines
using ModelingToolkit
using DomainSets
using OrdinaryDiffEq
using Plots
using LaTeXStringsFisher KPP with Julia
This implementation of numerical solve of a reaction diffusion equation is based on the presentation of the package MethodOfLines.jl at JuliaCon 2022 by A. Jones.
Fisher KPP equation
The Fisher KPP equation (Fisher’s version) reads (Fisher (1937), Kolmogorov, Petrovskii, and Piskunov (1937)):
\frac{\partial u}{\partial t} = ru\left(1-u\right) + D \frac{\partial^2 u}{\partial x^2},
with u(t,x) the population density at time t and position x (scaled to the local carrying capacity K), r the intrinsic growth rate of the population, and D the diffusion coefficient.
Packages
Let us first import the packages used for the simulation:
Model definition
MethodsOfLines.jl makes use of ModelingToolkit.jl to symbolically define the model to integrate.
Let us first define the time and space parameters:
@parameters t xThe model parameters:
@parameters r DNow the variable u(t,x):
@variables u(..)And finally the derivatives:
Dt = Differential(t)
Dx = Differential(x)
Dxx = Differential(x)^2We can now define the model symbolically through:
eq = Dt(u(t, x)) ~ r * u(t,x) * (1-u(t,x)) + D * Dxx(u(t,x))Differential(t)(u(t, x)) ~ D*Differential(x)(Differential(x)(u(t, x))) + r*u(t, x)*(1 - u(t, x))
Domains of integration
Let us introduce some parameters for space and time domains:
x_max = 30.0
t_max = 14.0And the domains of integration:
domain = [x ∈ Interval(0.0, x_max),
t ∈ Interval(0.0, t_max)]We also introduce (initial and) boundary conditions:
ic_bc = [u(0.0, x) ~ 0.0,
u(t, 0.0) ~ 1.0,
u(t, x_max) ~ 0.0]Simulation
We define the model to be integrated as a PDESystem, from the equation eq, the initial and boundary conditions ic_bc, the domains of integration domain, the time and space parameters t and x, the solution we want to retrieve u(t,x), and the model parameters r and D:
@named sys = PDESystem(eq, ic_bc, domain, [t, x], [u(t,x)], [r => 1.0, D => 1.0])We set up the discretization of space, through MethodOfLines.jl:
dx = 0.1
discretization = MOLFiniteDifference([x => dx], t)And we set up the (ODE) problem to be integrated:
prob = discretize(sys, discretization)And we finally integrate it through the OrdinaryDiffEq.jl solver with Tsit5 algorithm.
sol = solve(prob, Tsit5(), saveat = .1)Graphical representation
We retrieve the components of the solution for easier manipulation:
gridx = sol[x]
gridt = sol[t]
solu = sol[u(t,x)]And we plot the animation of the solution through time:
anim = @animate for i in eachindex(gridt)
plot(
gridx,
solu[i, :];
xlabel = "position "*L"$x$",
ylabel = "population density "*L"$u$",
label = L"$u(x,t)$",
title = "t=$(gridt[i])",
)
end
gif(anim, "fisherKPP.gif", fps = 10)[ Info: Saved animation to /home/ludo/Nextcloud/MyDrive/Programmes/julia/biomaths_julia_www/fisherKPP.gif
And that’s it !