Hutchinson with Diffusion
Consider the Hutchinson equation with diffusion
\[\begin{aligned} & \frac{\partial u(t, x)}{\partial t}=d \frac{\partial^2 u(t, x)}{\partial x^2}-a u(t-1, x)[1+u(t, x)], \quad t>0, x \in(0, \pi), \\ & \frac{\partial u(t, x)}{\partial x}=0, x=0, \pi \end{aligned}\]
where $a>0,d>0$.
Problem discretization
We start by discretizing the above PDE based on finite differences.
using Revise, DDEBifurcationKit, Parameters, LinearAlgebra, Plots, SparseArrays
using BifurcationKit
const BK = BifurcationKit
function Hutchinson(u, ud, p)
@unpack a,d,Δ = p
d .* (Δ*u) .- a .* ud[1] .* (1 .+ u)
end
delaysF(par) = [1.]
Bifurcation analysis
We can now instantiate the model
# discretisation
Nx = 200; Lx = pi/2;
X = -Lx .+ 2Lx/Nx*(0:Nx-1) |> collect
function DiffOp(N, lx; order = 2)
hx = 2lx/N
Δ = spdiagm(0 => -2ones(N), 1 => ones(N-1), -1 => ones(N-1) )
Δ[1,1]=-1; Δ[end,end]=-1
Δ = Δ / hx^2
return Δ
end
Δ = DiffOp(Nx, Lx)
We are now ready to compute the bifurcation of the trivial (constant in space) solution:
# bifurcation problem
pars = (a = 0.5, d = 1, τ = 1.0, Δ = Δ, N = Nx)
x0 = zeros(Nx)
prob = ConstantDDEBifProblem(Hutchinson, delaysF, x0, pars, (@lens _.a))
optn = NewtonPar(eigsolver = DDE_DefaultEig())
opts = ContinuationPar(p_max = 10., p_min = 0., newton_options = optn, ds = 0.01, detect_bifurcation = 3, nev = 5, dsmax = 0.2, n_inversion = 4)
br = continuation(prob, PALC(), opts; verbosity = 0, plot = false, normC = norminf)
br
┌─ Curve type: EquilibriumCont
├─ Number of points: 42
├─ Type of vectors: Vector{Float64}
├─ Parameter a starts at 0.5, ends at 10.0
├─ Algo: PALC
└─ Special points:
If `br` is the name of the branch,
ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
- # 1, hopf at a ≈ +1.57668056 ∈ (+1.56784173, +1.57668056), |δp|=9e-03, [converged], δ = ( 2, 2), step = 10, eigenelements in eig[ 11], ind_ev = 2
- # 2, hopf at a ≈ +2.26389996 ∈ (+2.26169025, +2.26389996), |δp|=2e-03, [converged], δ = ( 2, 2), step = 13, eigenelements in eig[ 14], ind_ev = 4
- # 3, hopf at a ≈ +4.75534651 ∈ (+4.75424166, +4.75534651), |δp|=1e-03, [converged], δ = ( 2, 2), step = 22, eigenelements in eig[ 23], ind_ev = 6
- # 4, hopf at a ≈ +9.43550952 ∈ (+9.43109010, +9.43550952), |δp|=4e-03, [converged], δ = ( 2, 2), step = 39, eigenelements in eig[ 40], ind_ev = 8
- # 5, endpoint at a ≈ +10.00000000, step = 41
We note that the first Hopf point is close to the theoretical value $a=\frac\pi 2$. This can be improved by increasing opts.n_inversion
.
We can now plot the branch
scene = plot(br)
Performance improvements
The previous implementation being simple, it leaves a lot performance on the table. For example, the jacobian is dense because it is computed with automatic differentiation without sparsity detection.
We show how to specify the jacobian and speed up the code a lot.
# analytical jacobian
function JacHutchinson(u, p)
@unpack a,d,Δ = p
# we compute the jacobian at the steady state
J0 = d * Δ .- a .* Diagonal(u)
J1 = -a .* Diagonal(1 .+ u)
return J0, [J1]
end
prob2 = ConstantDDEBifProblem(Hutchinson, delaysF, x0, pars, (@lens _.a); J = JacHutchinson)
optn = NewtonPar(eigsolver = DDE_DefaultEig())
opts = ContinuationPar(p_max = 10., p_min = 0., newton_options = optn, ds = 0.01, detect_bifurcation = 3, nev = 5, dsmax = 0.2, n_inversion = 4)
br = continuation(prob2, PALC(), opts; verbosity = 1, plot = true, normC = norminf)
br
┌─ Curve type: EquilibriumCont
├─ Number of points: 42
├─ Type of vectors: Vector{Float64}
├─ Parameter a starts at 0.5, ends at 10.0
├─ Algo: PALC
└─ Special points:
If `br` is the name of the branch,
ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
- # 1, hopf at a ≈ +1.57668056 ∈ (+1.56784173, +1.57668056), |δp|=9e-03, [converged], δ = ( 2, 2), step = 10, eigenelements in eig[ 11], ind_ev = 2
- # 2, hopf at a ≈ +2.26389996 ∈ (+2.26169025, +2.26389996), |δp|=2e-03, [converged], δ = ( 2, 2), step = 13, eigenelements in eig[ 14], ind_ev = 4
- # 3, hopf at a ≈ +4.75534651 ∈ (+4.75424166, +4.75534651), |δp|=1e-03, [converged], δ = ( 2, 2), step = 22, eigenelements in eig[ 23], ind_ev = 6
- # 4, hopf at a ≈ +9.43550952 ∈ (+9.43109010, +9.43550952), |δp|=4e-03, [converged], δ = ( 2, 2), step = 39, eigenelements in eig[ 40], ind_ev = 8
- # 5, endpoint at a ≈ +10.00000000, step = 41