Nonlinear laser model

The following model is taken from [Pusuluri]:

\[\left\{\begin{aligned} \dot{\beta} & =-\sigma \beta+g p_{23}, \\ \dot{p}_{21} & =-p_{21}-\beta p_{31}+a D_{21}, \\ \dot{p}_{23} & =-p_{23}+\beta D_{23}-a p_{31}, \\ \dot{p}_{31} & =-p_{31}+\beta p_{21}+a p_{23}, \\ \dot{D}_{21} & =-b\left(D_{21}-D_{21}^0\right)-4 a p_{21}-2 \beta p_{23}, \\ \dot{D}_{23} & =-b\left(D_{23}-D_{23}^0\right)-2 a p_{21}-4 \beta p_{23}, \end{aligned}\right.\]

It is easy to encode the ODE as follows

using Revise, Plots
using Parameters, Setfield, LinearAlgebra, Test, ForwardDiff
using BifurcationKit, Test
using HclinicBifurcationKit
const BK = BifurcationKit

recordFromSolution(x, p) = (D₂₃ = x[6], β = x[1],)
####################################################################################################
function OPL!(dz, u, p, t)
	@unpack b, σ, g, a, D₂₁⁰, D₂₃⁰  = p
	β, p₂₁, p₂₃, p₃₁, D₂₁, D₂₃ = u
	dz[1] = -σ * β + g * p₂₃
	dz[2] =	-p₂₁ - β * p₃₁ + a * D₂₁
	dz[3] = -p₂₃ + β * D₂₃ - a * p₃₁
	dz[4] = -p₃₁ + β * p₂₁ + a * p₂₃
	dz[5] = -b * (D₂₁ - D₂₁⁰) - 4a * p₂₁ - 2β * p₂₃
	dz[6] = -b * (D₂₃ - D₂₃⁰) - 2a * p₂₁ - 4β * p₂₃
	dz
end

OPL(z, p) = OPL!(similar(z), z, p, 0)
par_OPL = (b = 1.2, σ = 2.0, g=50., a = 1., D₂₁⁰ = -1., D₂₃⁰ = 0.)
z0 = zeros(6)
prob = BK.BifurcationProblem(OPL, z0, par_OPL, (@lens _.a); record_from_solution = recordFromSolution)
WARNING: using Plots.wrap in module BifurcationKit conflicts with an existing identifier.

We first compute the branch of equilibria

opts_br = ContinuationPar(p_min = -1., p_max = 8., ds = 0.001, dsmax = 0.06, n_inversion = 6, detect_bifurcation = 3, max_bisection_steps = 25, nev = 6, plot_every_step = 20, max_steps = 100, save_sol_every_step = 1, detect_fold = true)
	opts_br = @set opts_br.newton_options.verbose = false
	br = continuation(prob, PALC(tangent = Secant()), opts_br;
	bothside = false, normC = norminf)

plot(br, plotfold=true)

br2 = continuation(re_make(prob; u0 = [1.6931472491037485, -0.17634826359471437, 0.06772588996414994, -0.23085768742546342, -0.5672243219935907, -0.09634826359471438]), PALC(tangent = Secant()), opts_br; verbosity = 0, bothside = false, normC = norminf)
scene = plot(br, br2)

Codimension 2 bifurcations

sn_br = continuation(br, 1, (@lens _.b), ContinuationPar(opts_br, detect_bifurcation = 1, save_sol_every_step = 1, max_steps = 80) ;
	alg = PALC(),
	verbosity = 0,
	detect_codim2_bifurcation = 2,
	start_with_eigen = true,
	update_minaug_every_step = 1,
	bothside = true,
	)

hopf_br = continuation(br, 2, (@lens _.b), ContinuationPar(opts_br, detect_bifurcation = 1, save_sol_every_step = 1, max_steps = 140),
	detect_codim2_bifurcation = 2,
	start_with_eigen = true,
	update_minaug_every_step = 1,
	bothside = true,
	)

hopf_br2 = continuation(br2, 1, (@lens _.b), ContinuationPar(opts_br, detect_bifurcation = 1, save_sol_every_step = 1, max_steps = 140),
	detect_codim2_bifurcation = 2,
	start_with_eigen = true,
	update_minaug_every_step = 1,
	bothside = true,
	)

plot(sn_br, vars = (:a, :b), branchlabel = "SN", )
	plot!(hopf_br, branchlabel = "Hopf", vars = (:a, :b))
	plot!(hopf_br2, branchlabel = "Hopf", vars = (:a, :b))
	ylims!(0,1.5)

Branch of homoclinic orbits with Orthogonal Collocation

# plotting function
function plotPO(x, p; k...)
	xtt = BK.get_periodic_orbit(p.prob, x, set(getparams(p.prob), BK.getlens(p.prob), p.p))
	plot!(xtt.t, xtt[1,:]; markersize = 2, k...)
	plot!(xtt.t, xtt[6,:]; k...)
	scatter!(xtt.t, xtt[1,:]; markersize = 1, legend = false, k...)
end

# record function
function recordPO(x, p)
	xtt = BK.get_periodic_orbit(p.prob, x, set(getparams(p.prob), BK.getlens(p.prob), p.p))
	period = BK.getperiod(p.prob, x, p.p)
	return (max = maximum(xtt[6,:]), min = minimum(xtt[6,:]), period = period, )
end

# newton parameters
optn_po = NewtonPar(verbose = true, tol = 1e-8,  max_iterations = 25)

# continuation parameters
opts_po_cont = ContinuationPar(dsmax = 0.05, ds= 0.001, dsmin = 1e-4, p_max = 6.8, p_min=-5., max_steps = 100, newton_options = (@set optn_po.tol = 1e-8), detect_bifurcation = 0, plot_every_step = 3, save_sol_every_step=1,)

br_coll = continuation(
	# br, 2,
	br2, 1,
	opts_po_cont,
	PeriodicOrbitOCollProblem(20, 4; meshadapt = true, update_section_every_step = 2);
	ampfactor = 1., δp = 0.0015,
	verbosity = 2,	plot = true,
	alg = PALC(tangent = Bordered()),
	record_from_solution = recordPO,
	plot_solution = (x, p; k...) -> begin
		plotPO(x, p; k...)
		## add previous branch
		plot!(br, subplot=1, putbifptlegend = false)
		plot!(br2, subplot=1, putbifptlegend = false)
		end,
	finalise_solution = (z, tau, step, contResult; prob = nothing, kwargs...) -> begin
		# limit the period
			return z.u[end] < 150
			true
		end,
	normC = norminf)
 ┌─ Curve type: PeriodicOrbitCont from Hopf bifurcation point.
 ├─ Number of points: 101
 ├─ Type of vectors: Vector{Float64}
 ├─ Parameter a starts at 4.269257131580585, ends at 4.259422939031913
 ├─ 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,     fold at a ≈ +4.27074884 ∈ (+4.27074884, +4.27074884), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =   9, eigenelements in eig[  9], ind_ev =   0
- #  2,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  35, eigenelements in eig[ 35], ind_ev =   0
- #  3,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  36, eigenelements in eig[ 36], ind_ev =   0
- #  4,     fold at a ≈ +4.25942313 ∈ (+4.25942313, +4.25942313), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  37, eigenelements in eig[ 37], ind_ev =   0
- #  5,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  38, eigenelements in eig[ 38], ind_ev =   0
- #  6,     fold at a ≈ +4.25942313 ∈ (+4.25942313, +4.25942313), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  39, eigenelements in eig[ 39], ind_ev =   0
- #  7,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  40, eigenelements in eig[ 40], ind_ev =   0
- #  8,     fold at a ≈ +4.25942313 ∈ (+4.25942313, +4.25942313), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  41, eigenelements in eig[ 41], ind_ev =   0
- #  9,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  42, eigenelements in eig[ 42], ind_ev =   0
- # 10,     fold at a ≈ +4.25942313 ∈ (+4.25942313, +4.25942313), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  43, eigenelements in eig[ 43], ind_ev =   0
- # 11,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  44, eigenelements in eig[ 44], ind_ev =   0
- # 12,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  45, eigenelements in eig[ 45], ind_ev =   0
- # 13,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  46, eigenelements in eig[ 46], ind_ev =   0
- # 14,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  47, eigenelements in eig[ 47], ind_ev =   0
- # 15,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  48, eigenelements in eig[ 48], ind_ev =   0
- # 16,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  49, eigenelements in eig[ 49], ind_ev =   0
- # 17,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  50, eigenelements in eig[ 50], ind_ev =   0
- # 18,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  51, eigenelements in eig[ 51], ind_ev =   0
- # 19,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  52, eigenelements in eig[ 52], ind_ev =   0
- # 20,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  53, eigenelements in eig[ 53], ind_ev =   0
- # 21,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  54, eigenelements in eig[ 54], ind_ev =   0
- # 22,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  55, eigenelements in eig[ 55], ind_ev =   0
- # 23,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  56, eigenelements in eig[ 56], ind_ev =   0
- # 24,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  57, eigenelements in eig[ 57], ind_ev =   0
- # 25,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  58, eigenelements in eig[ 58], ind_ev =   0
- # 26,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  59, eigenelements in eig[ 59], ind_ev =   0
- # 27,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  60, eigenelements in eig[ 60], ind_ev =   0
- # 28,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  61, eigenelements in eig[ 61], ind_ev =   0
- # 29,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  62, eigenelements in eig[ 62], ind_ev =   0
- # 30,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  63, eigenelements in eig[ 63], ind_ev =   0
- # 31,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  64, eigenelements in eig[ 64], ind_ev =   0
- # 32,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  65, eigenelements in eig[ 65], ind_ev =   0
- # 33,     fold at a ≈ +4.25942317 ∈ (+4.25942317, +4.25942317), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  75, eigenelements in eig[ 75], ind_ev =   0
- # 34,     fold at a ≈ +4.25942314 ∈ (+4.25942314, +4.25942314), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  76, eigenelements in eig[ 76], ind_ev =   0
- # 35,     fold at a ≈ +4.25942315 ∈ (+4.25942315, +4.25942315), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  77, eigenelements in eig[ 77], ind_ev =   0
- # 36,     fold at a ≈ +4.25942302 ∈ (+4.25942302, +4.25942302), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  82, eigenelements in eig[ 82], ind_ev =   0
- # 37,     fold at a ≈ +4.25942309 ∈ (+4.25942309, +4.25942309), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  91, eigenelements in eig[ 91], ind_ev =   0
- # 38,     fold at a ≈ +4.25942307 ∈ (+4.25942307, +4.25942307), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  92, eigenelements in eig[ 92], ind_ev =   0
- # 39,     fold at a ≈ +4.25942308 ∈ (+4.25942308, +4.25942308), |δp|=-1e+00, [    guess], δ = ( 0,  0), step =  93, eigenelements in eig[ 93], ind_ev =   0
- # 40, endpoint at a ≈ +4.25942292,                                                                      step = 101
probhom, solh = generate_hom_problem(
	setproperties(br_coll.prob.prob, meshadapt=true, K = 100),
	br_coll.sol[end].x,
	BK.setparam(br_coll, br_coll.sol[end].p),
	BK.getlens(br_coll);
	update_every_step = 4,
	verbose = true,
	# ϵ0 = 1e-7, ϵ1 = 1e-7, # WORK BEST
	# ϵ0 = 1e-8, ϵ1 = 1e-5, # maxT = 70,
	t0 = 0., t1 = 120.,
	# freeparams = ((@lens _.T), (@lens _.ϵ1),)
	# freeparams = ((@lens _.T), (@lens _.ϵ0)),
	freeparams = ((@lens _.ϵ0), (@lens _.ϵ1)), # WORK BEST
	# freeparams = ((@lens _.T),),
	testOrbitFlip = false,
	testInclinationFlip = false
	)

#####

_sol = get_homoclinic_orbit(probhom, solh, BK.getparams(probhom);)
scene = plot(_sol.t, _sol[:,:]', marker = :d, markersize = 1)
optn_hom = NewtonPar(verbose = true, tol = 1e-10, max_iterations = 5)
optc_hom = ContinuationPar(newton_options = optn_hom, ds = -0.0001, dsmin = 1e-5, plot_every_step = 10, max_steps = 100, detect_bifurcation = 0, detect_event = 2, save_sol_every_step = 1, p_min = -1.01)

br_hom_c = continuation(
			deepcopy(probhom), solh, (@lens _.b),
			PALC(tangent = Bordered()),
			# PALC(),
			# MoorePenrose(),
			setproperties(optc_hom, max_steps = 100, save_sol_every_step = 1, dsmax = 4e-2, plot_every_step = 10, p_max = 1.5);
	verbosity = 1, plot = true,
	# callback_newton = BK.cbMaxNorm(1e1),
	# bothside = true,
	normC = norminf,
	plot_solution = (x,p;k...) -> begin
		𝐇𝐨𝐦 = p.prob
		par0 = set(BK.getparams(𝐇𝐨𝐦), BK.getlens(𝐇𝐨𝐦), x.x[end][1])
		par0 = set(par0, (@lens _.b), p.p)
		sol = get_homoclinic_orbit(𝐇𝐨𝐦, x, par0)
		m = (𝐇𝐨𝐦.bvp isa PeriodicOrbitOCollProblem && 𝐇𝐨𝐦.bvp.meshadapt) ? :d : :none
		plot!(sol.t, sol[:,:]',subplot=3, markersize = 1, marker=m)
	end,
	)

plot(sn_br, vars = (:a, :b), branchlabel = "SN", )
plot!(hopf_br, branchlabel = "AH₀", vars = (:a, :b))
plot!(hopf_br2, branchlabel = "AH₁₂", vars = (:a, :b))
plot!(br_hom_c, branchlabel = "H₀", vars = (:a, :b))
ylims!(0,1.5)

Branch of homoclinic orbits with Multiple Shooting

using DifferentialEquations
probsh = ODEProblem(OPL!, copy(z0), (0., 1000.), par_OPL; abstol = 1e-12, reltol = 1e-10)

# newton parameters
optn_po = NewtonPar(verbose = true, tol = 1e-8,  max_iterations = 25)

# continuation parameters
opts_po_cont = ContinuationPar(dsmax = 0.075, ds= -0.001, dsmin = 1e-4, p_max = 6.8, p_min=-5., max_steps = 130, newton_options = (@set optn_po.tol = 1e-8), tol_stability = 1e-4, detect_bifurcation = 0, plot_every_step = 10, save_sol_every_step=1)

br_sh = continuation(
	# br, 2,
	br2, 1,
	opts_po_cont,
	ShootingProblem(8, probsh, Rodas5P(); parallel = true, abstol = 1e-13, reltol = 1e-11);
	ampfactor = 1., δp = 0.0015,
	verbosity = 2,	plot = true,
	record_from_solution = recordPO,
	callback_newton = BK.cbMaxNorm(1e0),
	plot_solution = (x, p; k...) -> begin
		plotPO(x, p; k...)
		## add previous branch
		# plot!(br, subplot=1, putbifptlegend = false)
		end,
	finalise_solution = (z, tau, step, contResult; prob = nothing, kwargs...) -> begin
		# limit the period
			return z.u[end] < 100
			true
		end,
	normC = norminf)

_sol = get_periodic_orbit(br_sh.prob.prob, br_sh.sol[end].x, BK.setparam(br_sh,  br_sh.sol[end].p))
plot(_sol.t, _sol[:,:]')
# homoclinic
probhom, solh = generate_hom_problem(
	br_sh.prob.prob, br_sh.sol[end].x,
	BK.setparam(br_sh, br_sh.sol[end].p),
	BK.getlens(br_sh);
	verbose = true,
	update_every_step = 4,
	# ϵ0 = 1e-6, ϵ1 = 1e-5,
	t0 = 75, t1 = 25,
	# freeparams = ((@lens _.T), (@lens _.ϵ1),)
	# freeparams = ((@lens _.T), (@lens _.ϵ0)),
	# freeparams = ((@lens _.ϵ0), (@lens _.ϵ1)), # WORK BEST
	freeparams = ((@lens _.T),),
	)

_sol = get_homoclinic_orbit(probhom, solh, BK.getparams(probhom); saveat=.1)
plot(plot(_sol[1,:], _sol[2,:]), plot(_sol.t, _sol[:,:]'))

optn_hom = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 7)
optc_hom = ContinuationPar(newton_options = optn_hom, ds = -1e-4, dsmin = 1e-6, dsmax = 1e-3, plot_every_step = 1, max_steps = 10, detect_bifurcation = 0, save_sol_every_step = 1)

br_hom_sh = continuation(
			deepcopy(probhom), solh, (@lens _.b),
			PALC(),
			setproperties(optc_hom, max_steps = 600, save_sol_every_step = 1, dsmax = 12e-2, plot_every_step = 3, p_max = 7., detect_event = 2, a = 0.9);
	verbosity = 3, plot = true,
	callback_newton = BK.cbMaxNorm(1e0),
	normC = norminf,
	plot_solution = (x,p;k...) -> begin
		𝐇𝐨𝐦 = p.prob
		par0 = set(BK.getparams(𝐇𝐨𝐦), BK.getlens(𝐇𝐨𝐦), x.x[end][1])
		par0 = set(par0, (@lens _.b), p.p)
		sol = get_homoclinic_orbit(𝐇𝐨𝐦, x, par0)
		m = (𝐇𝐨𝐦.bvp isa PeriodicOrbitOCollProblem && 𝐇𝐨𝐦.bvp.meshadapt) ? :d : :none
		plot!(sol.t, sol[:,:]',subplot=3, markersize = 1, marker=m)
	end,
	)

_sol = get_homoclinic_orbit(probhom, br_hom_sh.sol[end].x, BK.setparam(br_hom_sh, br_hom_sh.sol[end].p); saveat=.1)
plot(_sol.t, _sol[:,:]')
plot(sn_br, vars = (:a, :b), branchlabel = "SN", )
plot!(hopf_br, branchlabel = "AH₀", vars = (:a, :b))
plot!(hopf_br2, branchlabel = "AH₁₂", vars = (:a, :b))
plot!(br_hom_c, branchlabel = "Hc₀", vars = (:a, :b))
plot!(br_hom_sh, branchlabel = "Hsh₀", vars = (:a, :b), linewidth = 3)
ylims!(0,1.5)

References

  • Pusuluri

    Pusuluri, K, H G E Meijer, and A L Shilnikov. “Homoclinic Puzzles and Chaos in a Nonlinear Laser Model,” n.d.