diff --git a/dev/ANM/index.html b/dev/ANM/index.html index bca2dca7..aa5ba3fb 100644 --- a/dev/ANM/index.html +++ b/dev/ANM/index.html @@ -27,713 +27,709 @@ ├─ 15 series of degree 20, tol = 1.0e-8 ├─ Number of points: 301 ├─ Type of vectors: Vector{Float64} - ├─ Parameter α starts at 6.666666666666667e-5, ends at 8.426001456466812e-10 + ├─ Parameter α starts at 6.666666666666667e-5, ends at 3.151713936141693e-12 ├─ Algo: ANM └─ 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, bp at α ≈ +0.36763519 ∈ (+0.36787944, +0.36787944), |δp|=2e-11, [converged], δ = ( 1, 0), step = 27, eigenelements in eig[ 28], ind_ev = 1 -- # 2, bp at α ≈ +0.14935757 ∈ (+0.14936120, +0.14936121), |δp|=8e-09, [converged], δ = ( 1, 0), step = 76, eigenelements in eig[ 77], ind_ev = 2 +- # 1, bp at α ≈ +0.36763519 ∈ (+0.36787944, +0.36787944), |δp|=2e-11, [converged], δ = ( 1, 0), step = 27, eigenelements in eig[ 28], ind_ev = 1 +- # 2, bp at α ≈ +0.14899935 ∈ (+0.14936088, +0.14936191), |δp|=1e-06, [converged], δ = ( 1, 0), step = 69, eigenelements in eig[ 70], ind_ev = 2

You can plot the result as usual:

plot(branm)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

You can also show the radius of convergence of each series:

plot(branm, plotseries = true)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Finally, for each series, we ca evaluate the residual norm:

plot()
 for ii in eachindex(branm.polU)
@@ -743,56 +739,58 @@
 title!("")
- + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -

References

+

References

diff --git a/dev/BifProblem/index.html b/dev/BifProblem/index.html index 24ff1b85..afb23942 100644 --- a/dev/BifProblem/index.html +++ b/dev/BifProblem/index.html @@ -29,4 +29,4 @@ prob2 = BifurcationKit.re_make(prob, u0 = rand(3))
┌─ Bifurcation Problem with uType Vector{Float64}
 ├─ Inplace:  false
 ├─ Symmetric: false
-└─ Parameter: a
+└─ Parameter: a diff --git a/dev/BifurcationDiagram/index.html b/dev/BifurcationDiagram/index.html index 8ec21063..79b1a5b9 100644 --- a/dev/BifurcationDiagram/index.html +++ b/dev/BifurcationDiagram/index.html @@ -37,350 +37,350 @@ plot(diagram; putspecialptlegend=false, markersize=2, plotfold=false, title = "#branches = $(size(diagram))") - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

This gives

diagram
[Bifurcation diagram]
  ┌─ From 0-th bifurcation point.
@@ -396,9 +396,9 @@
 If `br` is the name of the branch,
 ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
 
-- #  1,       bp at p ≈ +0.00000281 ∈ (-0.00000065, +0.00000281), |δp|=3e-06, [converged], δ = ( 1,  0), step =  31, eigenelements in eig[ 32], ind_ev =   1
-- #  2,       bp at p ≈ +0.15000016 ∈ (+0.14999995, +0.15000016), |δp|=2e-07, [   guessL], δ = (-1,  0), step =  53, eigenelements in eig[ 54], ind_ev =   1
-- #  3, endpoint at p ≈ +0.30000000,                                                                     step =  75
+- #  1,       bp at p ≈ +0.00000281 ∈ (-0.00000065, +0.00000281), |δp|=3e-06, [converged], δ = ( 1,  0), step =  31, eigenelements in eig[ 32], ind_ev =   1
+- #  2,       bp at p ≈ +0.15000016 ∈ (+0.14999995, +0.15000016), |δp|=2e-07, [   guessL], δ = (-1,  0), step =  53, eigenelements in eig[ 54], ind_ev =   1
+- #  3, endpoint at p ≈ +0.30000000,                                                                     step =  75
 

Example with nonsimple branch points

To show the ability of the branch switching method to cope with non simple branch points, we look at the normal form of the Pitchfork with D6 symmetry which occurs frequently in problems with hexagonal symmetry. You may want to look at Bratu–Gelfand problem for a non trivial example of use.

using Revise, Plots
 using BifurcationKit, Setfield, LinearAlgebra
 const BK = BifurcationKit
@@ -487,4 +487,4 @@
 graphplot(_g, 
 	node_weights = ones(nv(_g)).*10, 
 	names=[props(_g, ve)[:code] for ve in vertices(_g)], 
-	curvature_scalar=0.)
+ curvature_scalar=0.) diff --git a/dev/Borderedarrays/index.html b/dev/Borderedarrays/index.html index 05dd38a6..5add89ac 100644 --- a/dev/Borderedarrays/index.html +++ b/dev/Borderedarrays/index.html @@ -1,2 +1,2 @@ -Bordered arrays · Bifurcation Analysis in Julia

Bordered Arrays

Here are some informations on a composite type which is used all over the package to hold a couple (array, array) or (array, scalar) while implementing the methods described in Requested methods for Custom State.

BifurcationKit.BorderedArrayType
x = BorderedArray(vec1, vec2)

This defines an array (although not <: AbstractArray) to hold two arrays or an array and a scalar. This is useful when one wants to add constraints (phase, ...) to a functional for example. It is used throughout the package for the Pseudo Arc Length Continuation, for the continuation of Fold / Hopf points, for periodic orbits... It is also used to define periodic orbits as (orbit, period). As such, it is a convenient alternative to cat, vcat and friends. We chose not to make it a subtype of AbstractArray as we wish to apply the current package to general "arrays", see Requested methods for Custom State. Finally, it proves useful for the GPU where the operation x[end] can be slow.

+Bordered arrays · Bifurcation Analysis in Julia

Bordered Arrays

Here are some informations on a composite type which is used all over the package to hold a couple (array, array) or (array, scalar) while implementing the methods described in Requested methods for Custom State.

BifurcationKit.BorderedArrayType
x = BorderedArray(vec1, vec2)

This defines an array (although not <: AbstractArray) to hold two arrays or an array and a scalar. This is useful when one wants to add constraints (phase, ...) to a functional for example. It is used throughout the package for the Pseudo Arc Length Continuation, for the continuation of Fold / Hopf points, for periodic orbits... It is also used to define periodic orbits as (orbit, period). As such, it is a convenient alternative to cat, vcat and friends. We chose not to make it a subtype of AbstractArray as we wish to apply the current package to general "arrays", see Requested methods for Custom State. Finally, it proves useful for the GPU where the operation x[end] can be slow.

diff --git a/dev/DeflatedContinuation/index.html b/dev/DeflatedContinuation/index.html index fbbaf7f2..a9b5ed6e 100644 --- a/dev/DeflatedContinuation/index.html +++ b/dev/DeflatedContinuation/index.html @@ -49,1310 +49,1311 @@ plot(brdc) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/dev/EventCallback/index.html b/dev/EventCallback/index.html index 35998127..ab368a43 100644 --- a/dev/EventCallback/index.html +++ b/dev/EventCallback/index.html @@ -42,66 +42,66 @@ If `br` is the name of the branch, ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]` -- # 1, userC-1 at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0, 0), step = 25, eigenelements in eig[ 26], ind_ev = 0 -- # 2, userC-1 at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [ guessL], δ = ( 0, 0), step = 42, eigenelements in eig[ 43], ind_ev = 0 -- # 3, userC-2 at p1 ≈ -2.30843868 ∈ (-2.30845151, -2.30843868), |δp|=1e-05, [converged], δ = ( 0, 0), step = 47, eigenelements in eig[ 48], ind_ev = 0 -- # 4, userC-1 at p1 ≈ -1.99999219 ∈ (-2.00002233, -1.99999219), |δp|=3e-05, [converged], δ = ( 0, 0), step = 50, eigenelements in eig[ 51], ind_ev = 0 -- # 5, userC-2 at p1 ≈ -0.83492016 ∈ (-0.83492251, -0.83492016), |δp|=2e-06, [ guessL], δ = ( 0, 0), step = 62, eigenelements in eig[ 63], ind_ev = 0 -- # 6, userC-2 at p1 ≈ +1.14337663 ∈ (+1.14335658, +1.14337663), |δp|=2e-05, [converged], δ = ( 0, 0), step = 106, eigenelements in eig[107], ind_ev = 0 -- # 7, endpoint at p1 ≈ +4.00000000, step = 128 +- # 1, userC-1 at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0, 0), step = 25, eigenelements in eig[ 26], ind_ev = 0 +- # 2, userC-1 at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [ guessL], δ = ( 0, 0), step = 42, eigenelements in eig[ 43], ind_ev = 0 +- # 3, userC-2 at p1 ≈ -2.30843868 ∈ (-2.30845151, -2.30843868), |δp|=1e-05, [converged], δ = ( 0, 0), step = 47, eigenelements in eig[ 48], ind_ev = 0 +- # 4, userC-1 at p1 ≈ -1.99999219 ∈ (-2.00002233, -1.99999219), |δp|=3e-05, [converged], δ = ( 0, 0), step = 50, eigenelements in eig[ 51], ind_ev = 0 +- # 5, userC-2 at p1 ≈ -0.83492016 ∈ (-0.83492251, -0.83492016), |δp|=2e-06, [ guessL], δ = ( 0, 0), step = 62, eigenelements in eig[ 63], ind_ev = 0 +- # 6, userC-2 at p1 ≈ +1.14337663 ∈ (+1.14335658, +1.14337663), |δp|=2e-05, [converged], δ = ( 0, 0), step = 106, eigenelements in eig[107], ind_ev = 0 +- # 7, endpoint at p1 ≈ +4.00000000, step = 128

This shows for example that the first component of the event was detected userC-1 first. This yields

plot(br)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

You can also name the events as follows

 br = continuation(args...; kwargs...,
  	event = BK.ContinuousEvent(2,
  		(iter, state) -> (getp(state)+2, getx(state)[1]-1),
@@ -116,66 +116,66 @@
 If `br` is the name of the branch,
 ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
 
-- #  1,   event1 at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0,  0), step =  25, eigenelements in eig[ 26], ind_ev =   0
-- #  2,   event1 at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [   guessL], δ = ( 0,  0), step =  42, eigenelements in eig[ 43], ind_ev =   0
-- #  3,   event2 at p1 ≈ -2.30843868 ∈ (-2.30845151, -2.30843868), |δp|=1e-05, [converged], δ = ( 0,  0), step =  47, eigenelements in eig[ 48], ind_ev =   0
-- #  4,   event1 at p1 ≈ -1.99999219 ∈ (-2.00002233, -1.99999219), |δp|=3e-05, [converged], δ = ( 0,  0), step =  50, eigenelements in eig[ 51], ind_ev =   0
-- #  5,   event2 at p1 ≈ -0.83492016 ∈ (-0.83492251, -0.83492016), |δp|=2e-06, [   guessL], δ = ( 0,  0), step =  62, eigenelements in eig[ 63], ind_ev =   0
-- #  6,   event2 at p1 ≈ +1.14337663 ∈ (+1.14335658, +1.14337663), |δp|=2e-05, [converged], δ = ( 0,  0), step = 106, eigenelements in eig[107], ind_ev =   0
-- #  7, endpoint at p1 ≈ +4.00000000,                                                                     step = 128
+- #  1,   event1 at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0,  0), step =  25, eigenelements in eig[ 26], ind_ev =   0
+- #  2,   event1 at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [   guessL], δ = ( 0,  0), step =  42, eigenelements in eig[ 43], ind_ev =   0
+- #  3,   event2 at p1 ≈ -2.30843868 ∈ (-2.30845151, -2.30843868), |δp|=1e-05, [converged], δ = ( 0,  0), step =  47, eigenelements in eig[ 48], ind_ev =   0
+- #  4,   event1 at p1 ≈ -1.99999219 ∈ (-2.00002233, -1.99999219), |δp|=3e-05, [converged], δ = ( 0,  0), step =  50, eigenelements in eig[ 51], ind_ev =   0
+- #  5,   event2 at p1 ≈ -0.83492016 ∈ (-0.83492251, -0.83492016), |δp|=2e-06, [   guessL], δ = ( 0,  0), step =  62, eigenelements in eig[ 63], ind_ev =   0
+- #  6,   event2 at p1 ≈ +1.14337663 ∈ (+1.14335658, +1.14337663), |δp|=2e-05, [converged], δ = ( 0,  0), step = 106, eigenelements in eig[107], ind_ev =   0
+- #  7, endpoint at p1 ≈ +4.00000000,                                                                     step = 128
 
plot(br)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Example of discrete event

You can also use discrete events to detect a change. For example, the following detect when the parameter value equals -2:

br = continuation(args...; kwargs...,
 	event = BK.DiscreteEvent(1,
 		(iter, state) -> getp(state)>-2))
 ┌─ Curve type: EquilibriumCont
@@ -188,10 +188,10 @@ 

userD at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0, 0), step = 25, eigenelements in eig[ 26], ind_ev = 0 -- # 2, userD at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [ guessL], δ = ( 0, 0), step = 42, eigenelements in eig[ 43], ind_ev = 0 -- # 3, userD at p1 ≈ -1.99999434 ∈ (-2.00000187, -1.99999434), |δp|=8e-06, [converged], δ = ( 0, 0), step = 49, eigenelements in eig[ 50], ind_ev = 0 -- # 4, endpoint at p1 ≈ +4.00000000, step = 127 +- # 1, userD at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0, 0), step = 25, eigenelements in eig[ 26], ind_ev = 0 +- # 2, userD at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [ guessL], δ = ( 0, 0), step = 42, eigenelements in eig[ 43], ind_ev = 0 +- # 3, userD at p1 ≈ -1.99999434 ∈ (-2.00000187, -1.99999434), |δp|=8e-06, [converged], δ = ( 0, 0), step = 49, eigenelements in eig[ 50], ind_ev = 0 +- # 4, endpoint at p1 ≈ +4.00000000, step = 127

Example of PairOfEvents event

Let us be a bit more creative and combine a continuous event with a discrete one:

br = continuation(args...; kwargs...,
 	event = BK.PairOfEvents(
 		BK.ContinuousEvent(1, (iter, state) -> getp(state)),
@@ -205,11 +205,11 @@ 

userD-1 at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0, 0), step = 25, eigenelements in eig[ 26], ind_ev = 0 -- # 2, userD-1 at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [ guessL], δ = ( 0, 0), step = 42, eigenelements in eig[ 43], ind_ev = 0 -- # 3, userD-1 at p1 ≈ -1.99999434 ∈ (-2.00000187, -1.99999434), |δp|=8e-06, [converged], δ = ( 0, 0), step = 49, eigenelements in eig[ 50], ind_ev = 0 -- # 4, userC-1 at p1 ≈ +0.00000326 ∈ (-0.00000027, +0.00000326), |δp|=4e-06, [ guess], δ = ( 0, 0), step = 69, eigenelements in eig[ 70], ind_ev = 0 -- # 5, endpoint at p1 ≈ +4.00000000, step = 127 +- # 1, userD at p1 ≈ -1.99998635 ∈ (-2.00000275, -1.99998635), |δp|=2e-05, [converged], δ = ( 0, 0), step = 25, eigenelements in eig[ 26], ind_ev = 0 +- # 2, userD at p1 ≈ -2.00000133 ∈ (-2.00000133, -1.99999793), |δp|=3e-06, [ guessL], δ = ( 0, 0), step = 42, eigenelements in eig[ 43], ind_ev = 0 +- # 3, userD at p1 ≈ -1.99999434 ∈ (-2.00000187, -1.99999434), |δp|=8e-06, [converged], δ = ( 0, 0), step = 49, eigenelements in eig[ 50], ind_ev = 0 +- # 4, userC at p1 ≈ +0.00000326 ∈ (-0.00000027, +0.00000326), |δp|=4e-06, [ guess], δ = ( 0, 0), step = 69, eigenelements in eig[ 70], ind_ev = 0 +- # 5, endpoint at p1 ≈ +4.00000000, step = 127

Here userD-1 means that the first component of the discrete event was detected. Of course, you can name the event like done above.

Example of set of events

We can combine more events and chain them like we want using SetOfEvents. In this example, we show how to do bifurcation detection and event location altogether:

ev1 = BK.ContinuousEvent(1, (iter, state) -> getp(state)-1)
 ev2 = BK.ContinuousEvent(2, (iter, state) -> (getp(state)-2, getp(state)-2.5))
 # event to detect bifurcation
@@ -228,213 +228,213 @@ 

bp at p1 ≈ -1.13352254 ∈ (-1.13352254, -1.13351184), |δp|=1e-05, [ guess], δ = ( 1, 0), step = 33, eigenelements in eig[ 34], ind_ev = 1 -- # 2, bp at p1 ≈ -2.32505862 ∈ (-2.32505862, -2.32505849), |δp|=1e-07, [converged], δ = (-1, 0), step = 46, eigenelements in eig[ 47], ind_ev = 1 -- # 3, hopf at p1 ≈ -0.95384426 ∈ (-0.95385423, -0.95384426), |δp|=1e-05, [converged], δ = ( 2, 2), step = 60, eigenelements in eig[ 61], ind_ev = 2 -- # 4, hopf at p1 ≈ +0.95385225 ∈ (+0.95384228, +0.95385225), |δp|=1e-05, [converged], δ = (-2, -2), step = 80, eigenelements in eig[ 81], ind_ev = 2 -- # 5, userC1 at p1 ≈ +1.00000070 ∈ (+0.99999933, +1.00000070), |δp|=1e-06, [ guess], δ = ( 0, 0), step = 82, eigenelements in eig[ 83], ind_ev = 0 -- # 6, userC2-1 at p1 ≈ +2.00011806 ∈ (+1.99963580, +2.00011806), |δp|=5e-04, [converged], δ = ( 0, 0), step = 91, eigenelements in eig[ 92], ind_ev = 0 -- # 7, bp at p1 ≈ +2.32505862 ∈ (+2.32505862, +2.32505862), |δp|=2e-10, [ guess], δ = ( 1, 0), step = 95, eigenelements in eig[ 96], ind_ev = 1 -- # 8, userC2-1 at p1 ≈ +1.99990023 ∈ (+1.99990023, +2.00011780), |δp|=2e-04, [converged], δ = ( 0, 0), step = 99, eigenelements in eig[100], ind_ev = 0 -- # 9, bp at p1 ≈ +1.13286430 ∈ (+1.13286415, +1.13286430), |δp|=2e-07, [converged], δ = (-1, 0), step = 108, eigenelements in eig[109], ind_ev = 1 -- # 10, userC2-1 at p1 ≈ +2.00003159 ∈ (+1.99996599, +2.00003159), |δp|=7e-05, [converged], δ = ( 0, 0), step = 116, eigenelements in eig[117], ind_ev = 0 -- # 11, userC2-2 at p1 ≈ +2.50049932 ∈ (+2.49996432, +2.50049932), |δp|=5e-04, [converged], δ = ( 0, 0), step = 120, eigenelements in eig[121], ind_ev = 0 -- # 12, endpoint at p1 ≈ +3.74519842, step = 129 +- # 1, bp at p1 ≈ -1.13352254 ∈ (-1.13352254, -1.13351184), |δp|=1e-05, [ guess], δ = ( 1, 0), step = 33, eigenelements in eig[ 34], ind_ev = 1 +- # 2, bp at p1 ≈ -2.32505862 ∈ (-2.32505862, -2.32505849), |δp|=1e-07, [converged], δ = (-1, 0), step = 46, eigenelements in eig[ 47], ind_ev = 1 +- # 3, hopf at p1 ≈ -0.95384426 ∈ (-0.95385423, -0.95384426), |δp|=1e-05, [converged], δ = ( 2, 2), step = 60, eigenelements in eig[ 61], ind_ev = 2 +- # 4, hopf at p1 ≈ +0.95385225 ∈ (+0.95384228, +0.95385225), |δp|=1e-05, [converged], δ = (-2, -2), step = 80, eigenelements in eig[ 81], ind_ev = 2 +- # 5, userC1 at p1 ≈ +1.00000070 ∈ (+0.99999933, +1.00000070), |δp|=1e-06, [ guess], δ = ( 0, 0), step = 82, eigenelements in eig[ 83], ind_ev = 0 +- # 6, userC2-1 at p1 ≈ +2.00011806 ∈ (+1.99963580, +2.00011806), |δp|=5e-04, [converged], δ = ( 0, 0), step = 91, eigenelements in eig[ 92], ind_ev = 0 +- # 7, bp at p1 ≈ +2.32505862 ∈ (+2.32505862, +2.32505862), |δp|=2e-10, [ guess], δ = ( 1, 0), step = 95, eigenelements in eig[ 96], ind_ev = 1 +- # 8, userC2-1 at p1 ≈ +1.99990023 ∈ (+1.99990023, +2.00011780), |δp|=2e-04, [converged], δ = ( 0, 0), step = 99, eigenelements in eig[100], ind_ev = 0 +- # 9, bp at p1 ≈ +1.13286430 ∈ (+1.13286415, +1.13286430), |δp|=2e-07, [converged], δ = (-1, 0), step = 108, eigenelements in eig[109], ind_ev = 1 +- # 10, userC2-1 at p1 ≈ +2.00003159 ∈ (+1.99996599, +2.00003159), |δp|=7e-05, [converged], δ = ( 0, 0), step = 116, eigenelements in eig[117], ind_ev = 0 +- # 11, userC2-2 at p1 ≈ +2.50049932 ∈ (+2.49996432, +2.50049932), |δp|=5e-04, [converged], δ = ( 0, 0), step = 120, eigenelements in eig[121], ind_ev = 0 +- # 12, endpoint at p1 ≈ +3.74519842, step = 129

Which gives

plot(br)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/FoldContinuationPO/index.html b/dev/FoldContinuationPO/index.html index d1b9137a..4d985d28 100644 --- a/dev/FoldContinuationPO/index.html +++ b/dev/FoldContinuationPO/index.html @@ -1,5 +1,5 @@ -Fold continuation (2 params) · Bifurcation Analysis in Julia

Continuation of Fold of periodic orbits

Work in progress

Continuation of Fold of POs is a recent addition. It has not been thoroughly tested.

In this page, we explain how to perform continuation of Fold points and detect the associated codim 2 bifurcations.

List of detected codim 2 bifurcation points

Bifurcationsymbol used
Cuspcusp
Strong resonance 1:1 bifurcationR1
Fold / FlipfoldFlip
Fold / Neimark-SackerfoldNS

In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.

Fold continuation

The continuation of Fold bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation) for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.

Detection of codim 2 bifurcation points

You can detect the following codim 2 bifurcation points by using the keyword argument detect_codim2_bifurcation in the method continuation

  • the detection of Cusp (Cusp) is done by the detection of Fold bifurcation points along the curve of Folds by monitoring the parameter component of the tangent.
  • the detection the above bifurcation points is done by monitoring the number of eigenvalues $\lambda$ such that $\Re\lambda > \min\limits_{\nu\in\Sigma(dF)}|\Re\nu|$ and $\Im\lambda > \epsilon$ where $\epsilon$ is the Newton tolerance.

Setting the jacobian

In order to apply the newton algorithm to the Fold functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):

  • [Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the Fold functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)
  • for jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.
  • for jacobian_ma = :minaug, a specific procedure for evaluating the jacobian and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.

Codim 2 continuation

To compute the codim 2 curve of Fold points of periodic orbits, one can call continuation with the following options

BifurcationKit.continuationFunction
continuation(br, ind_bif, lens2)
+Fold continuation (2 params) · Bifurcation Analysis in Julia

Continuation of Fold of periodic orbits

Work in progress

Continuation of Fold of POs is a recent addition. It has not been thoroughly tested.

In this page, we explain how to perform continuation of Fold points and detect the associated codim 2 bifurcations.

List of detected codim 2 bifurcation points

Bifurcationsymbol used
Cuspcusp
Strong resonance 1:1 bifurcationR1
Fold / FlipfoldFlip
Fold / Neimark-SackerfoldNS

In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.

Fold continuation

The continuation of Fold bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation) for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.

Detection of codim 2 bifurcation points

You can detect the following codim 2 bifurcation points by using the keyword argument detect_codim2_bifurcation in the method continuation

  • the detection of Cusp (Cusp) is done by the detection of Fold bifurcation points along the curve of Folds by monitoring the parameter component of the tangent.
  • the detection the above bifurcation points is done by monitoring the number of eigenvalues $\lambda$ such that $\Re\lambda > \min\limits_{\nu\in\Sigma(dF)}|\Re\nu|$ and $\Im\lambda > \epsilon$ where $\epsilon$ is the Newton tolerance.

Setting the jacobian

In order to apply the newton algorithm to the Fold functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):

  • [Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the Fold functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)
  • for jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.
  • for jacobian_ma = :minaug, a specific procedure for evaluating the jacobian and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.

Codim 2 continuation

To compute the codim 2 curve of Fold points of periodic orbits, one can call continuation with the following options

BifurcationKit.continuationFunction
continuation(br, ind_bif, lens2; ...)
 continuation(
     br,
     ind_bif,
@@ -10,4 +10,4 @@
     detect_codim2_bifurcation,
     kwargs...
 )
-

Codimension 2 continuation of Fold / Hopf points. This function turns an initial guess for a Fold / Hopf point into a curve of Fold / Hopf points based on a Minimally Augmented formulation. The arguments are as follows

  • br results returned after a call to continuation
  • ind_bif bifurcation index in br
  • lens2 second parameter used for the continuation, the first one is the one used to compute br, e.g. getlens(br)
  • options_cont = br.contparams arguments to be passed to the regular continuation

Optional arguments:

  • bdlinsolver bordered linear solver for the constraint equation
  • update_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps
  • start_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements
  • detect_codim2_bifurcation ∈ {0,1,2} whether to detect Bogdanov-Takens, Bautin and Cusp. If equals 1 non precise detection is used. If equals 2, a bisection method is used to locate the bifurcations.
  • kwargs keywords arguments to be passed to the regular continuation

where the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br you want to refine.

ODE problems

For ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()

start_with_eigen

It is recommended that you use the option start_with_eigen = true

where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

+

Codimension 2 continuation of Fold / Hopf points. This function turns an initial guess for a Fold / Hopf point into a curve of Fold / Hopf points based on a Minimally Augmented formulation. The arguments are as follows

  • br results returned after a call to continuation
  • ind_bif bifurcation index in br
  • lens2 second parameter used for the continuation, the first one is the one used to compute br, e.g. getlens(br)
  • options_cont = br.contparams arguments to be passed to the regular continuation

Optional arguments:

  • bdlinsolver bordered linear solver for the constraint equation
  • update_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps
  • start_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements
  • detect_codim2_bifurcation ∈ {0,1,2} whether to detect Bogdanov-Takens, Bautin and Cusp. If equals 1 non precise detection is used. If equals 2, a bisection method is used to locate the bifurcations.
  • kwargs keywords arguments to be passed to the regular continuation

where the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br you want to refine.

ODE problems

For ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()

start_with_eigen

It is recommended that you use the option start_with_eigen = true

where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

diff --git a/dev/IntroContinuation/index.html b/dev/IntroContinuation/index.html index ccdc96e3..32e2d1d9 100644 --- a/dev/IntroContinuation/index.html +++ b/dev/IntroContinuation/index.html @@ -1,2 +1,2 @@ -Introduction · Bifurcation Analysis in Julia

Continuation methods: introduction

The goal of these methods[Kuz],[Govaerts],[Rabinowitz],[Mei],[Keller] is to find solutions $x\in\mathbb R^n$ to nonlinear equations

\[\mathbb R^n\ni F(x,p) = 0 \quad\tag{E}\]

as function of a real parameter $p$. Given a known solution $(x_0,p_0)$, we can, under reasonable assumptions, continue it by computing a 1d curve of solutions $\gamma = (x(s),p(s))_{s\in I}$ passing through $(x_0,p_0)$.

For the sequel, it is convenient to use the following formalism [Kuz]

  1. prediction of the next point
  2. correction
  3. step size control.

Natural continuation

More information is available at Predictors - Correctors

We just use this simple continuation method to give a trivial example of the formalism. Knowing $(x_0, p_0)$, we form the predictor $(x_0, p_0+ds)$ for some $ds$ and use it as a guess for a Newton corrector applied to $x\to F(x, p_0+ds)$. The corrector is thus the newton algorithm.

This continuation method is continuation(prob, Natural(), options).

Usage

You should almost never use this predictor for computations. It fails at turning points, is not adaptive, ...

Step size control

Each time the corrector phase failed, the step size $ds$ is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size can be controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.

References

  • Kuz

    Kuznetsov, Elements of Applied Bifurcation Theory.

  • Govaerts

    Govaerts, Numerical Methods for Bifurcations of Dynamical Equilibria; Allgower and Georg, Numerical Continuation Methods

  • Rabinowitz

    Rabinowitz, Applications of Bifurcation Theory; Dankowicz and Schilder, Recipes for Continuation

  • Mei

    Mei, Numerical Bifurcation Analysis for Reaction-Diffusion Equations

  • Keller

    Keller, Lectures on Numerical Methods in Bifurcation Problems

+Introduction · Bifurcation Analysis in Julia

Continuation methods: introduction

The goal of these methods[Kuz],[Govaerts],[Rabinowitz],[Mei],[Keller] is to find solutions $x\in\mathbb R^n$ to nonlinear equations

\[\mathbb R^n\ni F(x,p) = 0 \quad\tag{E}\]

as function of a real parameter $p$. Given a known solution $(x_0,p_0)$, we can, under reasonable assumptions, continue it by computing a 1d curve of solutions $\gamma = (x(s),p(s))_{s\in I}$ passing through $(x_0,p_0)$.

For the sequel, it is convenient to use the following formalism [Kuz]

  1. prediction of the next point
  2. correction
  3. step size control.

Natural continuation

More information is available at Predictors - Correctors

We just use this simple continuation method to give a trivial example of the formalism. Knowing $(x_0, p_0)$, we form the predictor $(x_0, p_0+ds)$ for some $ds$ and use it as a guess for a Newton corrector applied to $x\to F(x, p_0+ds)$. The corrector is thus the newton algorithm.

This continuation method is continuation(prob, Natural(), options).

Usage

You should almost never use this predictor for computations. It fails at turning points, is not adaptive, ...

Step size control

Each time the corrector phase failed, the step size $ds$ is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size can be controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.

References

  • Kuz

    Kuznetsov, Elements of Applied Bifurcation Theory.

  • Govaerts

    Govaerts, Numerical Methods for Bifurcations of Dynamical Equilibria; Allgower and Georg, Numerical Continuation Methods

  • Rabinowitz

    Rabinowitz, Applications of Bifurcation Theory; Dankowicz and Schilder, Recipes for Continuation

  • Mei

    Mei, Numerical Bifurcation Analysis for Reaction-Diffusion Equations

  • Keller

    Keller, Lectures on Numerical Methods in Bifurcation Problems

diff --git a/dev/ModulatedTW/index.html b/dev/ModulatedTW/index.html index 14e38179..153c4534 100644 --- a/dev/ModulatedTW/index.html +++ b/dev/ModulatedTW/index.html @@ -1,2 +1,2 @@ -Modulated Travelling waves · Bifurcation Analysis in Julia

Modulated travelling wave (MTW), $N_g=1$

This is work in progress

A modulated travelling wave with period $T$ satisfies $q(x,t+T) = q(x-s T,t)$. Equivalently, using a moving frame to freeze the wave $\xi=x-st$, it holds that $\tilde q(\xi,t+T) = \tilde q(\xi,t)$ where $\tilde q(\xi,t):=q(\xi+st,t)$. Hence, $\tilde q$ is a periodic solution to

\[\partial_t\tilde q = -sT\cdot\tilde q+F(\tilde q,p).\tag{eqMWP}\]

Stability of the MTW is determined by the spectrum of the linearized time-$T$ map associated with (eqMWP).

References

  • Beyn

    Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

  • Sandstede

    Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.

+Modulated Travelling waves · Bifurcation Analysis in Julia

Modulated travelling wave (MTW), $N_g=1$

This is work in progress

A modulated travelling wave with period $T$ satisfies $q(x,t+T) = q(x-s T,t)$. Equivalently, using a moving frame to freeze the wave $\xi=x-st$, it holds that $\tilde q(\xi,t+T) = \tilde q(\xi,t)$ where $\tilde q(\xi,t):=q(\xi+st,t)$. Hence, $\tilde q$ is a periodic solution to

\[\partial_t\tilde q = -sT\cdot\tilde q+F(\tilde q,p).\tag{eqMWP}\]

Stability of the MTW is determined by the spectrum of the linearized time-$T$ map associated with (eqMWP).

References

  • Beyn

    Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

  • Sandstede

    Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.

diff --git a/dev/MooreSpence/index.html b/dev/MooreSpence/index.html index 3b63c997..98b7a2f0 100644 --- a/dev/MooreSpence/index.html +++ b/dev/MooreSpence/index.html @@ -14,4 +14,4 @@ 0 \\ 1 \end{array}\right), \quad j=0,1,2, \ldots -\end{array}\right.\]

We initialise $\phi_1^0$ with the tangent.

Step size control

Each time the corrector fails, the step size $ds$ is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.

References

  • Meijer

    Meijer, Dercole, and Oldeman, “Numerical Bifurcation Analysis.”

+\end{array}\right.\]

We initialise $\phi_1^0$ with the tangent.

Step size control

Each time the corrector fails, the step size $ds$ is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.

References

  • Meijer

    Meijer, Dercole, and Oldeman, “Numerical Bifurcation Analysis.”

diff --git a/dev/NSContinuationPO/index.html b/dev/NSContinuationPO/index.html index b4704e76..171b05b0 100644 --- a/dev/NSContinuationPO/index.html +++ b/dev/NSContinuationPO/index.html @@ -18,4 +18,4 @@ \partial_{u}F_{po} & \partial_pF_{po} & 0 \\ \partial_u\sigma_r & \partial_p\sigma_r & \partial_\omega\sigma_r\\ \partial_u\sigma_i & \partial_p\sigma_i & \partial_\omega\sigma_i -\end{array}\right].\]

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

+\end{array}\right].\]

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

diff --git a/dev/PALC/index.html b/dev/PALC/index.html index 9a3bbd14..8cc55bef 100644 --- a/dev/PALC/index.html +++ b/dev/PALC/index.html @@ -1,2 +1,2 @@ -PALC · Bifurcation Analysis in Julia

Pseudo arclength continuation

This is one of the various continuation methods implemented in BifurcationKit.jl. It is set by the option PALC(tangent = Bordered()) or PALC(tangent = Secant()) in continuation. See also PALC for more information.

For solving

\[\mathbb R^n\ni F(x,p) = 0 \quad\tag{E}\]

using a Newton algorithm, we miss an equation. The simplest way is to select an hyperplane in the space $\mathbb R^n\times \mathbb R$ passing through $(x_0,p_0)$:

\[N(x, p) = \frac{\theta}{n} \langle x - x_0, dx_0\rangle + (1 - \theta)\cdot(p - p_0)\cdot dp_0 - ds = 0\tag{N}\]

with $\theta\in[0,1]$ and where $ds$ is the pseudo arclength (see [Keller]).

Parameter `θ`

The parameter θ in the struct ContinuationPar is very important. It should be tuned for the continuation to work properly especially in the case of large problems where the $\langle x - x_0, dx_0\rangle$ component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint $N$ involves the term $1-θ$.

Predictor

The possible predictors are listed in Predictors - Correctors.

Corrector

The corrector is the newton algorithm for finding the roots $(x,p)$ of

\[\begin{bmatrix} F(x,p) \\ N(x,p)\end{bmatrix} = 0\tag{PALC}\]

Linear Algebra

Let us discuss more about the norm and dot product. First, the option normC continuation specifies the norm used to evaluate the residual in the following way: $max(normC(F(x,p)), |N(x,p)|)<tol$. It is thus used as a stopping criterion for the corrector. The dot product (resp. norm) used in $N$ and in the (iterative) linear solvers is LinearAlgebra.dot (resp. LinearAlgebra.norm). It can be changed by importing these functions and redefining it. Note that by default, the $\mathcal L^2$ norm is used. These details are important because of the constraint $N$ which incorporates the factor length. For some custom composite type implementing a Vector space, the dot product could already incorporates the length factor in which case you should either redefine the dot product or change $\theta$.

The linear solver for the linear problem associated to (PALC) is set by the option linear_algo in continuation: it is one of Bordered linear solvers (BLS).

Dot product

In the constraint $N$ above, the scalar product is in fact saved in BifurcationKit.jl as dotp(x,y) -> dot(x,y)/length(y). This is used in the bordered linear solvers associated to PALC. If you want to use your own dot product, you can pass

dotPALC = BK.DotTheta(mydot),

to continuation. Additionally, you may want to provide the linear operator P such that mydot(x,y) = dot(x, A*y), especially if you intend too use the linear solver MatrixBLS. We refer to BifurcationKit.DotTheta for more details.

Step size control

Each time the corrector fails, the step size $ds$ is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.

References

  • Keller

    Keller, Herbert B. Lectures on Numerical Methods in Bifurcation Problems. Springer, 1988

+PALC · Bifurcation Analysis in Julia

Pseudo arclength continuation

This is one of the various continuation methods implemented in BifurcationKit.jl. It is set by the option PALC(tangent = Bordered()) or PALC(tangent = Secant()) in continuation. See also PALC for more information.

For solving

\[\mathbb R^n\ni F(x,p) = 0 \quad\tag{E}\]

using a Newton algorithm, we miss an equation. The simplest way is to select an hyperplane in the space $\mathbb R^n\times \mathbb R$ passing through $(x_0,p_0)$:

\[N(x, p) = \frac{\theta}{n} \langle x - x_0, dx_0\rangle + (1 - \theta)\cdot(p - p_0)\cdot dp_0 - ds = 0\tag{N}\]

with $\theta\in[0,1]$ and where $ds$ is the pseudo arclength (see [Keller]).

Parameter `θ`

The parameter θ in the struct ContinuationPar is very important. It should be tuned for the continuation to work properly especially in the case of large problems where the $\langle x - x_0, dx_0\rangle$ component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint $N$ involves the term $1-θ$.

Predictor

The possible predictors are listed in Predictors - Correctors.

Corrector

The corrector is the newton algorithm for finding the roots $(x,p)$ of

\[\begin{bmatrix} F(x,p) \\ N(x,p)\end{bmatrix} = 0\tag{PALC}\]

Linear Algebra

Let us discuss more about the norm and dot product. First, the option normC continuation specifies the norm used to evaluate the residual in the following way: $max(normC(F(x,p)), |N(x,p)|)<tol$. It is thus used as a stopping criterion for the corrector. The dot product (resp. norm) used in $N$ and in the (iterative) linear solvers is LinearAlgebra.dot (resp. LinearAlgebra.norm). It can be changed by importing these functions and redefining it. Note that by default, the $\mathcal L^2$ norm is used. These details are important because of the constraint $N$ which incorporates the factor length. For some custom composite type implementing a Vector space, the dot product could already incorporates the length factor in which case you should either redefine the dot product or change $\theta$.

The linear solver for the linear problem associated to (PALC) is set by the option linear_algo in continuation: it is one of Bordered linear solvers (BLS).

Dot product

In the constraint $N$ above, the scalar product is in fact saved in BifurcationKit.jl as dotp(x,y) -> dot(x,y)/length(y). This is used in the bordered linear solvers associated to PALC. If you want to use your own dot product, you can pass

dotPALC = BK.DotTheta(mydot),

to continuation. Additionally, you may want to provide the linear operator P such that mydot(x,y) = dot(x, A*y), especially if you intend too use the linear solver MatrixBLS. We refer to BifurcationKit.DotTheta for more details.

Step size control

Each time the corrector fails, the step size $ds$ is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.

References

  • Keller

    Keller, Herbert B. Lectures on Numerical Methods in Bifurcation Problems. Springer, 1988

diff --git a/dev/PDContinuationPO/index.html b/dev/PDContinuationPO/index.html index 3df3f3b3..e71f41eb 100644 --- a/dev/PDContinuationPO/index.html +++ b/dev/PDContinuationPO/index.html @@ -17,4 +17,4 @@ \end{array}\right).\]

The jacobian of the PD functional to use for the Newton algorithm

\[\left[\begin{array}{cc} \partial_{u}F_{po} & \partial_pF_{po} \\ \partial_u\sigma & \partial_p\sigma -\end{array}\right].\]

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

+\end{array}\right].\]

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

diff --git a/dev/Predictors/index.html b/dev/Predictors/index.html index 2e019db6..47de93ac 100644 --- a/dev/Predictors/index.html +++ b/dev/Predictors/index.html @@ -1,2 +1,2 @@ -Predictors / correctors · Bifurcation Analysis in Julia

Predictors - Correctors

The continuation method works with the following pattern (see [Allgower1990]):

  1. compute tangent
  2. call predictor (based on tangent, mostly)
  3. call corrector

There are several couples predictor-tangent/corrector which can be used in BifurcationKit.jl as we now explain. The tangent computation is formally included in the predictor whereas it is a distinct function in the code.

Corrector

Note that setting the predictor also sets the corresponding corrector: it selects the couple predictor-corrector. You don't have (in fact cannot) set them independently.

1. Natural, zeroth order predictor

This is the dumbest predictor based on the formula $(x_1,p_1) = (x_0, p_0 + ds)$ with Newton corrector ; it fails at Turning points. This is set by the algorithm Natural() in continuation. For matrix based jacobian, it is not faster than the pseudo-arclength predictor because the factorisation of the jacobian is cached. For Matrix-free methods, this predictor can be faster than the following ones until it hits a Turning point.

2. First order predictor

This predictor is based on a computation of the tangent $\tau = (dx,dp)$ to the curve of solutions, it is given by $(x_1,p_1) = (x_0,p_0) + ds\cdot \tau$. This predictor passes Turning points when used with PALC Newton corrector. BifurcationKit.jl provides two ways to compute the tangent $(dx, dp)$.

2a. Secant predictor

This predictor is called secant and is parametrized by the algorithm PALC(tangent = Secant()) in continuation with Secant . It is computed by $(dx, dp) = (z_1, p_1) - (z_0, p_0)$ and normalized by the norm $\|(x, p)\|^2_\theta = \frac{\theta}{length(x)} \langle x,x\rangle + (1 - \theta)\cdot p^2$.

Parameter `θ`

The parameter θ in the struct ContinuationParis very important. It should be tuned for the continuation to work properly especially in the case of large problems where the $\langle x - x_0, dx_0\rangle$ component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint $N$ involves the term $1-θ$.

2b. Bordered predictor

This predictor departs from the previous one in the way the tangent is estimated. It computes $(dx, dp)$ by solving solving the bordered linear system $\begin{bmatrix} F_x & F_p \\ \frac{\theta}{length(x)}dx_0 & (1-\theta)dp_0\end{bmatrix}\begin{bmatrix}dx \\ dp\end{bmatrix} =\begin{bmatrix}0 \\ 1\end{bmatrix}$.

It is set by the algorithm PALC(tangent = Bordered()) in continuation with Bordered. The linear solver for the linear problem in $(dx, dp)$ is set by the option bls in PALC: it is one of Bordered linear solvers (BLS).

3. Polynomial predictor

The polynomial predictor is based on a fit (least square regression) of an $n$th-order polynomial $P$ on the last $k$ solution vectors, where $n < k$. The arclength $s$ is used for the polynomial which then fits the solution $(x_i,p_i,s_i)$ as $P(s_i)\approx (x_i,p_i)$. To keep $s$ in suitable range (see [Waugh]), we rescale it as $s\to \frac{s-\bar s}{\sigma}$ where $\sigma$ is the standard deviation of the $s_i$.

This algorithm is parametrized by alg = Polynomial(Fred, n, k, v0) where pred::AbstractTangentComputation is the tangent predictor used only for the first $k$ solutions before the polynomial predictor is operational and v0 is an example of guess. More information is available in Polynomial.

4. Multiple predictor (aka pmcont in pde2path)

The predictor is designed [Uecker2014] to avoid spurious branch switching and pass singular points especially in PDE where branch point density can be quite high. It is based on the use of many predictors with increasing "jumps" $(x_i,p_i) = (x_0,p_0) + i\cdot ds\cdot \tau,\ i\leq nb$ and use a corrector (PALC Newton) with the following twist. The criterion is that in each Newton step, the residual has to decrease by a factor $0<\alpha<1$:

\[\| F(u_n,p_n)\|\leq \alpha \| F(u_{n-1},p_{n-1}) \|\]

otherwise the corrector fails. The solution that is returned is the one for the highest $i$. We refer to [Uecker2014] for an exposition of the step size adaption strategy.

This algorithm is parametrized by alg = Multiple(pred, x0, α, nb) where τ is an initial tangent vector (used to set the types) and pred::PALC is a predictor. The default value is pred = PALC(). More information is available in Multiple.

  • Allgower1990

    Allgower and Georg, Numerical Continuation Methods, 1990

  • Waugh

    Waugh, Illingworth, and Juniper, “Matrix-Free Continuation of Limit Cycles for Bifurcation Analysis of Large Thermoacoustic Systems.”

  • Uecker2014

    1.Uecker, H. pde2path - A Matlab Package for Continuation and Bifurcation in 2D Elliptic Systems. NMTMA 7, 58–106 (2014).

+Predictors / correctors · Bifurcation Analysis in Julia

Predictors - Correctors

The continuation method works with the following pattern (see [Allgower1990]):

  1. compute tangent
  2. call predictor (based on tangent, mostly)
  3. call corrector

There are several couples predictor-tangent/corrector which can be used in BifurcationKit.jl as we now explain. The tangent computation is formally included in the predictor whereas it is a distinct function in the code.

Corrector

Note that setting the predictor also sets the corresponding corrector: it selects the couple predictor-corrector. You don't have (in fact cannot) set them independently.

1. Natural, zeroth order predictor

This is the dumbest predictor based on the formula $(x_1,p_1) = (x_0, p_0 + ds)$ with Newton corrector ; it fails at Turning points. This is set by the algorithm Natural() in continuation. For matrix based jacobian, it is not faster than the pseudo-arclength predictor because the factorisation of the jacobian is cached. For Matrix-free methods, this predictor can be faster than the following ones until it hits a Turning point.

2. First order predictor

This predictor is based on a computation of the tangent $\tau = (dx,dp)$ to the curve of solutions, it is given by $(x_1,p_1) = (x_0,p_0) + ds\cdot \tau$. This predictor passes Turning points when used with PALC Newton corrector. BifurcationKit.jl provides two ways to compute the tangent $(dx, dp)$.

2a. Secant predictor

This predictor is called secant and is parametrized by the algorithm PALC(tangent = Secant()) in continuation with Secant . It is computed by $(dx, dp) = (z_1, p_1) - (z_0, p_0)$ and normalized by the norm $\|(x, p)\|^2_\theta = \frac{\theta}{length(x)} \langle x,x\rangle + (1 - \theta)\cdot p^2$.

Parameter `θ`

The parameter θ in the struct ContinuationParis very important. It should be tuned for the continuation to work properly especially in the case of large problems where the $\langle x - x_0, dx_0\rangle$ component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint $N$ involves the term $1-θ$.

2b. Bordered predictor

This predictor departs from the previous one in the way the tangent is estimated. It computes $(dx, dp)$ by solving solving the bordered linear system $\begin{bmatrix} F_x & F_p \\ \frac{\theta}{length(x)}dx_0 & (1-\theta)dp_0\end{bmatrix}\begin{bmatrix}dx \\ dp\end{bmatrix} =\begin{bmatrix}0 \\ 1\end{bmatrix}$.

It is set by the algorithm PALC(tangent = Bordered()) in continuation with Bordered. The linear solver for the linear problem in $(dx, dp)$ is set by the option bls in PALC: it is one of Bordered linear solvers (BLS).

3. Polynomial predictor

The polynomial predictor is based on a fit (least square regression) of an $n$th-order polynomial $P$ on the last $k$ solution vectors, where $n < k$. The arclength $s$ is used for the polynomial which then fits the solution $(x_i,p_i,s_i)$ as $P(s_i)\approx (x_i,p_i)$. To keep $s$ in suitable range (see [Waugh]), we rescale it as $s\to \frac{s-\bar s}{\sigma}$ where $\sigma$ is the standard deviation of the $s_i$.

This algorithm is parametrized by alg = Polynomial(Fred, n, k, v0) where pred::AbstractTangentComputation is the tangent predictor used only for the first $k$ solutions before the polynomial predictor is operational and v0 is an example of guess. More information is available in Polynomial.

4. Multiple predictor (aka pmcont in pde2path)

The predictor is designed [Uecker2014] to avoid spurious branch switching and pass singular points especially in PDE where branch point density can be quite high. It is based on the use of many predictors with increasing "jumps" $(x_i,p_i) = (x_0,p_0) + i\cdot ds\cdot \tau,\ i\leq nb$ and use a corrector (PALC Newton) with the following twist. The criterion is that in each Newton step, the residual has to decrease by a factor $0<\alpha<1$:

\[\| F(u_n,p_n)\|\leq \alpha \| F(u_{n-1},p_{n-1}) \|\]

otherwise the corrector fails. The solution that is returned is the one for the highest $i$. We refer to [Uecker2014] for an exposition of the step size adaption strategy.

This algorithm is parametrized by alg = Multiple(pred, x0, α, nb) where τ is an initial tangent vector (used to set the types) and pred::PALC is a predictor. The default value is pred = PALC(). More information is available in Multiple.

  • Allgower1990

    Allgower and Georg, Numerical Continuation Methods, 1990

  • Waugh

    Waugh, Illingworth, and Juniper, “Matrix-Free Continuation of Limit Cycles for Bifurcation Analysis of Large Thermoacoustic Systems.”

  • Uecker2014

    1.Uecker, H. pde2path - A Matlab Package for Continuation and Bifurcation in 2D Elliptic Systems. NMTMA 7, 58–106 (2014).

diff --git a/dev/abs-from-codim2-eq/index.html b/dev/abs-from-codim2-eq/index.html index 6af7ce60..dba02069 100644 --- a/dev/abs-from-codim2-eq/index.html +++ b/dev/abs-from-codim2-eq/index.html @@ -24,4 +24,4 @@ autodiff = false, Teigvec = getvectortype(br), scaleζ = norm, - kwargs...)

where ind_HH is the index of the HH point in br. Note that the HH has been detected during Hopf continuation. Calling the above method thus switches from Hopf continuation to another Hopf branch automatically with the same parameter axis.

Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.

+ kwargs...)

where ind_HH is the index of the HH point in br. Note that the HH has been detected during Hopf continuation. Calling the above method thus switches from Hopf continuation to another Hopf branch automatically with the same parameter axis.

Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.

diff --git a/dev/abs-from-codim2-po/index.html b/dev/abs-from-codim2-po/index.html index ccd1ab92..c89e9a92 100644 --- a/dev/abs-from-codim2-po/index.html +++ b/dev/abs-from-codim2-po/index.html @@ -10,4 +10,4 @@ prob::AbstractPeriodicOrbitProblem ; δp = nothing, ampfactor = 1, whichns = 1, - kwargs...)

where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information). The option whichns which belongs to {1,2} controls which NS curve you want to compute.

Note that the two parameters in br will be used for the continuation of NS points of periodic orbits.

See ODE for an example of use.

+ kwargs...)

where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information). The option whichns which belongs to {1,2} controls which NS curve you want to compute.

Note that the two parameters in br will be used for the continuation of NS points of periodic orbits.

See ODE for an example of use.

diff --git a/dev/abs-from-eq/index.html b/dev/abs-from-eq/index.html index 7f002c6f..4a16389c 100644 --- a/dev/abs-from-eq/index.html +++ b/dev/abs-from-eq/index.html @@ -1,5 +1,5 @@ -From equilibria to equilibria · Bifurcation Analysis in Julia

From equilibria to equilibria

From simple branch point to equilibria

See Branch switching (branch point) for the precise method definition

You can perform automatic branch switching by calling continuation with the following options:

continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar; kwargs...)

where br is a branch computed after a call to continuation with detection of bifurcation points enabled. This call computes the branch bifurcating from the ind_bifth bifurcation point in br. An example of use is provided in 2d Bratu–Gelfand problem.

See Branch switching (branch point) precise method definition

Simple example

using BifurcationKit, Setfield, Plots
+From equilibria to equilibria · Bifurcation Analysis in Julia

From equilibria to equilibria

From simple branch point to equilibria

See Branch switching (branch point) for the precise method definition

You can perform automatic branch switching by calling continuation with the following options:

continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar; kwargs...)

where br is a branch computed after a call to continuation with detection of bifurcation points enabled. This call computes the branch bifurcating from the ind_bifth bifurcation point in br. An example of use is provided in 2d Bratu–Gelfand problem.

See Branch switching (branch point) precise method definition

Simple example: transcritical bifurcation

using BifurcationKit, Setfield, Plots
 
 # vector field of transcritical bifurcation
 F(x, p) = [x[1] * (p.μ - x[1])]
@@ -10,108 +10,961 @@
 # problem (automatic differentiation)
 prob = BifurcationProblem(F, [0.], par, (@lens _.μ); record_from_solution = (x, p) -> x[1])
 
-# compute branch of trivial equilibria (=0) and detect a bifurcation point
-opts_br = ContinuationPar(detect_bifurcation = 3)
+# compute branch of trivial equilibria and detect a bifurcation point
+opts_br = ContinuationPar()
 br = continuation(prob, PALC(), opts_br)
 
-# perform branch switching on one side of the bifurcation point
-br1Top = continuation(br, 1, setproperties(opts_br; max_steps = 14) )
+# perform branch switching on both sides of the bifurcation point
+br1 = continuation(br, 1, setproperties(opts_br; max_steps = 14), bothside = true )
 
-# on the other side
-br1Bottom = continuation(br, 1, setproperties(opts_br; ds = -opts_br.ds, max_steps = 14))
-
-scene = plot(br, br1Top, br1Bottom; branchlabel = ["br", "br1Top", "br1Bottom"], legend = :topleft)
+scene = plot(br, br1; branchlabel = ["br", "br1"], legend = :topleft)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Algorithms

  • for the pitchfork bifurcation, the normal form is computed and non-trivial zeros are used to produce guesses for points on the bifurcated branch.

From non simple branch point to equilibria

We provide an automatic branch switching method in this case. The underlying method is to first compute the reduced equation (see Non-simple branch point) and use it to compute the nearby solutions. These solutions are then seeded as initial guess for continuation. Hence, you can perform automatic branch switching by calling continuation with the following options:

continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar;
-	kwargs...)

An example of use is provided in 2d Bratu–Gelfand problem.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Simple example: pitchfork bifurcation

using BifurcationKit, Setfield, Plots
+
+# vector field of pitchfork bifurcation
+F(x, p) = [x[1] * (p.μ - x[1]^2)]
+
+# parameters of the vector field
+par = (μ = -0.2, )
+
+# problem (automatic differentiation)
+prob = BifurcationProblem(F, [0.], par, (@lens _.μ); record_from_solution = (x, p) -> x[1])
+
+# compute branch of trivial equilibria and
+# detect a bifurcation point with improved precision
+opts_br = ContinuationPar(n_inversion = 6)
+br = continuation(prob, PALC(), opts_br)
+
+# perform branch switching on both sides of the bifurcation point
+br1 = continuation(br, 1, setproperties(opts_br; max_steps = 14), bothside = true )
+
+scene = plot(br, br1; branchlabel = ["br", "br1"], legend = :topleft)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Algorithm

  • the normal form is computed and non-trivial zeros are used to produce guesses for points on the bifurcated branch.

From non simple branch point to equilibria

We provide an automatic branch switching method in this case. The underlying method is to first compute the reduced equation (see Non-simple branch point) and its zeros. These zeros are then seeded as initial guess for continuation. Hence, you can perform automatic branch switching by calling continuation with the following options:

continuation(br::ContResult, 
+	ind_bif::Int,
+	optionsCont::ContinuationPar;
+	kwargs...)

Examples

An example of use is provided in 2d Bratu–Gelfand problem. A much simpler example is given now. It is a bit artificial because the vector field is its own normal form at the bifurcation point located at 0.

using BifurcationKit, Plots
+
+function FbpD6(x, p)
+    return [p.μ * x[1] + (p.a * x[2] * x[3] - p.b * x[1]^3 - p.c*(x[2]^2 + x[3]^2) * x[1]),
+           p.μ * x[2] + (p.a * x[1] * x[3] - p.b * x[2]^3 - p.c*(x[3]^2 + x[1]^2) * x[2]),
+           p.μ * x[3] + (p.a * x[1] * x[2] - p.b * x[3]^3 - p.c*(x[2]^2 + x[1]^2) * x[3])]
+end
+
+# model parameters
+pard6 = (μ = -0.2, a = 0.3, b = 1.5, c = 2.9)
+
+# problem
+prob = BifurcationProblem(FbpD6, zeros(3), pard6, (@lens _.μ);
+	record_from_solution = (x, p) -> (n = norminf(x)))
+
+# newton options
+opt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)
+
+# continuation options
+opts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.02, ds = 0.01,
+	# parameter interval
+	p_max = 0.4, p_min = -0.2,
+	nev = 3,
+	newton_options = opt_newton,
+	max_steps = 1000,
+	n_inversion = 6)
+
+br = continuation(prob, PALC(), opts_br)
 ┌─ Curve type: EquilibriumCont
+ ├─ Number of points: 24
+ ├─ Type of vectors: Vector{Float64}
+ ├─ Parameter μ starts at -0.2, ends at 0.4
+ ├─ 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,       nd at μ ≈ +0.00008912 ∈ (-0.00002136, +0.00008912), |δp|=1e-04, [converged], δ = ( 3,  0), step =   8, eigenelements in eig[  9], ind_ev =   3
+- #  2, endpoint at μ ≈ +0.40000000,                                                                     step =  23
+

You can now branch from the nd point

br2 = continuation(br, 1, opts_br; δp = 0.02)
+
+plot(br, br2...)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Assisted branching from non-simple bifurcation point

It may happen that the general procedure fails. We thus expose the procedure multicontinuation in order to let the user tune it to its need.

The first step is to compute the reduced equation, say of the first bifurcation point in br.

bp = get_normal_form(br, 1)
Non simple bifurcation point at μ ≈ 8.912198888088785e-5. 
+Kernel dimension = 3
+Normal form:
+ + 1.0 * x1 ⋅ p + -1.5 ⋅ x1³ + -2.9001 ⋅ x1 ⋅ x2² + -2.9001 ⋅ x1 ⋅ x3² + 0.3 ⋅ x2 ⋅ x3
+ + 1.0 * x2 ⋅ p + -2.9001 ⋅ x1² ⋅ x2 + 0.3 ⋅ x1 ⋅ x3 + -1.5 ⋅ x2³ + -2.9001 ⋅ x2 ⋅ x3²
+ + 1.0 * x3 ⋅ p + -2.9001 ⋅ x1² ⋅ x3 + 0.3 ⋅ x1 ⋅ x2 + -2.9001 ⋅ x2² ⋅ x3 + -1.5 ⋅ x3³
+
+

Next, we want to find the zeros of the reduced equation. This is usually achieved by calling the predictor

δp = 0.005
+pred = predictor(bp, δp)
(before = [[0.0, 0.0, 0.0]], after = [[0.0, 0.0, 0.0], [0.05382180219586075, -0.05382180219586075, -0.05382180219586075], [-3.6734198463196485e-39, 0.057735026918947635, -2.938735877055719e-39], [0.057735026918947635, -2.033782021272921e-31, -1.910522504832138e-31], [-5.546678239835239e-32, -0.057735026918947635, 3.774822690998982e-32], [-2.2420775429197073e-43, -3.1389085600875902e-43, 0.057735026918947635]])

which returns zeros of bp before and after the bifurcation point. You could also use your preferred procedure from Roots.jl (or other) to find the zeros of the polynomials bp(Val(:reducedForm), z, p).

We can use these zeros to form guesses to apply Newton for the full functional:

pts = BifurcationKit.get_first_points_on_branch(br, bp, pred, opts_br; δp =  δp)
(before = ┌─ Deflation operator with 1 root(s)
+├─ eltype   = Float64
+├─ power    = 2
+├─ α        = 1.0
+├─ dist     = dot
+└─ autodiff = true
+, after = ┌─ Deflation operator with 4 root(s)
+├─ eltype   = Float64
+├─ power    = 2
+├─ α        = 1.0
+├─ dist     = dot
+└─ autodiff = true
+, bpm = -0.004910878011119112, bpp = 0.005089121988880888)

We can then use this to continue the different branches

brbp = BifurcationKit.multicontinuation(br, bp, pts.before, pts.after, opts_br)
+
+plot(br, brbp...)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Note that you can chose another predictor which uses all vertices of the cube as initial guesses

pred = predictor(bp, Val(:exhaustive), δp)
+pts = BifurcationKit.get_first_points_on_branch(br, bp, pred, opts_br; δp =  δp)
(before = ┌─ Deflation operator with 1 root(s)
+├─ eltype   = Float64
+├─ power    = 2
+├─ α        = 1.0
+├─ dist     = dot
+└─ autodiff = true
+, after = ┌─ Deflation operator with 10 root(s)
+├─ eltype   = Float64
+├─ power    = 2
+├─ α        = 1.0
+├─ dist     = dot
+└─ autodiff = true
+, bpm = -0.004910878011119112, bpp = 0.005089121988880888)
brbp = BifurcationKit.multicontinuation(br, bp, pts.before, pts.after, opts_br)
+
+plot(br, brbp...)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

predictors @docsBifurcationKit.predictor(bp::BifurcationKit.NdBranchPoint, δp::T; k...) where T@docsBifurcationKit.predictor(bp::BifurcationKit.NdBranchPoint, algo::Val{:exhaustive}, δp::T;k...) where T

diff --git a/dev/abs-from-hopf/index.html b/dev/abs-from-hopf/index.html index 5fe6a28a..c07d9e54 100644 --- a/dev/abs-from-hopf/index.html +++ b/dev/abs-from-hopf/index.html @@ -1,5 +1,125 @@ -From Hopf/PD/Branch to periodic orbits · Bifurcation Analysis in Julia

From Hopf / PD / Branch point to periodic orbits

From Hopf point to periodic orbits

In order to compute the bifurcated branch of periodic solutions at a Hopf bifurcation point, you need to choose a method to compute periodic orbits among:

Once you have decided which method to use, you can call the following:

continuation(br::ContResult, ind_HOPF::Int, _contParams::ContinuationPar,
+From Hopf/PD/Branch to periodic orbits · Bifurcation Analysis in Julia

From Hopf / PD / Branch point to periodic orbits

From Hopf point to periodic orbits

In order to compute the bifurcated branch of periodic solutions at a Hopf bifurcation point, you need to choose a method to compute periodic orbits among:

Once you have decided which method to use, you can call the following:

continuation(br::ContResult, ind_HOPF::Int, _contParams::ContinuationPar,
 	prob::AbstractPeriodicOrbitProblem ;
-	δp = nothing, ampfactor = 1, kwargs...)

We refer to continuation for more information about the arguments. Here, we just say a few words about how we can specify prob::AbstractPeriodicOrbitProblem.

The simplest example is from the getting-started section. Several examples are provided in example ODE. In case of PDE, you can have a look at Brusselator or 2d Ginzburg-Landau equation.

See Branch switching (Hopf point) for the precise method definition

Algorithm

From Branch / Period-doubling point to curve of periodic orbits

We do not provide (for now) the automatic branching procedure for these bifurcations of periodic orbits. As a consequence, the user is asked to provide the amplitude of the bifurcated solution.

We provide the branching method for the following methods to compute periodic orbits: PeriodicOrbitTrapProblem, PeriodicOrbitOCollProblem, ShootingProblem and PoincareShootingProblem. The call is as follows. Please note that a deflation is included in this method to simplify branch switching.

An example of use is provided in Lur'e problem.

continuation(br::AbstractBranchResult, ind_PD::Int, contParams::ContinuationPar;
-	δp = 0.1, ampfactor = 1, usedeflation = false, kwargs...)
+ δp = nothing, ampfactor = 1, kwargs...)

We refer to continuation for more information about the arguments. Here, we just say a few words about how we can specify prob::AbstractPeriodicOrbitProblem.

See Branch switching (Hopf point) for the precise method definition

Algorithm

The algorithm proceeds as follows. The normal form of the Hopf bifurcation is first computed. Then a predictor for the bifurcated branch of periodic orbits is generated from the normal form. Finally, this predictor is used as a guess for the computation of periodic orbits.

Example

The simplest example is from the getting-started section which we repeat partially below. Several examples are provided in example ODE. In the case of PDE, you can have a look at Brusselator or 2d Ginzburg-Landau equation.

We compute a branch with a Hopf bifurcation:

using BifurcationKit, Parameters, Plots
+
+function Fsl(X, p)
+    @unpack r, μ, ν, c3 = p
+    u, v = X
+    ua = u^2 + v^2
+    [
+        r * u - ν * v - ua * (c3 * u - μ * v)
+        r * v + ν * u - ua * (c3 * v + μ * u)
+    ]
+end
+
+par_sl = (r = 0.1, μ = 0., ν = 1.0, c3 = 1.0)
+u0 = zeros(2)
+prob = BifurcationProblem(Fsl, u0, par_sl, (@lens _.r))
+opts = ContinuationPar()
+br = continuation(prob, PALC(), opts, bothside = true)
 ┌─ Curve type: EquilibriumCont
+ ├─ Number of points: 25
+ ├─ Type of vectors: Vector{Float64}
+ ├─ Parameter r starts at -1.0, ends at 1.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, endpoint at r ≈ -1.00000000,                                                                     step =   0
+- #  2,     hopf at r ≈ -0.00595553 ∈ (-0.00595553, +0.00299379), |δp|=9e-03, [converged], δ = ( 2,  2), step =   8, eigenelements in eig[  9], ind_ev =   2
+- #  3, endpoint at r ≈ +1.00000000,                                                                     step =  24
+

We then compute the branch of periodic solutions using orthogonal collocation (for example):

br_po = continuation(br, 2, opts,
+        PeriodicOrbitOCollProblem(20, 5)
+        )
+plot(br, br_po)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

From Period-doubling point to curve of periodic orbits

Case of Shooting and Collocation

We provide an automatic branching procedure in this case. In essence, all you have to do is to call

continuation(br::ContResult, ind_PD::Int, _contParams::ContinuationPar;
+    prm = true,
+    kwargs...)

The option prm=true enforces that the period-doubling normal form is computed using the Poincaré return map ; this is only necessary in case of use of the collocation method. Indeed, in the case of the collocation method, an automatic procedure based on the Iooss normal form has yet to be implemented.

Case of Trapezoid method

We do not provide (for now) the automatic branching procedure for these bifurcations of periodic orbits. As a consequence, the user is asked to provide the amplitude of the bifurcated solution.

The call is as follows. Please note that a deflation is included in this method to simplify branch switching.

continuation(br::AbstractBranchResult, ind_PD::Int, contParams::ContinuationPar;
+	δp = 0.1, ampfactor = 1, usedeflation = false, kwargs...)

An example of use is provided in Lur'e problem.

Algorithm

The algorithm proceeds as follows. The normal form of the Period-doubling bifurcation is first computed. Then a predictor for the bifurcated branch of periodic orbits is generated from the normal form. Finally, this predictor is used as a guess for the computation of periodic orbits.

From Branch point to curve of periodic orbits

We do not provide (for now) the automatic branching procedure for these bifurcations of periodic orbits. As a consequence, the user is asked to provide the amplitude of the bifurcated solution.

We provide the branching method for the following methods to compute periodic orbits: PeriodicOrbitTrapProblem, PeriodicOrbitOCollProblem, ShootingProblem and PoincareShootingProblem. The call is as follows. Please note that a deflation is included in this method to simplify branch switching.

An example of use is provided in Lur'e problem.

continuation(br::AbstractBranchResult, ind_PD::Int, contParams::ContinuationPar;
+	δp = 0.1, ampfactor = 1, usedeflation = false, kwargs...)
diff --git a/dev/bautin/index.html b/dev/bautin/index.html index 523ea674..0fdfdf6e 100644 --- a/dev/bautin/index.html +++ b/dev/bautin/index.html @@ -1,2 +1,2 @@ -Bautin · Bifurcation Analysis in Julia

Normal form of the Bautin bifurcation

We follow the paper[Kuznetsov] and consider a Cauchy problem

\[\dot x=\mathbf F(x,p).\]

We denote by $\mathbf L$ the jacobian of $\mathbf F$ at the bifurcation point $(x_0,p_0)$. We choose a basis such that:

\[\mathbf L q=i \omega_{0} q, \quad \mathbf L^{T} p=-i \omega_{0} p, \quad \langle p, q\rangle=1.\]

Under some conditions, $x(t)\approx x_0+2\Re w(t)q$ where $w$ satisfies the normal form:

\[\dot{w}=i \omega_{0} w+\frac{1}{2} G_{21} w|w|^{2}+\frac{1}{12} G_{32} w|w|^{4}+O\left(|w|^{6}\right).\tag{E}\]

The second Lyapunov coefficient is

\[l_2:=\frac{1}{12} \operatorname{Re} G_{32}.\]

Normal form computation

The normal form (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Bautin.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Kuznetsov

    Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

+Bautin · Bifurcation Analysis in Julia

Normal form of the Bautin bifurcation

We follow the paper[Kuznetsov] and consider a Cauchy problem

\[\dot x=\mathbf F(x,p).\]

We denote by $\mathbf L$ the jacobian of $\mathbf F$ at the bifurcation point $(x_0,p_0)$. We choose a basis such that:

\[\mathbf L q=i \omega_{0} q, \quad \mathbf L^{T} p=-i \omega_{0} p, \quad \langle p, q\rangle=1.\]

Under some conditions, $x(t)\approx x_0+2\Re w(t)q$ where $w$ satisfies the normal form:

\[\dot{w}=i \omega_{0} w+\frac{1}{2} G_{21} w|w|^{2}+\frac{1}{12} G_{32} w|w|^{4}+O\left(|w|^{6}\right).\tag{E}\]

The second Lyapunov coefficient is

\[l_2:=\frac{1}{12} \operatorname{Re} G_{32}.\]

Normal form computation

The normal form (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Bautin.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Kuznetsov

    Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

diff --git a/dev/borderedlinearsolver/index.html b/dev/borderedlinearsolver/index.html index cb9588be..3991101b 100644 --- a/dev/borderedlinearsolver/index.html +++ b/dev/borderedlinearsolver/index.html @@ -9,4 +9,4 @@ {u_2} \end{array}\right)$ to $(E)$ when $A$ is non singular is

\[\begin{array}{l} u_2 = \frac{1}{d - c\cdot x_2}(v_2 - c\cdot x_1) \\ u_1=x_1-u_2x_2 -\end{array}\]

where $x_1=A^{-1}v_1, x_2=A^{-1}b$.

It is very efficient for large scale problems because it is entirely Matrix-Free and one can use preconditioners. You can create such bordered linear solver using bls = BorderingBLS(ls) where ls::AbstractLinearSolver is a linear solver which defaults to \. The intermediate solutions $x_1=A^{-1}v_1, x_2=A^{-1}b$ are formed using ls.

  1. In the case where ls = DefaultLS(), the factorisation of A is cached so the second linear solve is very fast

There are more options to BorderingBLS. First, the residual can be checked using the option check_precision = true. If the residual is above a prescribed tolerance, an iterative method is used based on several bordering transformations. This is the BEC+k algorithm in [Govaerts].

Full Matrix-Free MatrixFreeBLS

In cases where $A$ is singular but $J$ is not, the bordering method may fail. It can thus be advantageous to form the Matrix-Free version of $J$ and call a generic linear solver to find the solution to $(E)$. You can create such bordered linear solver using bls = MatrixFreeBLS(ls) where ls::AbstractLinearSolver is a (Matrix Free) linear solver which is used to invert J.

For now, this linear solver only works with AbstractArray

References

  • Govaerts

    Govaerts, W. “Stable Solvers and Block Elimination for Bordered Systems.” SIAM Journal on Matrix Analysis and Applications 12, no. 3 (July 1, 1991): 469–83. https://doi.org/10.1137/0612034.

+\end{array}\]

where $x_1=A^{-1}v_1, x_2=A^{-1}b$.

It is very efficient for large scale problems because it is entirely Matrix-Free and one can use preconditioners. You can create such bordered linear solver using bls = BorderingBLS(ls) where ls::AbstractLinearSolver is a linear solver which defaults to \. The intermediate solutions $x_1=A^{-1}v_1, x_2=A^{-1}b$ are formed using ls.

  1. In the case where ls = DefaultLS(), the factorisation of A is cached so the second linear solve is very fast

There are more options to BorderingBLS. First, the residual can be checked using the option check_precision = true. If the residual is above a prescribed tolerance, an iterative method is used based on several bordering transformations. This is the BEC+k algorithm in [Govaerts].

Full Matrix-Free MatrixFreeBLS

In cases where $A$ is singular but $J$ is not, the bordering method may fail. It can thus be advantageous to form the Matrix-Free version of $J$ and call a generic linear solver to find the solution to $(E)$. You can create such bordered linear solver using bls = MatrixFreeBLS(ls) where ls::AbstractLinearSolver is a (Matrix Free) linear solver which is used to invert J.

For now, this linear solver only works with AbstractArray

References

  • Govaerts

    Govaerts, W. “Stable Solvers and Block Elimination for Bordered Systems.” SIAM Journal on Matrix Analysis and Applications 12, no. 3 (July 1, 1991): 469–83. https://doi.org/10.1137/0612034.

diff --git a/dev/bt/index.html b/dev/bt/index.html index 0ef64adc..57af2b40 100644 --- a/dev/bt/index.html +++ b/dev/bt/index.html @@ -13,4 +13,4 @@ &a=\left\langle\mathbf{F}_{20}\left(\zeta_{0}, \zeta_{0}\right), \zeta_{1}^{*}\right\rangle \\ &b=2\left\langle \mathbf{F}_{20}\left(\zeta_{0}, \zeta_{1}\right), \zeta_{1}^{*}\right\rangle + 2\left\langle\mathbf{F}_{20}\left(\zeta_{0}, \zeta_{0}\right), \zeta_{0}^{*}\right\rangle. \end{aligned}\]

Computation of the basis

To build the basis $\left\{\zeta_{0}, \zeta_{1}\right\}$, we follow the procedure described in [AlHdaibat] on page 972.

Computation of the parameter transform

To invert the mapping $\mu\to (\alpha_{1}(\mu),\alpha_{2}(\mu),\alpha_{3}(\mu))$, we follow the procedure described in [AlHdaibat] on page 956 forward.

Normal form computation

The normal form (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ;
-	nev = 5, verbose = false, ζs = nothing, autodiff = true, detailed = true)

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The option detailed controls the computation of a simplified version of the normal form. autodiff controls the use of ForwardDiff during the normal form computation.

The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BogdanovTakens.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Haragus

    Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

  • AlHdaibat

    Al-Hdaibat, B., W. Govaerts, Yu. A. Kuznetsov, and H. G. E. Meijer. “Initialization of Homoclinic Solutions near Bogdanov–Takens Points: Lindstedt–Poincaré Compared with Regular Perturbation Method.” SIAM Journal on Applied Dynamical Systems 15, no. 2 (January 2016): 952–80. https://doi.org/10.1137/15M1017491.

+ nev = 5, verbose = false, ζs = nothing, autodiff = true, detailed = true)

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The option detailed controls the computation of a simplified version of the normal form. autodiff controls the use of ForwardDiff during the normal form computation.

The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BogdanovTakens.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Haragus

    Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

  • AlHdaibat

    Al-Hdaibat, B., W. Govaerts, Yu. A. Kuznetsov, and H. G. E. Meijer. “Initialization of Homoclinic Solutions near Bogdanov–Takens Points: Lindstedt–Poincaré Compared with Regular Perturbation Method.” SIAM Journal on Applied Dynamical Systems 15, no. 2 (January 2016): 952–80. https://doi.org/10.1137/15M1017491.

diff --git a/dev/capabilities/index.html b/dev/capabilities/index.html index 486cdc6f..d34b6263 100644 --- a/dev/capabilities/index.html +++ b/dev/capabilities/index.html @@ -1,2 +1,2 @@ -Overview of capabilities · Bifurcation Analysis in Julia

Overview of capabilities

Main features

  • Newton-Krylov solver with generic linear / eigen preconditioned solver. Idem for the arc-length continuation.
  • Newton-Krylov solver with nonlinear deflation and preconditioner. It can be used for branch switching for example. It is used for deflated continuation.
  • Continuation written as an iterator
  • Monitoring user functions along curves computed by continuation, see events
  • Continuation methods: PALC, Moore Penrose, Multiple, Polynomial, Deflated continuation, ANM, ...
  • Bifurcation points located with bisection
  • Detection of Branch, Fold, Hopf bifurcation points of stationary solutions and computation of their normal form.
  • Automatic branch switching at branch points (whatever the dimension of the kernel) to equilibria
  • Automatic computation of bifurcation diagrams of equilibria
  • Fold / Hopf continuation based on Minimally Augmented formulation, with Matrix Free / Sparse / Dense Jacobian.
  • Detection of all codim 2 bifurcations of equilibria and computation of the normal forms of Bogdanov-Takens, Bautin and Cusp
  • Branching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf points to Fold / Hopf curve

Note that you can combine most solvers, like use Deflation for Periodic orbit computation or Fold of periodic orbits family.

Custom state means, we can use something else than AbstractArray, for example your own struct.

FeaturesMatrix FreeCustom stateTutorialGPU
(Deflated) Krylov-NewtonYesYeslinkYes
Continuation PALC (Natural, Secant, Tangent, Polynomial)YesYesAllYes
Deflated ContinuationYesYeslinkYes
Bifurcation / Fold / Hopf point detectionYesYesAll / All / linkYes
Fold Point continuationYesYesPDE, PDE, ODEYes
Hopf Point continuationYesAbstractArrayODE
Branch point / Fold / Hopf normal formYesYesYes
Branch switching at Branch pointsYesAbstractArraylinkYes
Automatic bifurcation diagram computation of equilibriaYesAbstractArraylink
Bogdanov-Takens / Bautin / Cusp / Zero-Hopf / Hopf-Hopf point detectionYesYesODE
Bogdanov-Takens / Bautin / Cusp normal formsYesAbstractArrayODEYes
Branching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf to Fold / Hopf curveYesAbstractArrayODE
  • Periodic orbit computation and continuation using parallel (Standard or Poincaré) Shooting, Finite Differences or Orthogonal Collocation.
  • Automatic branch switching at simple Hopf points to periodic orbits
  • Detection of Branch, Fold, Neimark-Sacker, Period Doubling bifurcation points of periodic orbits.
  • Continuation of Fold of periodic orbits

Legend for the table: Standard shooting (SS), Poincaré shooting (PS), Orthogonal collocation (OC), trapezoid (T).

FeaturesMethodMatrix FreeCustom stateTutorialGPU
Branch switching at Hopf pointsSS/PS/OC/TSee eachODE
Newton / continuationTYesAbstractVectorPDE, PDEYes
Newton / continuationOCAbstractVectorODE
Newton / continuationSSYesAbstractArrayODEYes
Newton / continuationPSYesAbstractArrayPDEYes
Fold, Neimark-Sacker, Period doubling detectionSS/PS/OC/TSee eachAbstractVectorlink
Branch switching at Branch pointSS/PS/OC/TSee eachODE
Branch switching at PD pointSS/PS/OC/TSee eachODE
Continuation of Fold pointsSS/PS/OC/TSee eachAbstractVectorODE PDEYes
Continuation of Period-doubling pointsSS/OCAbstractVectorODE
Continuation of Neimark-Sacker pointsSS/OCAbstractVectorODE
detection of codim 2 bifurcations of periodic orbitsSS/OCAbstractVectorODE
Branch switching at Bautin point to curve of Fold of periodic orbitsSS/OCAbstractVectorODE
Branch switching at ZH/HH point to curve of NS of periodic orbitsSS/OCAbstractVectorODE

This is available through the plugin HclinicBifurcationKit.jl. Please see the specific docs for more information.

  • compute Homoclinic to Hyperbolic Saddle Orbits (HomHS) using Orthogonal collocation or Standard shooting
  • compute bifurcation of HomHS
  • start HomHS from a direct simulation
  • automatic branch switching to HomHS from Bogdanov-Takes bifurcation point
+Overview of capabilities · Bifurcation Analysis in Julia

Overview of capabilities

Main features

  • Newton-Krylov solver with generic linear / eigen preconditioned solver. Idem for the arc-length continuation.
  • Newton-Krylov solver with nonlinear deflation and preconditioner. It can be used for branch switching for example. It is used for deflated continuation.
  • Continuation written as an iterator
  • Monitoring user functions along curves computed by continuation, see events
  • Continuation methods: PALC, Moore Penrose, Multiple, Polynomial, Deflated continuation, ANM, ...
  • Bifurcation points located with bisection
  • Detection of Branch, Fold, Hopf bifurcation points of stationary solutions and computation of their normal form.
  • Automatic branch switching at branch points (whatever the dimension of the kernel) to equilibria
  • Automatic computation of bifurcation diagrams of equilibria
  • Fold / Hopf continuation based on Minimally Augmented formulation, with Matrix Free / Sparse / Dense Jacobian.
  • Detection of all codim 2 bifurcations of equilibria and computation of the normal forms of Bogdanov-Takens, Bautin and Cusp
  • Branching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf points to Fold / Hopf curve

Note that you can combine most solvers, like use Deflation for Periodic orbit computation or Fold of periodic orbits family.

Custom state means, we can use something else than AbstractArray, for example your own struct.

FeaturesMatrix FreeCustom stateTutorialGPU
(Deflated) Krylov-NewtonYesYeslinkYes
Continuation PALC (Natural, Secant, Tangent, Polynomial)YesYesAllYes
Deflated ContinuationYesYeslinkYes
Bifurcation / Fold / Hopf point detectionYesYesAll / All / linkYes
Fold Point continuationYesYesPDE, PDE, ODEYes
Hopf Point continuationYesAbstractArrayODE
Branch point / Fold / Hopf normal formYesYesYes
Branch switching at Branch pointsYesAbstractArraylinkYes
Automatic bifurcation diagram computation of equilibriaYesAbstractArraylink
Bogdanov-Takens / Bautin / Cusp / Zero-Hopf / Hopf-Hopf point detectionYesYesODE
Bogdanov-Takens / Bautin / Cusp normal formsYesAbstractArrayODEYes
Branching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf to Fold / Hopf curveYesAbstractArrayODE
  • Periodic orbit computation and continuation using parallel (Standard or Poincaré) Shooting, Finite Differences or Orthogonal Collocation.
  • Automatic branch switching at simple Hopf points to periodic orbits
  • Detection of Branch, Fold, Neimark-Sacker, Period Doubling bifurcation points of periodic orbits.
  • Continuation of Fold of periodic orbits

Legend for the table: Standard shooting (SS), Poincaré shooting (PS), Orthogonal collocation (OC), trapezoid (T).

FeaturesMethodMatrix FreeCustom stateTutorialGPU
Branch switching at Hopf pointsSS/PS/OC/TSee eachODE
Newton / continuationTYesAbstractVectorPDE, PDEYes
Newton / continuationOCAbstractVectorODE
Newton / continuationSSYesAbstractArrayODEYes
Newton / continuationPSYesAbstractArrayPDEYes
Fold, Neimark-Sacker, Period doubling detectionSS/PS/OC/TSee eachAbstractVectorlink
Branch switching at Branch pointSS/PS/OC/TSee eachODE
Branch switching at PD pointSS/PS/OC/TSee eachODE
Continuation of Fold pointsSS/PS/OC/TSee eachAbstractVectorODE PDEYes
Continuation of Period-doubling pointsSS/OCAbstractVectorODE
Continuation of Neimark-Sacker pointsSS/OCAbstractVectorODE
detection of codim 2 bifurcations of periodic orbitsSS/OCAbstractVectorODE
Branch switching at Bautin point to curve of Fold of periodic orbitsSS/OCAbstractVectorODE
Branch switching at ZH/HH point to curve of NS of periodic orbitsSS/OCAbstractVectorODE

This is available through the plugin HclinicBifurcationKit.jl. Please see the specific docs for more information.

  • compute Homoclinic to Hyperbolic Saddle Orbits (HomHS) using Orthogonal collocation or Standard shooting
  • compute bifurcation of HomHS
  • start HomHS from a direct simulation
  • automatic branch switching to HomHS from Bogdanov-Takes bifurcation point
diff --git a/dev/codim2Continuation/index.html b/dev/codim2Continuation/index.html index faeb73cb..dac8c82b 100644 --- a/dev/codim2Continuation/index.html +++ b/dev/codim2Continuation/index.html @@ -50,7 +50,7 @@ record_from_solution, kwargs... ) -

Codim 2 continuation of Fold points. This function turns an initial guess for a Fold point into a curve of Fold points based on a Minimally Augmented formulation. The arguments are as follows

  • prob::AbstractBifurcationFunction
  • foldpointguess initial guess (x0, p10) for the Fold point. It should be a BorderedArray as returned by the function FoldPoint
  • par set of parameters
  • lens1 parameter axis for parameter 1
  • lens2 parameter axis for parameter 2
  • eigenvec guess for the 0 eigenvector at p1_0
  • eigenvec_ad guess for the 0 adjoint eigenvector
  • options_cont arguments to be passed to the regular continuation

Optional arguments:

  • jacobian_ma::Symbol = :autodiff, how the linear system of the Fold problem is solved. Can be :autodiff, :finiteDifferencesMF, :finiteDifferences, :minaug
  • bdlinsolver bordered linear solver for the constraint equation with top-left block J. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.
  • bdlinsolver_adjoint bordered linear solver for the constraint equation with top-left block J^*. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.
  • update_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps
  • compute_eigen_elements = false whether to compute eigenelements. If options_cont.detect_event>0, it allows the detection of ZH points.
  • kwargs keywords arguments to be passed to the regular continuation

Simplified call

continuation_fold(br::AbstractBranchResult, ind_fold::Int64, lens2::Lens, options_cont::ContinuationPar ; kwargs...)

where the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Fold point in br that you want to continue.

Jacobian transpose

The adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian would be computed twice!

ODE problems

For ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS(). This is the default setting.

Detection of Bogdanov-Takens and Cusp bifurcations

In order to trigger the detection, pass detect_event = 1,2 in options_cont.

BifurcationKit.continuation_hopfFunction
continuation_hopf(
+

Codim 2 continuation of Fold points. This function turns an initial guess for a Fold point into a curve of Fold points based on a Minimally Augmented formulation. The arguments are as follows

  • prob::AbstractBifurcationFunction
  • foldpointguess initial guess (x0, p10) for the Fold point. It should be a BorderedArray as returned by the function foldpoint
  • par set of parameters
  • lens1 parameter axis for parameter 1
  • lens2 parameter axis for parameter 2
  • eigenvec guess for the right null vector
  • eigenvec_ad guess for the left null vector
  • options_cont arguments to be passed to the regular continuation

Optional arguments:

  • jacobian_ma::Symbol = :autodiff, how the linear system of the Fold problem is solved. Can be :autodiff, :finiteDifferencesMF, :finiteDifferences, :minaug
  • bdlinsolver bordered linear solver for the constraint equation with top-left block J. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.
  • bdlinsolver_adjoint bordered linear solver for the constraint equation with top-left block J^*. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.
  • update_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps
  • compute_eigen_elements = false whether to compute eigenelements. If options_cont.detect_event>0, it allows the detection of ZH points.
  • kwargs keywords arguments to be passed to the regular continuation

Simplified call

continuation_fold(br::AbstractBranchResult, ind_fold::Int64, lens2::Lens, options_cont::ContinuationPar ; kwargs...)

where the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Fold point in br that you want to continue.

Jacobian transpose

The adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian would be computed twice!

ODE problems

For ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS(). This is the default setting.

Detection of Bogdanov-Takens and Cusp bifurcations

In order to trigger the detection, pass detect_event = 1 or 2 in options_cont.

BifurcationKit.continuation_hopfFunction
continuation_hopf(
     prob_vf,
     alg,
     hopfpointguess,
@@ -80,4 +80,4 @@
 \partial_{u}F & \partial_pF & 0 \\
 \partial_x\sigma_r & \partial_p\sigma_r & \partial_\omega\sigma_r\\
 \partial_x\sigma_i & \partial_p\sigma_i & \partial_\omega\sigma_i
-\end{array}\right]\]

using a similar formula for $\partial\sigma$ as in the Fold case.

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

  • Blank

    Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.

  • Bindel

    Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.

+\end{array}\right]\]

using a similar formula for $\partial\sigma$ as in the Fold case.

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

  • Blank

    Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.

  • Bindel

    Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.

diff --git a/dev/codim3Continuation/index.html b/dev/codim3Continuation/index.html index e108ca90..dab552b4 100644 --- a/dev/codim3Continuation/index.html +++ b/dev/codim3Continuation/index.html @@ -55,6 +55,8 @@ jacobian_ma, usehessian, bdlinsolver, + bdlinsolver_adjoint, + bdlinsolver_block, kwargs... )

This function turns an initial guess for a BT point into a solution to the BT problem based on a Minimally Augmented formulation. The arguments are as follows

  • prob::AbstractBifurcationFunction
  • btpointguess initial guess (x0, p0) for the BT point. It should be a BorderedArray as returned by the function BTPoint
  • par parameters used for the vector field
  • eigenvec guess for the 0 eigenvector
  • eigenvec_ad guess for the 0 adjoint eigenvector
  • options::NewtonPar options for the Newton-Krylov algorithm, see NewtonPar.

Optional arguments:

  • normN = norm
  • bdlinsolver bordered linear solver for the constraint equation
  • jacobian_ma::Symbol = true specify the way the (newton) linear system is solved. Can be (:autodiff, :finitedifferences, :minaug)
  • kwargs keywords arguments to be passed to the regular Newton-Krylov solver

Simplified call

Simplified call to refine an initial guess for a BT point. More precisely, the call is as follows

newton(br::AbstractBranchResult, ind_bt::Int; options = br.contparams.newton_options, kwargs...)

The parameters / options are as usual except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of bifurcation point in br you want to refine. You can pass newton parameters different from the ones stored in br by using the argument options.

Jacobian transpose

The adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian will be computed twice!

ODE problems

For ODE problems, it is more efficient to pass the option jacobian_ma = :autodiff

newton_bt(
@@ -66,6 +68,7 @@
     nev,
     start_with_eigen,
     bdlinsolver,
+    bdlinsolver_adjoint,
     kwargs...
 )
-

This function turns an initial guess for a Bogdanov-Takens point into a solution to the Bogdanov-Takens problem based on a Minimally Augmented formulation.

Arguments

  • br results returned after a call to continuation
  • ind_bif bifurcation index in br

Optional arguments:

  • options::NewtonPar, default value br.contparams.newton_options
  • normN = norm
  • options You can pass newton parameters different from the ones stored in br by using this argument options.
  • jacobian_ma::Symbol = true specify the way the (newton) linear system is solved. Can be (:autodiff, :finitedifferences, :minaug)
  • bdlinsolver bordered linear solver for the constraint equation
  • start_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements.
  • kwargs keywords arguments to be passed to the regular Newton-Krylov solver
ODE problems

For ODE problems, it is more efficient to pass the option jacobian = :autodiff

start_with_eigen

For ODE problems, it is more efficient to pass the option start_with_eigen = true

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

  • Blank

    Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.

  • Bindel

    Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.

+

This function turns an initial guess for a Bogdanov-Takens point into a solution to the Bogdanov-Takens problem based on a Minimally Augmented formulation.

Arguments

  • br results returned after a call to continuation
  • ind_bif bifurcation index in br

Optional arguments:

  • options::NewtonPar, default value br.contparams.newton_options
  • normN = norm
  • options You can pass newton parameters different from the ones stored in br by using this argument options.
  • jacobian_ma::Symbol = true specify the way the (newton) linear system is solved. Can be (:autodiff, :finitedifferences, :minaug)
  • bdlinsolver bordered linear solver for the constraint equation
  • start_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements.
  • kwargs keywords arguments to be passed to the regular Newton-Krylov solver
ODE problems

For ODE problems, it is more efficient to pass the option jacobian = :autodiff

start_with_eigen

For ODE problems, it is more efficient to pass the option start_with_eigen = true

References

  • Govaerts

    Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

  • Blank

    Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.

  • Bindel

    Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.

diff --git a/dev/constrainedproblem/index.html b/dev/constrainedproblem/index.html index 49dd020e..8537d819 100644 --- a/dev/constrainedproblem/index.html +++ b/dev/constrainedproblem/index.html @@ -7,4 +7,4 @@ \begin{array}{l} F(x) + p\cdot T\cdot x=0 \\ \langle T\cdot x_{ref},x-x_{ref}\rangle=0 -\end{array}\right.\]

where $T$ is a generator of the Lie algebra associated to $G$ and $x_{ref}$ is a reference solution. This is known as the freezing method.

Reference

See Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation. for more information on the freezing method.

+\end{array}\right.\]

where $T$ is a generator of the Lie algebra associated to $G$ and $x_{ref}$ is a reference solution. This is known as the freezing method.

Reference

See Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation. for more information on the freezing method.

diff --git a/dev/cusp/index.html b/dev/cusp/index.html index ca95402d..a43e2e14 100644 --- a/dev/cusp/index.html +++ b/dev/cusp/index.html @@ -1,2 +1,2 @@ -Cusp · Bifurcation Analysis in Julia

Normal form of the Cusp bifurcation

We follow the paper[Kuznetsov] and consider a Cauchy problem

\[\dot x=\mathbf F(x,p).\]

We denote by $\mathbf L$ the jacobian of $\mathbf F$ at the bifurcation point $(x_0,p_0)$. We choose a basis such that:

\[\mathbf L q=0, \quad \mathbf L^{T} p=0, \quad \langle p, q\rangle=1.\]

Under some conditions, $x(t)\approx x_0+ w(t)q$ where $w$ satisfies the normal form:

\[\dot{w}=c w^{3}+O\left(w^{4}\right).\tag{E}\]

Normal form computation

The normal form (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Cusp.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Kuznetsov

    Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

+Cusp · Bifurcation Analysis in Julia

Normal form of the Cusp bifurcation

We follow the paper[Kuznetsov] and consider a Cauchy problem

\[\dot x=\mathbf F(x,p).\]

We denote by $\mathbf L$ the jacobian of $\mathbf F$ at the bifurcation point $(x_0,p_0)$. We choose a basis such that:

\[\mathbf L q=0, \quad \mathbf L^{T} p=0, \quad \langle p, q\rangle=1.\]

Under some conditions, $x(t)\approx x_0+ w(t)q$ where $w$ satisfies the normal form:

\[\dot{w}=c w^{3}+O\left(w^{4}\right).\tag{E}\]

Normal form computation

The normal form (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Cusp.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Kuznetsov

    Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

diff --git a/dev/deflatedproblem/index.html b/dev/deflatedproblem/index.html index da5f74d7..6a16a5af 100644 --- a/dev/deflatedproblem/index.html +++ b/dev/deflatedproblem/index.html @@ -12,4 +12,4 @@ prob = BifurcationProblem(F, rand(1), nothing) # call deflated newton sol = newton(prob, deflationOp, NewtonPar()) -println("We found the additional root: ", sol.u)
We found the additional root: [1.9999999999999951]
Tip

You can use this method for periodic orbits as well by passing the deflation operator M to the newton method

+println("We found the additional root: ", sol.u)
We found the additional root: [2.0]
Tip

You can use this method for periodic orbits as well by passing the deflation operator M to the newton method

diff --git a/dev/detectionBifurcation/index.html b/dev/detectionBifurcation/index.html index c1425366..8d7e4bff 100644 --- a/dev/detectionBifurcation/index.html +++ b/dev/detectionBifurcation/index.html @@ -1,2 +1,2 @@ -Bifurcation detection (1 param) · Bifurcation Analysis in Julia

Detection of bifurcation points of Equilibria

The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:

  • contParams.detect_bifurcation = 2

The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The eigenvalue λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint.

Precise detection of bifurcation points using Bisection

Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.

If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:

  • n_inversion: number of sign inversions in the bisection algorithm
  • max_bisection_steps maximum number of bisection steps
  • tol_bisection_eigenvalue tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps

If this is still not enough, you can use a Newton solver to locate them very precisely. See Fold / Hopf Continuation.

Bisection mode

During the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.

Large scale computations

The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).

List of detected bifurcation points

Bifurcationindex used
Foldfold
Hopfhopf
Bifurcation point (single eigenvalue stability change, Fold or branch point)bp
Not documentednd

Eigensolver

The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.

The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.

Generic bifurcation

By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation.

Fold bifurcation

The detection of Fold point is done by monitoring the monotonicity of the parameter.

The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.

Hopf bifurcation

The detection of Hopf point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Hopf point is detected, a point is added to br.specialpoint allowing for later refinement using the function newton_hopf.

  • 1In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation.
+Bifurcation detection (1 param) · Bifurcation Analysis in Julia

Detection of bifurcation points of Equilibria

The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:

  • contParams.detect_bifurcation = 2

The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The eigenvalue λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint.

Precise detection of bifurcation points using Bisection

Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.

If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:

  • n_inversion: number of sign inversions in the bisection algorithm
  • max_bisection_steps maximum number of bisection steps
  • tol_bisection_eigenvalue tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps

If this is still not enough, you can use a Newton solver to locate them very precisely. See Fold / Hopf Continuation.

Bisection mode

During the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.

Large scale computations

The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).

List of detected bifurcation points

Bifurcationindex used
Foldfold
Hopfhopf
Bifurcation point (single eigenvalue stability change, Fold or branch point)bp
Not documentednd

Eigensolver

The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.

The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.

Generic bifurcation

By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation.

Fold bifurcation

The detection of Fold point is done by monitoring the monotonicity of the parameter.

The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.

Hopf bifurcation

The detection of Hopf point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Hopf point is detected, a point is added to br.specialpoint allowing for later refinement using the function newton_hopf.

  • 1In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation.
diff --git a/dev/detectionBifurcationPO/index.html b/dev/detectionBifurcationPO/index.html index 2315db57..34166487 100644 --- a/dev/detectionBifurcationPO/index.html +++ b/dev/detectionBifurcationPO/index.html @@ -1,2 +1,2 @@ -Bifurcation detection (1 param) · Bifurcation Analysis in Julia

Detection of bifurcation points of periodic orbits

The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:

  • contParams.detect_bifurcation = 2

The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The Floquet exponent λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint.

Precise detection of bifurcation points using Bisection

Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.

If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:

  • n_inversion: number of sign inversions in the bisection algorithm
  • max_bisection_steps maximum number of bisection steps
  • tol_bisection_eigenvalue tolerance on real part of Floquet exponent to detect bifurcation points in the bisection steps
Bisection mode

During the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.

Large scale computations

The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).

List of detected bifurcation points

Bifurcationindex used
Bifurcation point (single eigenvalue stability change, Fold or branch point)bp
Neimark-Sackerns
Period doublingpd
Not documentednd

Eigensolver

The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.

The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.

Floquet multipliers computation

The computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of the eigensolver. Nevertheless, note that for most implemented eigensolvers in BifurcationKit, the proper option is automatically set.

Generic bifurcation

By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation.

Fold bifurcation

The detection of Fold point is done by monitoring the monotonicity of the parameter.

The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.

Neimark-Sacker bifurcation

The detection of Neimark-Sacker point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Neimark-Sacker point is detected, a point is added to br.specialpoint.

Period-doubling bifurcation

The detection of Period-doubling point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Period-doubling point is detected, a point is added to br.specialpoint.

  • 1In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation.
+Bifurcation detection (1 param) · Bifurcation Analysis in Julia

Detection of bifurcation points of periodic orbits

The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:

  • contParams.detect_bifurcation = 2

The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The Floquet exponent λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint.

Precise detection of bifurcation points using Bisection

Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.

If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:

  • n_inversion: number of sign inversions in the bisection algorithm
  • max_bisection_steps maximum number of bisection steps
  • tol_bisection_eigenvalue tolerance on real part of Floquet exponent to detect bifurcation points in the bisection steps
Bisection mode

During the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.

Large scale computations

The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).

List of detected bifurcation points

Bifurcationindex used
Bifurcation point (single eigenvalue stability change, Fold or branch point)bp
Neimark-Sackerns
Period doublingpd
Not documentednd

Eigensolver

The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.

The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.

Floquet multipliers computation

The computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of the eigensolver. Nevertheless, note that for most implemented eigensolvers in BifurcationKit, the proper option is automatically set.

Generic bifurcation

By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation.

Fold bifurcation

The detection of Fold point is done by monitoring the monotonicity of the parameter.

The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.

Neimark-Sacker bifurcation

The detection of Neimark-Sacker point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Neimark-Sacker point is detected, a point is added to br.specialpoint.

Period-doubling bifurcation

The detection of Period-doubling point is done by analysis of the spectrum of the Jacobian.

The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Period-doubling point is detected, a point is added to br.specialpoint.

  • 1In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation.
diff --git a/dev/diffeq/index.html b/dev/diffeq/index.html index b48e9368..62f36cd2 100644 --- a/dev/diffeq/index.html +++ b/dev/diffeq/index.html @@ -1,2 +1,2 @@ -DiffEq wrapper · Bifurcation Analysis in Julia

Wrapper to the package DifferentialEquations.jl

Warning

This is work in progress.

The current package will provide basic methods to wrap some of the functionality of DifferentialEquations.jl.

Basically, the ultimate idea is that you provide a prob::ODEProblem to our newton, continuation... and they will use the expression of the jacobians, the linear solvers... that you already provided for the construction of prob.

+DiffEq wrapper · Bifurcation Analysis in Julia

Wrapper to the package DifferentialEquations.jl

Warning

This is work in progress.

The current package will provide basic methods to wrap some of the functionality of DifferentialEquations.jl.

Basically, the ultimate idea is that you provide a prob::ODEProblem to our newton, continuation... and they will use the expression of the jacobians, the linear solvers... that you already provided for the construction of prob.

diff --git a/dev/educational/index.html b/dev/educational/index.html index bdc3fd77..2acc4dce 100644 --- a/dev/educational/index.html +++ b/dev/educational/index.html @@ -105,244 +105,244 @@ p = scatter(ps, [x[1] for x in xs]; color = colors, markerstrokecolor = colors, xlabel = "p", ylabel = "x", label = "") - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/dev/eigensolver/index.html b/dev/eigensolver/index.html index 32abf5ce..4476de6c 100644 --- a/dev/eigensolver/index.html +++ b/dev/eigensolver/index.html @@ -8,4 +8,4 @@ nev2 = min(nev, length(I)) return F.values[I[1:nev2]], F.vectors[:, I[1:nev2]], true, 1 end
Eigenvalues

The eigenvalues must be ordered by increasing real part for the detection of bifurcations to work properly.

Eigenvectors

You have to implement the method geteigenvector(eigsolver, eigenvectors, i::Int) for newtonHopf to work properly.

Methods for computing eigenvalues

Like for the linear solvers, computing the spectrum of operators $A$ associated to PDE is a highly non trivial task because of the clustering of eigenvalues. Most methods are based on the so-called power method but this only yields the eigenvalues with largest modulus. In case of the Laplacian operator, this can be disastrous and it is better to apply the power method to $(\sigma I-A)^{-1}$ instead.

This method, called Shift-invert, is readily available for the solvers EigArpack and EigArnoldiMethod, see below. It is mostly used to compute interior eigenvalues. For the solver EigKrylovKit, one must implement its own shift invert operator, using for example GMRESKrylovKit.

In some cases, it may be advantageous to consider the Cayley transform $(\sigma I-A)^{-1}(\tau I+A)$ to focus on a specific part of the spectrum. As it is mathematically equivalent to the Shift-invert method, we did not implement it.

List of implemented eigen solvers

  1. Default eigen Julia eigensolver for matrices. You can create it via eig = DefaultEig(). Note that you can also specify how the eigenvalues are ordered (by decreasing real part by default). You can then compute 3 eigenelements of J like eig(J, 3).
  2. Eigensolver from Arpack.jl. You can create one via eigsolver = EigArpack() and pass appropriate options (see Arpack.jl). For example, you can compute eigenvalues using Shift-Invert method with shift σ by using EigArpack(σ, :LR). Note that you can specify how the eigenvalues are ordered (by decreasing real part by default). Finally, this method can be used for (sparse) matrix or Matrix-Free formulation. For a matrix J, you can compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigArpack(v0 = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3).
  3. Eigensolver from KrylovKit.jl. You create one via eig = EigKrylovKit() and pass appropriate options (see KrylovKit.jl). This method can be used for (sparse) matrix or Matrix-Free formulation. In the case of a matrix J, you can create a solver like this eig = EigKrylovKit(). Then, you compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigKrylovKit(x₀ = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3).
  4. Eigensolver from ArnoldiMethod.jl. You can create one via eig = EigArnoldiMethod() and pass appropriate options (see ArnoldiMethod.jl). For example, you can compute eigenvalues using the Shift-Invert method with shift σ by using EigArnoldiMethod(σ, LR()). Note that you can also specify how the eigenvalues are ordered (by decreasing real part by default). In the case of a matrix J, you can create a solver like eig = EigArnoldiMethod(). Then, you compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigArnoldiMethod(x₀ = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3).
Slow computations

This is probably due to iterative refinement conducted by SuiteSparse as explained in this blog post. You can disable this using

using SuiteSparse
-SuiteSparse.UMFPACK.umf_ctrl[8] = 0
+SuiteSparse.UMFPACK.umf_ctrl[8] = 0 diff --git a/dev/faq/index.html b/dev/faq/index.html index 7ed14945..899abd6a 100644 --- a/dev/faq/index.html +++ b/dev/faq/index.html @@ -20,4 +20,4 @@ out[3] = y - par.ω * x - y * x2 out end

Arpack is slow in computing eigenvalues

This is probably due to iterative refinement conducted by SuiteSparse as explained in this blog post. You can disable this using

using SuiteSparse
-SuiteSparse.UMFPACK.umf_ctrl[8] = 0

Should I use CVODE_BDF?

SciML is now able to match the performance of the Sundials solver CVODE_BDF. Check the news for more information.

+SuiteSparse.UMFPACK.umf_ctrl[8] = 0

Should I use CVODE_BDF?

SciML is now able to match the performance of the Sundials solver CVODE_BDF. Check the news for more information.

diff --git a/dev/gettingstarted/index.html b/dev/gettingstarted/index.html index 266639f2..9f9f5696 100644 --- a/dev/gettingstarted/index.html +++ b/dev/gettingstarted/index.html @@ -8,104 +8,104 @@ plot(br) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

where the pieces are described below.

Step 1: Defining a Problem

To solve this numerically, we define a problem type by giving it the equation, the initial condition, the parameters and the parameter axis to solve over:

using BifurcationKit
 F(x, p) = @. p.μ + x - x^3/3
 prob = BifurcationProblem(F, [-2.], (μ = -1.,), (@lens _.μ);
@@ -119,284 +119,284 @@
 scene = plot(br)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Choosing a continuation Algorithm

BifurcationKit.jl offers a much wider variety of continuation algorithms than traditional continuation softwares. Many of these algorithms are from recent research and have their own strengths and weaknesses. Each algoritm comes with a doc string, for example:

? PALC

For example, you can chose a different tangent predictor in PALC

opts = ContinuationPar(p_min = -1., p_max = 1.)
 br = continuation(prob, PALC(tangent = Bordered()), opts)
 scene = plot(br)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

or you can use the Moore-Penrose continuation algorithm

opts = ContinuationPar(p_min = -1., p_max = 1.)
 br = continuation(prob, MoorePenrose(), opts)
 scene = plot(br)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Step 3: Analyzing the Solution

The result of continuation is a solution object. A summary of the result is provided by the show method:

show(br) # this is equivalent to the REPL julia> br
 ┌─ Curve type: EquilibriumCont
  ├─ Number of points: 55
  ├─ Type of vectors: Vector{Float64}
@@ -407,113 +407,113 @@ 

bp at μ ≈ +0.66597167 ∈ (+0.66597167, +0.66658738), |δp|=6e-04, [converged], δ = ( 1, 0), step = 20, eigenelements in eig[ 21], ind_ev = 1 -- # 2, bp at μ ≈ -0.66665277 ∈ (-0.66666619, -0.66665277), |δp|=1e-05, [converged], δ = (-1, 0), step = 38, eigenelements in eig[ 39], ind_ev = 1 -- # 3, endpoint at μ ≈ +1.00000000, step = 54

From there, you can see that the branch has 55 points, the algorithm is also recalled because it can be modified internally. This summary shows that two bifurcation points where detected. At each such point, the couple δ indicates how many real/complex eigenvalues crossed the imaginary axis. This is useful for debugging or when non generic bifurcations are encountered.

We can access the 5th value of the branch with:

br[5]
(x = -2.0742615684285792, param = -0.9006174451276318, itnewton = 2, itlinear = 0, ds = 0.04102643120243098, n_unstable = 0, n_imag = 0, stable = true, step = 4, eigenvals = ComplexF64[-3.3025610542597894 + 0.0im], eigenvecs = ComplexF64[1.0 + 0.0im;;])

The solution contains many other fields:

propertynames(br)
(:branch, :eig, :sol, :contparams, :kind, :prob, :specialpoint, :alg)

Hence, the eigenelements are saved in br.eig, the solutions are saved in br.sol and the bifurcation points in br.specialpoint.

Plotting branches

While one can directly plot solution time points using the tools given above, convenience commands are defined by recipes for Plots.jl. To plot the solution object, simply call plot:

#]add Plots # You need to install Plots.jl before your first time using it!
+- #  1,       bp at μ ≈ +0.66597167 ∈ (+0.66597167, +0.66658738), |δp|=6e-04, [converged], δ = ( 1,  0), step =  20, eigenelements in eig[ 21], ind_ev =   1
+- #  2,       bp at μ ≈ -0.66665277 ∈ (-0.66666619, -0.66665277), |δp|=1e-05, [converged], δ = (-1,  0), step =  38, eigenelements in eig[ 39], ind_ev =   1
+- #  3, endpoint at μ ≈ +1.00000000,                                                                     step =  54

From there, you can see that the branch has 55 points, the algorithm is also recalled because it can be modified internally. This summary shows that two bifurcation points where detected. At each such point, the couple δ indicates how many real/complex eigenvalues crossed the imaginary axis. This is useful for debugging or when non generic bifurcations are encountered.

We can access the 5th value of the branch with:

br[5]
(x = -2.0742615684285792, param = -0.9006174451276318, itnewton = 2, itlinear = 0, ds = 0.04102643120243098, n_unstable = 0, n_imag = 0, stable = true, step = 4, eigenvals = ComplexF64[-3.3025610542597894 + 0.0im], eigenvecs = ComplexF64[1.0 + 0.0im;;])

The solution contains many other fields:

propertynames(br)
(:branch, :eig, :sol, :contparams, :kind, :prob, :specialpoint, :alg)

Hence, the eigenelements are saved in br.eig, the solutions are saved in br.sol and the bifurcation points in br.specialpoint.

Plotting branches

While one can directly plot solution time points using the tools given above, convenience commands are defined by recipes for Plots.jl. To plot the solution object, simply call plot:

#]add Plots # You need to install Plots.jl before your first time using it!
 using Plots
 #plotly() # You can optionally choose a plotting backend
 plot(br)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Example 2: simple branching

In this example, we will solve the equation

\[0 = x\cdot(\mu-x)\]

as function of $\mu$. Here $u\in\mathbb R$ is the state variable and $\mu$ is our parameter.

In our example, we know by calculus that the solutions to this equation are $u_0(\mu)=0$ and $u_1(\mu)=\mu$ but we will use BifurcationKit.jl to solve this problem numerically, which is essential for problems where a symbolic solution is not known.

In case we know there are many branches, the best is to use an automatic method to compute them all. We will focus on bifurcationdiagram which computes the connected component of the initial guess in the plane $(x,\mu)$. An alternative is to use Deflated Continuation.

We define a problem type by giving it the equation, the initial condition, the parameters and the parameter axis to solve over:

using Plots
 using BifurcationKit
 
@@ -555,80 +555,80 @@ 

bp at μ ≈ +0.00108349 ∈ (-0.00333593, +0.00108349), |δp|=4e-03, [converged], δ = ( 1, 0), step = 6, eigenelements in eig[ 7], ind_ev = 1 -- # 2, endpoint at μ ≈ +0.20000000, step = 8 +- # 1, bp at μ ≈ +0.00108349 ∈ (-0.00333593, +0.00108349), |δp|=4e-03, [converged], δ = ( 1, 0), step = 6, eigenelements in eig[ 7], ind_ev = 1 +- # 2, endpoint at μ ≈ +0.20000000, step = 8

You can plot the diagram like

plot(diagram)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Example 3: continuing periodic orbits

In this example, we will compute periodic orbits of the Stuart-Landau oscillator:

\[\begin{aligned} \frac{du}{dt} &= r u - \nu v - (u^2+v^2) (c_3 u - \mu v) \\ \frac{dv}{dt} &= r v + \nu u - (u^2+v^2) (c_3 + \mu u). @@ -660,9 +660,9 @@

Example 3: conti If `br` is the name of the branch, ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]` -- # 1, endpoint at r ≈ -1.00000000, step = 0 -- # 2, hopf at r ≈ -0.00595553 ∈ (-0.00595553, +0.00299379), |δp|=9e-03, [converged], δ = ( 2, 2), step = 8, eigenelements in eig[ 9], ind_ev = 2 -- # 3, endpoint at r ≈ +1.00000000, step = 24 +- # 1, endpoint at r ≈ -1.00000000, step = 0 +- # 2, hopf at r ≈ -0.00595553 ∈ (-0.00595553, +0.00299379), |δp|=9e-03, [converged], δ = ( 2, 2), step = 8, eigenelements in eig[ 9], ind_ev = 2 +- # 3, endpoint at r ≈ +1.00000000, step = 24

Having found a Hopf bifurcation, we compute the branch of periodic orbits which is nearby. Thus, we provide the branch br, the index of the special point we want to branch from: 2 in this case and a method PeriodicOrbitOCollProblem(20, 5) to compute periodic orbits. You can look at Periodic orbits computation for a list of all methods. Suffice it to say that PeriodicOrbitOCollProblem is the default method in the case of ODEs.

br_po = continuation(br, 2, opts,
         PeriodicOrbitOCollProblem(20, 5)
         )
 ┌─ Curve type: PeriodicOrbitCont from Hopf bifurcation point.
@@ -675,320 +675,320 @@ 

Example 3: conti If `br` is the name of the branch, ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]` -- # 1, endpoint at r ≈ +1.00000000, step = 14 +- # 1, endpoint at r ≈ +1.00000000, step = 14

Analyzing the Solution

The branch of periodic orbits has been computed. You can look at what is recorded in the first point on the branch:

br_po[1]
(max = 0.06359613398726469, min = -0.06359613398726469, amplitude = 0.12719226797452937, period = 6.2831853071795924, param = 0.00404446825657828, itnewton = 0, itlinear = 0, ds = 0.01, n_unstable = 0, n_imag = 0, stable = true, step = 0, eigenvals = ComplexF64[-9.731992989306553e-12 + 0.0im, -0.05082428707935688 + 0.0im], eigenvecs = ComplexF64[1.0081869231557963e-14 + 0.0im -1.0 + 0.0im; -1.0 + 0.0im 1.120207692395329e-14 + 0.0im])

It shows that the maximum/minimum/amplitude/period of the periodic orbit are recorded by default. You can also plot all the branches as follows

plot(br, br_po, branchlabel = ["equilibria", "periodic orbits"])
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Finally, if you are interested in the periodic orbits saved in br_po, for example to plot it, the method get_periodic_orbit is what you are looking for:

sol = get_periodic_orbit(br_po, 10)
 plot(sol.t, sol[1,:], label = "u", xlabel = "time")
 plot!(sol.t, sol[2,:], label = "v", xlabel = "time")
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Plotting the periodic orbit during continuation

If you plot the solution during continuation, you see that the right bottom panel is empty ; this panel is used to plot the solution at the current continuation step:

br_po = continuation(br, 2, opts,
         PeriodicOrbitOCollProblem(20, 5);
         plot = true,
         )
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

(Note that the bottom panel is a plot of the eigenvalues of the jacobian in the complex plane at the current continuation step. )

In order to plot the periodic solution during continuation, you need to supply a periodic_solution to continuation. This is not done by default because in some cases, obtaining the solution is costly (e.g. for Shooting methods). Based on the previous paragraph, it is straightforward to implement this plotting function:

br_po = continuation(br, 2, opts,
         PeriodicOrbitOCollProblem(20, 5);
@@ -1003,173 +1003,173 @@ 

- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/dev/guidelines/index.html b/dev/guidelines/index.html index e6bdbe7e..a38bf78d 100644 --- a/dev/guidelines/index.html +++ b/dev/guidelines/index.html @@ -1,2 +1,2 @@ -Guidelines · Bifurcation Analysis in Julia

Guidelines

The goal of this package is to find solutions $x$ to nonlinear equations

\[F(x,p) = 0 \quad\tag{E}\]

in large dimensions as function of a real parameter $p$. We want to be able to do so on GPU, distributed systems...

The core of the package is built around a Newton-Krylov solver (see newton) which allows to solve equations of the form $F(x)=0$, or find a solution $x_0$ to (E) for a particular $p_0$.

Once such a solution (or several) $(x_0,p_0)$ is known, we can continue it by computing a 1d curve of solutions $\gamma = (x(s),p(s))_{s\in I}$ passing through $(x_0,p_0)$ (see continuation and Deflated Continuation).

In practice, you don't need to know exactly $(x_0,p_0)$ to compute $\gamma$. Indeed, continuation will call newton to refine any initial guess that you pass.

Textbook

Only the basics of bifurcation theory is underlined here. We refer to [Kuznetsov],[haragus] for a more thorough description.

Bifurcation analysis of Equilibria

We can detect if the curve of solutions $\gamma$ crosses another curve of solutions $\gamma^{bif}$ without knowing $\gamma^{bif}$! The intersection point $(x^b,p^b)\in\gamma$ is called a bifurcation point and is such that $\partial_xF(x^b,p^b)$ is non invertible. When calling γ = continuation(...) with the option detect_bifurcation > 1 inside ContinuationPar, the bifurcation points are automatically detected and stored in γ.specialpoints.

Eigenvalues

The rightmost eigenvalues are computed by default to detect bifurcations. Hence, the number of eigenvalues with positive real parts must be finite (e.g. small). This might require to consider $-F(x,p)=0$ instead of (E).

Branch switching

In the simple case where $dim\ker \partial_xF(x^b,p^b) = 1$, we can compute automatically the bifurcated branch $\gamma^{bif}$ by calling continuation and passing $\gamma$. This is explained in Branch switching from simple branch point to equilibria. Recursively, we can compute the curves of solutions which are connected to $(x_0,p_0)$, this is called a bifurcation diagram. This bifurcation diagram can be automatically computed using the function bifurcationdiagram with minimum input from the user. More information is provided in Automatic Bifurcation diagram computation and examples of use are 1d Swift-Hohenberg equation and Bratu–Gelfand problem.

When $d\equiv dim\ker \partial_xF(x^b,p^b) > 1$, you can still compute automatically the bifurcated branches $\gamma^{bif}$s by calling continuation. It is based on a reduction of (E) to a small system of $d$ dimensional multivariate polynomial equations in $d$ unknowns whose solutions give the local topology of branches in the neighborhood of the bifurcation point $(x^b, p^b)$. The solutions of this reduced equation are then used as initial guesses for the call to Krylov-Newton. This is explained in From simple branch point to equilibria and examples of use are shown in 2d Bratu–Gelfand problem and Automatic 2d Bratu–Gelfand problem (Intermediate).

In the case $d=1$, the reduced equation can be further simplified into a normal form. This is also automatically computed by the package.

Branch switching

Many more branch switching procedures are available. They are all listed in Branch switching

Bifurcation analysis of Cauchy problems

The goal of this section is to study the dynamics of the Cauchy problem

\[\frac{d}{dt}x - F(x,p) = 0. \quad\tag{C}\]

The equilibria are time independent solutions of (C) hence satisfying (E). The previous section can be applied to compute curves of equilibria. However, we can do more. By discretizing time, we can recast (C) in the general form (E) and look for time dependent solutions as well.

We can detect the existence of periodic solutions close to $\gamma$. This is done automatically and those bifurcation points are stored in γ.specialpoint as well with the name of Hopf bifurcation points.

Branch switching at Hopf points

We focus on computing the branch of periodic solutions branching from a Hopf point. This is done automatically by calling continuation, passing $\gamma$ and choosing a time discretization algorithm (see Periodic orbits computation). Some details about this branch switching are given in From Hopf point to periodic orbits.

Branch switching at bifurcation points of periodic orbits

Let us consider the case where a branch of periodic orbits $\gamma^{po}$ have been computed (see for example previous section) and several bifurcation points have been detected (branch point, period doubling and Neimark Sacker). Can we compute bifurcated branches from $\gamma^{po}$? Automatically?

We do not provide an automatic branch switching for those points and for all methods (Shooting, Finite differences). However, for branch points of periodic orbits, you can call continuation by passing $\gamma^{po}$ and some simple arguments (amplitude of the periodic orbits) to perform branch switching in a semi-automatic way. For the case of Periodic orbits based on Trapezoidal rule, see From Branch / Period-doubling point of curve of periodic orbits.

Branch switching

Many more branch switching procedures are available. They are all listed in Branch switching

Manual Branch switching

You can perform manual branch switching by computing the nearby solutions close to a bifurcation point using a deflated newton (see Deflated problems), which provides a way to compute solutions other than a set of already known solutions. You can then use these solutions to compute branches by calling continuation. Many, if not all tutorials give example of doing so like 2d Bratu–Gelfand problem or 1d Brusselator.

References

  • Kuznetsov

    Kuznetsov, Yuri A. Elements of Applied Bifurcation Theory. Vol. 112. Applied Mathematical Sciences. Cham: Springer International Publishing, 2023. https://doi.org/10.1007/978-3-031-22007-4.

  • haragus

    Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

+Guidelines · Bifurcation Analysis in Julia

Guidelines

The goal of this package is to find solutions $x$ to nonlinear equations

\[F(x,p) = 0 \quad\tag{E}\]

in large dimensions as function of a real parameter $p$. We want to be able to do so on GPU, distributed systems...

The core of the package is built around a Newton-Krylov solver (see newton) which allows to solve equations of the form $F(x)=0$, or find a solution $x_0$ to (E) for a particular $p_0$.

Once such a solution (or several) $(x_0,p_0)$ is known, we can continue it by computing a 1d curve of solutions $\gamma = (x(s),p(s))_{s\in I}$ passing through $(x_0,p_0)$ (see continuation and Deflated Continuation).

In practice, you don't need to know exactly $(x_0,p_0)$ to compute $\gamma$. Indeed, continuation will call newton to refine any initial guess that you pass.

Textbook

Only the basics of bifurcation theory is underlined here. We refer to [Kuznetsov],[haragus] for a more thorough description.

Bifurcation analysis of Equilibria

We can detect if the curve of solutions $\gamma$ crosses another curve of solutions $\gamma^{bif}$ without knowing $\gamma^{bif}$! The intersection point $(x^b,p^b)\in\gamma$ is called a bifurcation point and is such that $\partial_xF(x^b,p^b)$ is non invertible. When calling γ = continuation(...) with the option detect_bifurcation > 1 inside ContinuationPar, the bifurcation points are automatically detected and stored in γ.specialpoints.

Eigenvalues

The rightmost eigenvalues are computed by default to detect bifurcations. Hence, the number of eigenvalues with positive real parts must be finite (e.g. small). This might require to consider $-F(x,p)=0$ instead of (E).

Branch switching

In the simple case where $dim\ker \partial_xF(x^b,p^b) = 1$, we can compute automatically the bifurcated branch $\gamma^{bif}$ by calling continuation and passing $\gamma$. This is explained in Branch switching from simple branch point to equilibria. Recursively, we can compute the curves of solutions which are connected to $(x_0,p_0)$, this is called a bifurcation diagram. This bifurcation diagram can be automatically computed using the function bifurcationdiagram with minimum input from the user. More information is provided in Automatic Bifurcation diagram computation and examples of use are 1d Swift-Hohenberg equation and Bratu–Gelfand problem.

When $d\equiv dim\ker \partial_xF(x^b,p^b) > 1$, you can still compute automatically the bifurcated branches $\gamma^{bif}$s by calling continuation. It is based on a reduction of (E) to a small system of $d$ dimensional multivariate polynomial equations in $d$ unknowns whose solutions give the local topology of branches in the neighborhood of the bifurcation point $(x^b, p^b)$. The solutions of this reduced equation are then used as initial guesses for the call to Krylov-Newton. This is explained in From simple branch point to equilibria and examples of use are shown in 2d Bratu–Gelfand problem and Automatic 2d Bratu–Gelfand problem (Intermediate).

In the case $d=1$, the reduced equation can be further simplified into a normal form. This is also automatically computed by the package.

Branch switching

Many more branch switching procedures are available. They are all listed in Branch switching

Bifurcation analysis of Cauchy problems

The goal of this section is to study the dynamics of the Cauchy problem

\[\frac{d}{dt}x - F(x,p) = 0. \quad\tag{C}\]

The equilibria are time independent solutions of (C) hence satisfying (E). The previous section can be applied to compute curves of equilibria. However, we can do more. By discretizing time, we can recast (C) in the general form (E) and look for time dependent solutions as well.

We can detect the existence of periodic solutions close to $\gamma$. This is done automatically and those bifurcation points are stored in γ.specialpoint as well with the name of Hopf bifurcation points.

Branch switching at Hopf points

We focus on computing the branch of periodic solutions branching from a Hopf point. This is done automatically by calling continuation, passing $\gamma$ and choosing a time discretization algorithm (see Periodic orbits computation). Some details about this branch switching are given in From Hopf point to periodic orbits.

Branch switching at bifurcation points of periodic orbits

Let us consider the case where a branch of periodic orbits $\gamma^{po}$ have been computed (see for example previous section) and several bifurcation points have been detected (branch point, period doubling and Neimark Sacker). Can we compute bifurcated branches from $\gamma^{po}$? Automatically?

We do not provide an automatic branch switching for those points and for all methods (Shooting, Finite differences). However, for branch points of periodic orbits, you can call continuation by passing $\gamma^{po}$ and some simple arguments (amplitude of the periodic orbits) to perform branch switching in a semi-automatic way. For the case of Periodic orbits based on Trapezoidal rule, see From Branch / Period-doubling point of curve of periodic orbits.

Branch switching

Many more branch switching procedures are available. They are all listed in Branch switching

Manual Branch switching

You can perform manual branch switching by computing the nearby solutions close to a bifurcation point using a deflated newton (see Deflated problems), which provides a way to compute solutions other than a set of already known solutions. You can then use these solutions to compute branches by calling continuation. Many, if not all tutorials give example of doing so like 2d Bratu–Gelfand problem or 1d Brusselator.

References

  • Kuznetsov

    Kuznetsov, Yuri A. Elements of Applied Bifurcation Theory. Vol. 112. Applied Mathematical Sciences. Cham: Springer International Publishing, 2023. https://doi.org/10.1007/978-3-031-22007-4.

  • haragus

    Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

diff --git a/dev/hh/index.html b/dev/hh/index.html index df6ecf7e..ce16f8af 100644 --- a/dev/hh/index.html +++ b/dev/hh/index.html @@ -5,4 +5,4 @@ & +O\left(\left\|\left(w_1, \bar{w}_1, w_2, \bar{w}_2\right)\right\|^6\right) \\ \dot{w}_2= & i \omega_2 w_2+G_{1110} w_2\left|w_1\right|^2+\frac{1}{2} G_{0021} w_2\left|w_2\right|^2 +\frac{1}{4} G_{2210} w_2\left|w_1\right|^4+\frac{1}{2} G_{1121} w_2\left|w_1\right|^2\left|w_2\right|^2+\frac{1}{12} G_{0032} w_2\left|w_2\right|^4 \\ & +O\left(\left\|\left(w_1, \bar{w}_1, w_2, \bar{w}_2\right)\right\|^6\right) -\end{aligned}\right.\tag{E}\]

This normal form is usually computed in order to branch from a Hopf-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the $G_{ijkl}$ is returned.

Normal form computation

The normal form (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type HopfHopf.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Kuznetsov

    Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

  • Kuznetsov2

    Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.

+\end{aligned}\right.\tag{E}\]

This normal form is usually computed in order to branch from a Hopf-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the $G_{ijkl}$ is returned.

Normal form computation

The normal form (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type HopfHopf.

Note

You should not need to call get_normal_form except if you need the full information about the branch point.

References

  • Kuznetsov

    Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

  • Kuznetsov2

    Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.

diff --git a/dev/index.html b/dev/index.html index 61703dc8..3a5cb9c8 100644 --- a/dev/index.html +++ b/dev/index.html @@ -13,7 +13,7 @@ }

Other softwares

There are many good softwares already available.

  • For continuation in small dimension, most softwares are listed on DSWeb. One can mention the widely used AUTO-07p, or also, XPPAUT, MATCONT, PyDSTool and COCO. All these are very reliable and some address high codimensional bifurcations.

  • For large scale problems, there is the versatile and feature full pde2path but also Trilinos-LOCA, CL_MATCONTL, COCO, GetFEM and the python libraries pyNCT and pacopy. There are also some nice lectures by D. Avitabile et al. on matrix free secant continuation based on a concise Matlab implementation which are used in the influential paper [Rankin]. At the time of initial release of BifurcationKit.jl, these lectures provided one of the only libraries for matrix-free continuation, much easier to use than Trilinos-LOCA.

  • For deflated continuation, there is defcont (by the inventor of the algo. P. E. Farrell) and this code by N. M. Evstigneev.

In Julia, we also have Bifurcations.jl which is unmaintained.

A word on performance

The examples which follow have not all been written with the goal of performance but rather simplicity (except maybe 2d Ginzburg-Landau equation and Langmuir–Blodgett model). One could surely turn them into more efficient codes. The intricacies of PDEs make the writing of efficient code highly problem dependent and one should take advantage of every particularity of the problem under study.

For example, in one of the simplest tutorials, Temperature model, one could use BandedMatrices.jl for the jacobian and an inplace modification when the jacobian is called ; using a composite type would be favored. Porting them to GPU could be another option.

Requested methods for Custom State

Needless to say, if you use regular arrays, you don't need to worry about what follows.

We make the same requirements as KrylovKit.jl. Hence, we refer to its docs for more information. We additionally require the following methods to be available:

  • Base.length(x): it is used in the constraint equation of the pseudo arclength continuation method (see continuation for more details). If length is not available for your "vector", define it length(x) = 1 and adjust tuning the parameter θ in PALC.
  • Base.copyto!(dest, in) this is required to reduce the allocations by avoiding too many copies
  • Base.eltype must be extended to your vector type. It is mainly used for branching.

Citations

The papers citing this work are collected on google scholar.

Reproducibility

The documentation of BifurcationKit was built using these direct dependencies,
Status `~/work/BifurcationKitDocs.jl/BifurcationKitDocs.jl/docs/Project.toml`
   [49cd1f3c] AsymptoticNumericalMethod v0.1.0 `https://github.com/bifurcationkit/AsymptoticNumericalMethod.jl#main`
 ⌅ [aae01518] BandedMatrices v0.17.18
-  [0f109fa4] BifurcationKit v0.3.2
+  [0f109fa4] BifurcationKit v0.3.3
   [52551710] BifurcationKitDocs v0.2.6 `~/work/BifurcationKitDocs.jl/BifurcationKitDocs.jl`
   [9fdde737] DiffEqOperators v4.45.0
 ⌃ [0c46a032] DifferentialEquations v7.7.0
@@ -27,9 +27,9 @@
   [efcf1570] Setfield v1.1.1
 ⌅ [47a9eef4] SparseDiffTools v1.31.0
   [37e2e46d] LinearAlgebra
-  [2f01184e] SparseArrays
-Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated`
and using this machine and Julia version.
Julia Version 1.9.4
-Commit 8e5136fa297 (2023-11-14 08:46 UTC)
+  [2f01184e] SparseArrays v1.10.0
+Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated`
and using this machine and Julia version.
Julia Version 1.10.0
+Commit 3120989f39b (2023-12-25 18:01 UTC)
 Build Info:
   Official https://julialang.org/ release
 Platform Info:
@@ -37,24 +37,22 @@
   CPU: 4 × AMD EPYC 7763 64-Core Processor
   WORD_SIZE: 64
   LIBM: libopenlibm
-  LLVM: libLLVM-14.0.6 (ORCJIT, znver3)
-  Threads: 1 on 4 virtual cores
-Environment:
-  JULIA_IMAGE_THREADS = 1
A more complete overview of all dependencies and their versions is also provided.
Status `~/work/BifurcationKitDocs.jl/BifurcationKitDocs.jl/docs/Manifest.toml`
-  [47edcb42] ADTypes v0.2.5
+  LLVM: libLLVM-15.0.7 (ORCJIT, znver3)
+  Threads: 1 on 4 virtual cores
A more complete overview of all dependencies and their versions is also provided.
Status `~/work/BifurcationKitDocs.jl/BifurcationKitDocs.jl/docs/Manifest.toml`
+  [47edcb42] ADTypes v0.2.6
   [a4c015fc] ANSIColoredPrinters v0.0.1
 ⌅ [c3fe647b] AbstractAlgebra v0.27.10
   [1520ce14] AbstractTrees v0.4.4
-  [79e6a3ab] Adapt v3.7.2
+⌅ [79e6a3ab] Adapt v3.7.2
   [ec485272] ArnoldiMethod v0.2.0
 ⌅ [7d9fca2a] Arpack v0.5.3
-  [4fba245c] ArrayInterface v7.6.1
+  [4fba245c] ArrayInterface v7.7.0
 ⌅ [4c555306] ArrayLayouts v0.8.18
   [49cd1f3c] AsymptoticNumericalMethod v0.1.0 `https://github.com/bifurcationkit/AsymptoticNumericalMethod.jl#main`
   [a9b6321e] Atomix v0.1.0
 ⌅ [aae01518] BandedMatrices v0.17.18
   [6e4b80f9] BenchmarkTools v1.4.0
-  [0f109fa4] BifurcationKit v0.3.2
+  [0f109fa4] BifurcationKit v0.3.3
   [52551710] BifurcationKitDocs v0.2.6 `~/work/BifurcationKitDocs.jl/BifurcationKitDocs.jl`
   [e2ed5e7c] Bijections v0.1.6
   [d1d4a3ce] BitFlags v0.1.8
@@ -66,7 +64,7 @@
   [2a0fbf3d] CPUSummary v0.2.4
   [00ebfdb7] CSTParser v3.3.6
   [49dc2e85] Calculus v0.5.1
-  [d360d2e6] ChainRulesCore v1.18.0
+  [d360d2e6] ChainRulesCore v1.19.0
   [fb6a15b2] CloseOpenIntervals v0.1.12
   [da1fd8a2] CodeTracking v1.3.5
   [944b1d66] CodecZlib v0.7.3
@@ -88,10 +86,10 @@
   [9a962f9c] DataAPI v1.15.0
   [864edb3b] DataStructures v0.18.15
   [e2d170a0] DataValueInterfaces v1.0.0
-  [bcd4f6db] DelayDiffEq v5.44.0
+⌃ [bcd4f6db] DelayDiffEq v5.44.0
   [8bb1440f] DelimitedFiles v1.9.1
 ⌃ [2b5f629d] DiffEqBase v6.130.0
-  [459566f4] DiffEqCallbacks v2.35.0
+⌃ [459566f4] DiffEqCallbacks v2.35.0
   [77a26b50] DiffEqNoiseProcess v5.20.0
   [9fdde737] DiffEqOperators v4.45.0
   [163ba53b] DiffResults v1.1.0
@@ -116,14 +114,14 @@
   [442a2c76] FastGaussQuadrature v1.0.1
 ⌅ [29a986be] FastLapackInterface v1.2.9
 ⌅ [1a297f60] FillArrays v0.13.11
-  [6a86dc24] FiniteDiff v2.21.1
+  [6a86dc24] FiniteDiff v2.22.0
   [53c48c17] FixedPointNumbers v0.8.4
   [59287772] Formatting v0.4.2
   [f6369f11] ForwardDiff v0.10.36
   [069b7b12] FunctionWrappers v1.1.3
   [77dc65aa] FunctionWrappersWrappers v0.1.3
   [d9f16b24] Functors v0.4.5
-  [46192b85] GPUArraysCore v0.1.5
+⌃ [46192b85] GPUArraysCore v0.1.5
 ⌅ [28b8d3ca] GR v0.72.10
   [c145ed77] GenericSchur v0.5.3
   [c27321d9] Glob v1.3.1
@@ -149,7 +147,7 @@
   [aa1ae85d] JuliaInterpreter v0.9.27
   [ccbc3e58] JumpProcesses v9.10.1
   [ef3ab10e] KLU v0.4.1
-  [63c18a36] KernelAbstractions v0.9.14
+  [63c18a36] KernelAbstractions v0.9.15
   [ba0b0d4f] Krylov v0.9.5
   [0b1a1467] KrylovKit v0.6.0
   [929cbde3] LLVM v6.4.1
@@ -170,7 +168,7 @@
   [e6f89c97] LoggingExtras v1.0.3
   [bdcacae8] LoopVectorization v0.12.166
   [6f1432cf] LoweredCodeUtils v2.3.2
-  [1914dd2f] MacroTools v0.5.11
+  [1914dd2f] MacroTools v0.5.12
   [d125e4d3] ManualMemory v0.1.8
 ⌅ [a3b82374] MatrixFactorizations v0.9.6
   [739be429] MbedTLS v1.1.9
@@ -185,7 +183,7 @@
 ⌅ [872c559c] NNlib v0.8.21
   [77ba4419] NaNMath v1.0.2
 ⌅ [8913a72c] NonlinearSolve v1.6.0
-  [6fe1bfb0] OffsetArrays v1.12.10
+  [6fe1bfb0] OffsetArrays v1.13.0
   [4d8831e6] OpenSSL v1.4.1
   [429524aa] Optim v1.7.8
   [bac558e1] OrderedCollections v1.6.3
@@ -193,11 +191,11 @@
   [90014a1f] PDMats v0.11.31
   [65ce6f38] PackageExtensionCompat v1.0.2
   [d96e819e] Parameters v0.12.3
-  [69de0a69] Parsers v2.8.0
+  [69de0a69] Parsers v2.8.1
   [b98c9c47] Pipe v1.3.0
   [32113eaa] PkgBenchmark v0.2.12
   [ccf2f8ad] PlotThemes v3.1.0
-  [995b91a9] PlotUtils v1.3.5
+  [995b91a9] PlotUtils v1.4.0
   [91a5bcdd] Plots v1.39.0
   [e409e4f3] PoissonRandom v0.4.4
   [f517fe37] Polyester v0.7.9
@@ -209,7 +207,7 @@
   [27ebfcd6] Primes v0.5.5
   [33c8b6b6] ProgressLogging v0.1.4
   [1fd47b50] QuadGK v2.9.1
-  [74087812] Random123 v1.6.1
+  [74087812] Random123 v1.6.2
   [fb686558] RandomExtensions v0.4.4
   [e6cf234a] RandomNumbers v1.5.3
   [3cdcf5f2] RecipesBase v1.3.4
@@ -236,13 +234,13 @@
   [699a6c99] SimpleTraits v0.9.4
   [ce78b400] SimpleUnPack v1.1.0
   [66db9d55] SnoopPrecompile v1.0.3
-  [a2af1166] SortingAlgorithms v1.2.0
+  [a2af1166] SortingAlgorithms v1.2.1
 ⌅ [47a9eef4] SparseDiffTools v1.31.0
   [e56a9233] Sparspak v0.3.9
   [276daf66] SpecialFunctions v2.3.1
   [aedffcd0] Static v0.8.8
   [0d7ed370] StaticArrayInterface v1.5.0
-  [90137ffa] StaticArrays v1.8.0
+  [90137ffa] StaticArrays v1.8.1
   [1e83bf80] StaticArraysCore v1.4.2
   [82ae8749] StatsAPI v1.7.0
   [2913bbd2] StatsBase v0.34.2
@@ -274,7 +272,7 @@
   [1cfade01] UnicodeFun v0.4.1
   [1986cc42] Unitful v1.19.0
   [45397f5d] UnitfulLatexify v1.6.3
-  [a7c27f48] Unityper v0.1.5
+  [a7c27f48] Unityper v0.1.6
   [013be700] UnsafeAtomics v0.2.1
   [d80eeb9a] UnsafeAtomicsLLVM v0.1.3
   [41fe7b60] Unzip v0.2.0
@@ -290,7 +288,7 @@
   [a3f928ae] Fontconfig_jll v2.13.93+0
   [d7e528f0] FreeType2_jll v2.13.1+0
   [559328eb] FriBidi_jll v1.0.10+0
-  [0656b61e] GLFW_jll v3.3.8+0
+  [0656b61e] GLFW_jll v3.3.9+0
 ⌅ [d2c73de3] GR_jll v0.72.10+0
   [78b55507] Gettext_jll v0.21.0+0
   [7746bdde] Glib_jll v2.76.5+0
@@ -300,7 +298,7 @@
   [c1c5ebd0] LAME_jll v3.100.1+0
   [88015f11] LERC_jll v3.0.0+1
   [dad2f222] LLVMExtra_jll v0.0.27+1
-  [1d63c593] LLVMOpenMP_jll v15.0.4+0
+  [1d63c593] LLVMOpenMP_jll v15.0.7+0
   [dd4b983a] LZO_jll v2.10.1+0
 ⌅ [e9f186c6] Libffi_jll v3.2.2+1
   [d4300ac3] Libgcrypt_jll v1.8.7+0
@@ -317,7 +315,7 @@
   [30392449] Pixman_jll v0.42.2+0
   [c0090381] Qt6Base_jll v6.5.3+1
   [f50d1b31] Rmath_jll v0.4.0+0
-⌅ [fb77eaff] Sundials_jll v5.2.1+0
+⌅ [fb77eaff] Sundials_jll v5.2.2+0
   [a44049a8] Vulkan_Loader_jll v1.3.243+0
   [a2964d1f] Wayland_jll v1.21.0+1
   [2381bf8a] Wayland_protocols_jll v1.25.0+0
@@ -381,7 +379,7 @@
   [d6f4376e] Markdown
   [a63ad114] Mmap
   [ca575930] NetworkOptions v1.2.0
-  [44cfe95a] Pkg v1.9.2
+  [44cfe95a] Pkg v1.10.0
   [de0858da] Printf
   [9abbd945] Profile
   [3fa0cd96] REPL
@@ -390,27 +388,28 @@
   [9e88b42a] Serialization
   [1a1011a3] SharedArrays
   [6462fe0b] Sockets
-  [2f01184e] SparseArrays
-  [10745b16] Statistics v1.9.0
+  [2f01184e] SparseArrays v1.10.0
+  [10745b16] Statistics v1.10.0
   [4607b0f0] SuiteSparse
   [fa267f1f] TOML v1.0.3
   [a4e569a6] Tar v1.10.0
   [8dfed614] Test
   [cf7118a7] UUIDs
   [4ec0a83e] Unicode
-  [e66e0078] CompilerSupportLibraries_jll v1.0.5+0
+  [e66e0078] CompilerSupportLibraries_jll v1.0.5+1
   [deac9b47] LibCURL_jll v8.4.0+0
+  [e37daf67] LibGit2_jll v1.6.4+0
   [29816b5a] LibSSH2_jll v1.11.0+1
-  [c8ffd9c3] MbedTLS_jll v2.28.2+0
-  [14a3606d] MozillaCACerts_jll v2022.10.11
-  [4536629a] OpenBLAS_jll v0.3.21+4
-  [05823500] OpenLibm_jll v0.8.1+0
-  [efcefdf7] PCRE2_jll v10.42.0+0
-  [bea87d4a] SuiteSparse_jll v5.10.1+6
-  [83775a58] Zlib_jll v1.2.13+0
-  [8e850b90] libblastrampoline_jll v5.8.0+0
+  [c8ffd9c3] MbedTLS_jll v2.28.2+1
+  [14a3606d] MozillaCACerts_jll v2023.1.10
+  [4536629a] OpenBLAS_jll v0.3.23+2
+  [05823500] OpenLibm_jll v0.8.1+2
+  [efcefdf7] PCRE2_jll v10.42.0+1
+  [bea87d4a] SuiteSparse_jll v7.2.1+1
+  [83775a58] Zlib_jll v1.2.13+1
+  [8e850b90] libblastrampoline_jll v5.8.0+1
   [8e850ede] nghttp2_jll v1.52.0+1
-  [3f19e933] p7zip_jll v17.4.0+0
+  [3f19e933] p7zip_jll v17.4.0+2
 Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated -m`
You can also download the manifest file and the -project file.

References

  • Rankin

    J. Rankin et al., "Continuation of localized coherent structures in nonlocal neural field equations", SIAM J. Scientific Computing 36, pp. B70–B93 (2014): https://epubs.siam.org/doi/10.1137/130918721

+project file.

References

  • Rankin

    J. Rankin et al., "Continuation of localized coherent structures in nonlocal neural field equations", SIAM J. Scientific Computing 36, pp. B70–B93 (2014): https://epubs.siam.org/doi/10.1137/130918721

diff --git a/dev/interfaceFlow/index.html b/dev/interfaceFlow/index.html index ddd9cf4c..5546b154 100644 --- a/dev/interfaceFlow/index.html +++ b/dev/interfaceFlow/index.html @@ -1,2 +1,2 @@ -Flow · Bifurcation Analysis in Julia

Interface for Flow of Cauchy problem

Here is a description of the interface that is used to specify flows or semigroups of solutions of a Cauchy problem $\frac{du}{dt} = F(u, p),\quad u(0) = u_0.$

More precisely, we call flow the mapping $Flow(x, p, t) = u(t)$.

The flow fl must be a subtype of the abstract type AbstractFlow. Note that in most cases, we only need u(t). However, for plotting, we need optionally the full trajectory with time stamps in $[0,T]$.

Another point is the need for implementing serial versions of multithreaded flows.

Required methodsBrief description
vf(fl, x, p)The vector field F(x, p) associated to a Cauchy problem. Used for the differential of the shooting problem. Must return F(x, p)
evolve(fl, x, par, t; k...)the function implements the flow (or semigroup) (x, p, t) -> flow(x, p, t) associated to an autonomous Cauchy problem. Only the last time point must be returned in the form Named Tuple (u = ..., t = t). In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, x, par, Inf).
Optional methodsBrief description
evolve(fl, x, par, t; k...)Same as above but for t::AbstractVector of some length M and x a matrix of size N x M. In this case, you are asked to compute several flows flow(x[:, i],p,t[i]). This can be done in parallel.
evolve(fl, x, par, dx, t; k...)The differential dflow of the flow w.r.t. x, (x, p, dx, t) -> dflow(x, p, dx, t). One important thing is that we require dflow(x, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = dflow(x, p, dx, t)), the last component being the value of the derivative of the flow.
evolve(fl, ::Val{:Full}, x, par, t; k...)The function implements the flow (or semigroup) associated to an autonomous Cauchy problem (x, p, t) -> flow(x, p, t). The whole solution on the time interval [0,t] must be returned. It is not strictly necessary to provide this, it is mainly used for plotting on the user side. In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, Val(:Full), x, par, Inf).
evolve(fl, ::Val{:SerialTimeSol}, x, par, t; k...)Serial version of the flow. Used for Matrix based jacobian (Shooting and Poincaré Shooting) and diffPoincareMap
evolve(fl, ::Val{:TimeSol}, x, par, t = Inf; k...)Flow which returns the tuple (t, u(t)). Optional, mainly used for plotting on the user side.
evolve(fl, ::Val{:SerialdFlow}, x, par, dx, t; k...)Serial version of dflow. Used internally when using parallel multiple shooting. Named Tuple (u = ..., du = ..., t = t).
+Flow · Bifurcation Analysis in Julia

Interface for Flow of Cauchy problem

Here is a description of the interface that is used to specify flows or semigroups of solutions of a Cauchy problem $\frac{du}{dt} = F(u, p),\quad u(0) = u_0.$

More precisely, we call flow the mapping $Flow(x, p, t) = u(t)$.

The flow fl must be a subtype of the abstract type AbstractFlow. Note that in most cases, we only need u(t). However, for plotting, we need optionally the full trajectory with time stamps in $[0,T]$.

Another point is the need for implementing serial versions of multithreaded flows.

Required methodsBrief description
vf(fl, x, p)The vector field F(x, p) associated to a Cauchy problem. Used for the differential of the shooting problem. Must return F(x, p)
evolve(fl, x, par, t; k...)the function implements the flow (or semigroup) (x, p, t) -> flow(x, p, t) associated to an autonomous Cauchy problem. Only the last time point must be returned in the form Named Tuple (u = ..., t = t). In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, x, par, Inf).
Optional methodsBrief description
evolve(fl, x, par, t; k...)Same as above but for t::AbstractVector of some length M and x a matrix of size N x M. In this case, you are asked to compute several flows flow(x[:, i],p,t[i]). This can be done in parallel.
evolve(fl, x, par, dx, t; k...)The differential dflow of the flow w.r.t. x, (x, p, dx, t) -> dflow(x, p, dx, t). One important thing is that we require dflow(x, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = dflow(x, p, dx, t)), the last component being the value of the derivative of the flow.
evolve(fl, ::Val{:Full}, x, par, t; k...)The function implements the flow (or semigroup) associated to an autonomous Cauchy problem (x, p, t) -> flow(x, p, t). The whole solution on the time interval [0,t] must be returned. It is not strictly necessary to provide this, it is mainly used for plotting on the user side. In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, Val(:Full), x, par, Inf).
evolve(fl, ::Val{:SerialTimeSol}, x, par, t; k...)Serial version of the flow. Used for Matrix based jacobian (Shooting and Poincaré Shooting) and diffPoincareMap
evolve(fl, ::Val{:TimeSol}, x, par, t = Inf; k...)Flow which returns the tuple (t, u(t)). Optional, mainly used for plotting on the user side.
evolve(fl, ::Val{:SerialdFlow}, x, par, dx, t; k...)Serial version of dflow. Used internally when using parallel multiple shooting. Named Tuple (u = ..., du = ..., t = t).
diff --git a/dev/interfaceLS/index.html b/dev/interfaceLS/index.html index 17e14f67..58b15f6a 100644 --- a/dev/interfaceLS/index.html +++ b/dev/interfaceLS/index.html @@ -8,4 +8,4 @@ \end{array}\right] = \left[\begin{array}{l} R \\ n -\end{array}\right]\]

where $\xi_u,\xi_p\in\mathbb C$ and $dR,\xi_u\in\mathbb C^N$.

Required methodsBrief description
bls(J, dR, dzu, dzp, R, n, ξu::Number, ξp::Number; shift = nothing, kwargs...)Compute the solution dX, dl of the linear problem (BLS) where J is the jacobian and dR, dzu are vectors (not necessarily subtypes of AbstractVector). shift = nothing is used in place of saying shift=0. Returns (dX, dl, success::Bool, itnumber) where itnumber is the number of iterations for solving the problem.
+\end{array}\right]\]

where $\xi_u,\xi_p\in\mathbb C$ and $dR,\xi_u\in\mathbb C^N$.

Required methodsBrief description
bls(J, dR, dzu, dzp, R, n, ξu::Number, ξp::Number; shift = nothing, kwargs...)Compute the solution dX, dl of the linear problem (BLS) where J is the jacobian and dR, dzu are vectors (not necessarily subtypes of AbstractVector). shift = nothing is used in place of saying shift=0. Returns (dX, dl, success::Bool, itnumber) where itnumber is the number of iterations for solving the problem.
diff --git a/dev/interfacePred/index.html b/dev/interfacePred/index.html index ddfb5149..6c332668 100644 --- a/dev/interfacePred/index.html +++ b/dev/interfacePred/index.html @@ -1,2 +1,2 @@ -Predictor / corrector · Bifurcation Analysis in Julia

Interface for Predictor / Corrector

Here is a description of the interface that is used to specify predictor / corrector for continuation methods. The type must be a subtype of the abstract type AbstractTangentPredictor.

In the table below, we assume it::AbstractContinuationIterable and M = BorderedArray

Required methodsBrief description
getPredictor!(z_pred::M, z_old::M, τ::M, ds, pred::AbstractTangentPredictor, nrm = false)Write in z_pred a prediction for the new Newton guess given the current solution z_old, tangent τ and arc length ds.
getTangent!(τ::M, z_new::M, z_old::M, it, ds, θ, pred:: AbstractTangentPredictor, verbosity)Generate an estimate of the tangent to the branch of solutions at positions z_new, z_old
corrector(it, z_old::M, τ::M, z_pred::M, ds, θ, pred::AbstractTangentPredictor, linearalgo; normC = norm, callback = cbDefault, kwargs...)Correct the guess z_pred. Must return a tuple (sol, residuals, isconverged, it numbers, itlinear)
Optional methodsBrief description
Base.empty!(pred::AbstractTangentPredictor)Reset the predictor
+Predictor / corrector · Bifurcation Analysis in Julia

Interface for Predictor / Corrector

Here is a description of the interface that is used to specify predictor / corrector for continuation methods. The type must be a subtype of the abstract type AbstractTangentPredictor.

In the table below, we assume it::AbstractContinuationIterable and M = BorderedArray

Required methodsBrief description
getPredictor!(z_pred::M, z_old::M, τ::M, ds, pred::AbstractTangentPredictor, nrm = false)Write in z_pred a prediction for the new Newton guess given the current solution z_old, tangent τ and arc length ds.
getTangent!(τ::M, z_new::M, z_old::M, it, ds, θ, pred:: AbstractTangentPredictor, verbosity)Generate an estimate of the tangent to the branch of solutions at positions z_new, z_old
corrector(it, z_old::M, τ::M, z_pred::M, ds, θ, pred::AbstractTangentPredictor, linearalgo; normC = norm, callback = cbDefault, kwargs...)Correct the guess z_pred. Must return a tuple (sol, residuals, isconverged, it numbers, itlinear)
Optional methodsBrief description
Base.empty!(pred::AbstractTangentPredictor)Reset the predictor
diff --git a/dev/intro-abs/index.html b/dev/intro-abs/index.html index c233df71..6c9f0215 100644 --- a/dev/intro-abs/index.html +++ b/dev/intro-abs/index.html @@ -1,2 +1,2 @@ -Introduction · Bifurcation Analysis in Julia

Branch switching

The precise definition of the methods are given in Branch switching (branch point) and Branch switching (Hopf point).

Summary of branching procedures

We collect in the following table the list of automatic branch switching (aBS) functions. Their detailed explanation follows in this page.

functionind-th bif. pointType Tdescription
continuation(br::ContResult{T}, ind::Int; kw...):bp, :ndEquilibriumContaBS from equilibria to equilibria
continuation(br::ContResult{T}, ind::Int, lens2::Lens; kw...):bp, :hopfEquilibriumContFold/Hopf continuation w.r.t. parameters getlens(br) and lens2
continuation(br::ContResult{T}, ind::Int; kw...):bt,:zh,:hhFoldCont,HopfContswitch to Fold/Hopf continuation from Hopf/Fold w.r.t. parameters of codim 2 br
continuation(br::ContResult{T}, ind_hopf::Int, ::ContinuationPar, prob::AbstractPeriodicOrbitProblem):hopfEquilibriumContBranch switching from Hopf point to periodic orbits
continuation(br::ContResult{T}, ind::Int, kw...):bp,:pdPeriodicOrbitContBranch switching from Branch / Period-doubling point of periodic orbits to curve of periodic orbits
continuation(br::ContResult{T}, ind::Int, kw...):gh,:zh,:hhTwoParamContBranch switching from Bautin / Zero-Hopf/ Hopf-Hopf point to curve of Fold/NS of periodic orbits
+Introduction · Bifurcation Analysis in Julia

Branch switching

The precise definition of the methods are given in Branch switching (branch point) and Branch switching (Hopf point).

Summary of branching procedures

We collect in the following table the list of automatic branch switching (aBS) functions. Their detailed explanation follows in this page.

functionind-th bif. pointType Tdescription
continuation(br::ContResult{T}, ind::Int; kw...):bp, :ndEquilibriumContaBS from equilibria to equilibria
continuation(br::ContResult{T}, ind::Int, lens2::Lens; kw...):bp, :hopfEquilibriumContFold/Hopf continuation w.r.t. parameters getlens(br) and lens2
continuation(br::ContResult{T}, ind::Int; kw...):bt,:zh,:hhFoldCont,HopfContswitch to Fold/Hopf continuation from Hopf/Fold w.r.t. parameters of codim 2 br
continuation(br::ContResult{T}, ind_hopf::Int, ::ContinuationPar, prob::AbstractPeriodicOrbitProblem):hopfEquilibriumContBranch switching from Hopf point to periodic orbits
continuation(br::ContResult{T}, ind::Int, kw...):bp,:pdPeriodicOrbitContBranch switching from Branch / Period-doubling point of periodic orbits to curve of periodic orbits
continuation(br::ContResult{T}, ind::Int, kw...):gh,:zh,:hhTwoParamContBranch switching from Bautin / Zero-Hopf/ Hopf-Hopf point to curve of Fold/NS of periodic orbits
diff --git a/dev/intro_wave/index.html b/dev/intro_wave/index.html index fe4314d7..1039369d 100644 --- a/dev/intro_wave/index.html +++ b/dev/intro_wave/index.html @@ -11,4 +11,4 @@ \begin{array}{l}\tag{W} J x_1+c_1A_{12} = \sigma x_1 \\ \langle A_{21},x_1\rangle + A_{22}c_1=0 -\end{array}\right.\]

Case $A_{22}\neq 0$

If $A_{22}\neq 0$, the eigen problem is equivalent to

\[Jx_1 - c_1\frac{\langle A_{21},x_1\rangle}{A_{22}} A_{12}= \sigma x_1\]

Case $A_{22} = 0$

If $A_{22} = 0$, the eigen problem is equivalent to $x_1=α A_{21} + x_1^\bot$ with $\langle A_{21},x_1^\bot\rangle=0$. Hence, I find $\langle A_{21},Jx_1^\bot\rangle+c_1\langle A_{21},A_{12}\rangle=0$

\[Jx_1^\bot-\frac{\langle A_{21},Jx_1^\bot\rangle}{\langle A_{21},A_{12}\rangle}A_{21}=σ x_1^⊥\]

Encoding of the functional for the freezed problem

The freezing method is encoded in the composite type TWProblem which we loosely refer to as a Travelling Wave (TW) problem.

Computation with newton

We provide a simplified call to newton to locate the freezed solution

newton(prob::TWProblem, orbitguess, options::NewtonPar; kwargs...)

Continuation

We also provide a simplified call to continuation to continue the freezed solution as function of a parameter:

continuation(prob::TWProblem, orbitguess, lens::Lens, contParams::ContinuationPar; jacobian = :MatrixFree, kwargs...)

Note that in this case, the eigen solver passed in contParams is converted into an appropriate generalized eigensolver.

References

  • Beyn

    Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

  • Sandstede

    Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.

+\end{array}\right.\]

Case $A_{22}\neq 0$

If $A_{22}\neq 0$, the eigen problem is equivalent to

\[Jx_1 - c_1\frac{\langle A_{21},x_1\rangle}{A_{22}} A_{12}= \sigma x_1\]

Case $A_{22} = 0$

If $A_{22} = 0$, the eigen problem is equivalent to $x_1=α A_{21} + x_1^\bot$ with $\langle A_{21},x_1^\bot\rangle=0$. Hence, I find $\langle A_{21},Jx_1^\bot\rangle+c_1\langle A_{21},A_{12}\rangle=0$

\[Jx_1^\bot-\frac{\langle A_{21},Jx_1^\bot\rangle}{\langle A_{21},A_{12}\rangle}A_{21}=σ x_1^⊥\]

Encoding of the functional for the freezed problem

The freezing method is encoded in the composite type TWProblem which we loosely refer to as a Travelling Wave (TW) problem.

Computation with newton

We provide a simplified call to newton to locate the freezed solution

newton(prob::TWProblem, orbitguess, options::NewtonPar; kwargs...)

Continuation

We also provide a simplified call to continuation to continue the freezed solution as function of a parameter:

continuation(prob::TWProblem, orbitguess, lens::Lens, contParams::ContinuationPar; jacobian = :MatrixFree, kwargs...)

Note that in this case, the eigen solver passed in contParams is converted into an appropriate generalized eigensolver.

References

  • Beyn

    Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

  • Sandstede

    Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.

diff --git a/dev/iterator/index.html b/dev/iterator/index.html index 5890b0f8..6e463ec6 100644 --- a/dev/iterator/index.html +++ b/dev/iterator/index.html @@ -32,44 +32,44 @@ plot(resp, resx; label = "", xlabel = "p") - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + -

Additional information

If you want to customize the iterator to your needs, perhaps the best source of inspiration is the code of the function continuation!(it::ContIterable, state::ContState, contRes::ContResult) where the iterator is used at its fullest. You will see how the eigen-elements and the stability are computed, how bifurcations are detected and how results are saved.

+

Additional information

If you want to customize the iterator to your needs, perhaps the best source of inspiration is the code of the function continuation!(it::ContIterable, state::ContState, contRes::ContResult) where the iterator is used at its fullest. You will see how the eigen-elements and the stability are computed, how bifurcations are detected and how results are saved.

diff --git a/dev/library/index.html b/dev/library/index.html index ae09c8ac..7bcb1f3f 100644 --- a/dev/library/index.html +++ b/dev/library/index.html @@ -1,5 +1,5 @@ -Library · Bifurcation Analysis in Julia

Library

Parameters

BifurcationKit.NewtonParType
struct NewtonPar{T, L<:BifurcationKit.AbstractLinearSolver, E<:AbstractEigenSolver}

Returns a variable containing parameters to affect the newton algorithm when solving F(x) = 0.

Arguments (with default values):

  • tol::Any: absolute tolerance for F(x) Default: 1.0e-12

  • max_iterations::Int64: number of Newton iterations Default: 25

  • verbose::Bool: display Newton iterations? Default: false

  • linsolver::BifurcationKit.AbstractLinearSolver: linear solver, must be <: AbstractLinearSolver Default: DefaultLS()

  • eigsolver::AbstractEigenSolver: eigen solver, must be <: AbstractEigenSolver Default: DefaultEig()

  • linesearch::Bool: Default: false

  • α::Any: Default: convert(typeof(tol), 1.0)

  • αmin::Any: Default: convert(typeof(tol), 0.001)

Arguments for line search (Armijo)

  • linesearch = false: use line search algorithm (i.e. Newton with Armijo's rule)
  • α = 1.0: initial value of α (damping) parameter for line search algorithm
  • αmin = 0.001: minimal value of the damping alpha
Mutating

For performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See the tutorials for examples.

BifurcationKit.ContinuationParType
options = ContinuationPar(dsmin = 1e-4,...)

Returns a variable containing parameters to affect the continuation algorithm used to solve F(x,p) = 0.

Arguments

  • dsmin, dsmax are the minimum, maximum arclength allowed value. It controls the density of points in the computed branch of solutions.
  • ds = 0.01 is the initial arclength.
  • p_min, p_max allowed parameter range for p
  • max_steps = 100 maximum number of continuation steps
  • newton_options::NewtonPar: options for the Newton algorithm
  • save_to_file = false: save to file. A name is automatically generated or can be defined in continuation. This requires using JLD2.
  • save_sol_every_step::Int64 = 0 at which continuation steps do we save the current solution
  • plot_every_step = 10 at which continuation steps do we plot the current solution

Handling eigen elements, their computation is triggered by the argument detect_bifurcation (see below)

  • nev = 3 number of eigenvalues to be computed. It is automatically increased to have at least nev unstable eigenvalues. To be set for proper bifurcation detection. See Detection of bifurcation points of Equilibria for more informations.
  • save_eig_every_step = 1 record eigen vectors every specified steps. Important for memory limited resource, e.g. GPU.
  • save_eigenvectors = true Important for memory limited resource, e.g. GPU.

Handling bifurcation detection

  • tol_stability = 1e-10 lower bound on the real part of the eigenvalues to test for stability of equilibria and periodic orbits
  • detect_fold = true detect Fold bifurcations? It is a useful option although the detection of Fold is cheap. Indeed, it may happen that there is a lot of Fold points and this can saturate the memory in memory limited devices (e.g. on GPU)
  • detect_bifurcation::Int ∈ {0, 1, 2, 3} If set to 0, nothing is done. If set to 1, the eigen-elements are computed. If set to 2, the bifurcations points are detected during the continuation run, but not located precisely. If set to 3, a bisection algorithm is used to locate the bifurcations points (slower). The possibility to switch off detection is a useful option. Indeed, it may happen that there are a lot of bifurcation points and this can saturate the memory of memory limited devices (e.g. on GPU)
  • dsmin_bisection = 1e-16 dsmin for the bisection algorithm for locating bifurcation points
  • n_inversion = 2 number of sign inversions in bisection algorithm
  • max_bisection_steps = 15 maximum number of bisection steps
  • tol_bisection_eigenvalue = 1e-16 tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps

Handling ds adaptation (see continuation for more information)

  • a = 0.5 aggressiveness factor. It is used to adapt ds in order to have a number of newton iterations per continuation step roughly constant. The higher a is, the larger the step size ds is changed at each continuation step.

Handling event detection

  • detect_event::Int ∈ {0, 1, 2} If set to 0, nothing is done. If set to 1, the event locations are sought during the continuation run, but not located precisely. If set to 2, a bisection algorithm is used to locate the event (slower).
  • tol_param_bisection_event = 1e-16 tolerance on parameter to locate event

Misc

  • η = 150. parameter to estimate tangent at first point with parameter p₀ + ds / η
  • detect_loop [WORK IN PROGRESS] detect loops in the branch and stop the continuation
Mutating

For performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See tutorials for more examples.

Results

BifurcationKit.NonLinearSolutionType

Structure which holds the solution from application of Newton-Krylov algorithm to a nonlinear problem.

For example

sol = newton(prob, NewtonPar())

Fields

  • u::Any: solution

  • prob::Any: nonlinear problem, typically a BifurcationProblem

  • residuals::Any: sequence of residuals

  • converged::Bool: has algorithm converged?

  • itnewton::Int64: number of newton steps

  • itlineartot::Any: total number of linear iterations

BifurcationKit.ContResultType
struct ContResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tbr, Teigvals, Teigvec, Biftype, Tsol, Tparc, Tprob, Talg} <: BifurcationKit.AbstractResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tprob}

Structure which holds the results after a call to continuation.

You can see the propertynames of a result br by using propertynames(br) or propertynames(br.branch).

Fields

  • branch::StructArrays.StructArray: holds the low-dimensional information about the branch. More precisely, branch[i+1] contains the following information (record_from_solution(u, param), param, itnewton, itlinear, ds, θ, n_unstable, n_imag, stable, step) for each continuation step i.

    • itnewton number of Newton iterations
    • itlinear total number of linear iterations during newton (corrector)
    • n_unstable number of eigenvalues with positive real part for each continuation step (to detect stationary bifurcation)
    • n_imag number of eigenvalues with positive real part and non zero imaginary part at current continuation step (useful to detect Hopf bifurcation).
    • stable stability of the computed solution for each continuation step. Hence, stable should match eig[step] which corresponds to branch[k] for a given k.
    • step continuation step (here equal i)
  • eig::Array{NamedTuple{(:eigenvals, :eigenvecs, :converged, :step), Tuple{Teigvals, Teigvec, Bool, Int64}}, 1} where {Teigvals, Teigvec}: A vector with eigen-elements at each continuation step.

  • sol::Any: Vector of solutions sampled along the branch. This is set by the argument save_sol_every_step::Int64 (default 0) in ContinuationPar.

  • contparams::Any: The parameters used for the call to continuation which produced this branch. Must be a ContinuationPar

  • kind::BifurcationKit.AbstractContinuationKind: Type of solutions computed in this branch. Default: EquilibriumCont()

  • prob::Any: Bifurcation problem used to compute the branch, useful for branch switching. For example, when computing periodic orbits, the functional PeriodicOrbitTrapProblem, ShootingProblem... will be saved here. Default: nothing

  • specialpoint::Vector: A vector holding the set of detected bifurcation points. See SpecialPoint for a list of special points.

  • alg::Any: Continuation algorithm used for the computation of the branch

Associated methods

  • length(br) number of the continuation steps
  • show(br) display information about the branch
  • eigenvals(br, ind) returns the eigenvalues for the ind-th continuation step
  • eigenvec(br, ind, indev) returns the indev-th eigenvector for the ind-th continuation step
  • get_normal_form(br, ind) compute the normal form of the ind-th points in br.specialpoint
  • getlens(br) return the parameter axis used for the branch
  • getlenses(br) return the parameter two axis used for the branch when 2 parameters continuation is used (Fold, Hopf, NS, PD)
  • br[k+1] gives information about the k-th step. A typical run yields the following
julia> br[1]
+Library · Bifurcation Analysis in Julia

Library

Parameters

BifurcationKit.NewtonParType
struct NewtonPar{T, L<:BifurcationKit.AbstractLinearSolver, E<:AbstractEigenSolver}

Returns a variable containing parameters to affect the newton algorithm when solving F(x) = 0.

Arguments (with default values):

  • tol::Any: absolute tolerance for F(x) Default: 1.0e-12

  • max_iterations::Int64: number of Newton iterations Default: 25

  • verbose::Bool: display Newton iterations? Default: false

  • linsolver::BifurcationKit.AbstractLinearSolver: linear solver, must be <: AbstractLinearSolver Default: DefaultLS()

  • eigsolver::AbstractEigenSolver: eigen solver, must be <: AbstractEigenSolver Default: DefaultEig()

  • linesearch::Bool: Default: false

  • α::Any: Default: convert(typeof(tol), 1.0)

  • αmin::Any: Default: convert(typeof(tol), 0.001)

Arguments for line search (Armijo)

  • linesearch = false: use line search algorithm (i.e. Newton with Armijo's rule)
  • α = 1.0: initial value of α (damping) parameter for line search algorithm
  • αmin = 0.001: minimal value of the damping alpha
Mutating

For performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See the tutorials for examples.

BifurcationKit.ContinuationParType
options = ContinuationPar(dsmin = 1e-4,...)

Returns a variable containing parameters to affect the continuation algorithm used to solve F(x,p) = 0.

Arguments

  • dsmin, dsmax are the minimum, maximum arclength allowed value. It controls the density of points in the computed branch of solutions.
  • ds = 0.01 is the initial arclength.
  • p_min, p_max allowed parameter range for p
  • max_steps = 100 maximum number of continuation steps
  • newton_options::NewtonPar: options for the Newton algorithm
  • save_to_file = false: save to file. A name is automatically generated or can be defined in continuation. This requires using JLD2.
  • save_sol_every_step::Int64 = 0 at which continuation steps do we save the current solution
  • plot_every_step = 10 at which continuation steps do we plot the current solution

Handling eigen elements, their computation is triggered by the argument detect_bifurcation (see below)

  • nev = 3 number of eigenvalues to be computed. It is automatically increased to have at least nev unstable eigenvalues. To be set for proper bifurcation detection. See Detection of bifurcation points of Equilibria for more informations.
  • save_eig_every_step = 1 record eigen vectors every specified steps. Important for memory limited resource, e.g. GPU.
  • save_eigenvectors = true Important for memory limited resource, e.g. GPU.

Handling bifurcation detection

  • tol_stability = 1e-10 lower bound on the real part of the eigenvalues to test for stability of equilibria and periodic orbits
  • detect_fold = true detect Fold bifurcations? It is a useful option although the detection of Fold is cheap. Indeed, it may happen that there is a lot of Fold points and this can saturate the memory in memory limited devices (e.g. on GPU)
  • detect_bifurcation::Int ∈ {0, 1, 2, 3} If set to 0, nothing is done. If set to 1, the eigen-elements are computed. If set to 2, the bifurcations points are detected during the continuation run, but not located precisely. If set to 3, a bisection algorithm is used to locate the bifurcations points (slower). The possibility to switch off detection is a useful option. Indeed, it may happen that there are a lot of bifurcation points and this can saturate the memory of memory limited devices (e.g. on GPU)
  • dsmin_bisection = 1e-16 dsmin for the bisection algorithm for locating bifurcation points
  • n_inversion = 2 number of sign inversions in bisection algorithm
  • max_bisection_steps = 15 maximum number of bisection steps
  • tol_bisection_eigenvalue = 1e-16 tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps

Handling ds adaptation (see continuation for more information)

  • a = 0.5 aggressiveness factor. It is used to adapt ds in order to have a number of newton iterations per continuation step roughly constant. The higher a is, the larger the step size ds is changed at each continuation step.

Handling event detection

  • detect_event::Int ∈ {0, 1, 2} If set to 0, nothing is done. If set to 1, the event locations are sought during the continuation run, but not located precisely. If set to 2, a bisection algorithm is used to locate the event (slower).
  • tol_param_bisection_event = 1e-16 tolerance on parameter to locate event

Misc

  • η = 150. parameter to estimate tangent at first point with parameter p₀ + ds / η
  • detect_loop [WORK IN PROGRESS] detect loops in the branch and stop the continuation
Mutating

For performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See tutorials for more examples.

Results

BifurcationKit.NonLinearSolutionType

Structure which holds the solution from application of Newton-Krylov algorithm to a nonlinear problem.

For example

sol = newton(prob, NewtonPar())

Fields

  • u::Any: solution

  • prob::Any: nonlinear problem, typically a BifurcationProblem

  • residuals::Any: sequence of residuals

  • converged::Bool: has algorithm converged?

  • itnewton::Int64: number of newton steps

  • itlineartot::Any: total number of linear iterations

BifurcationKit.ContResultType
struct ContResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tbr, Teigvals, Teigvec, Biftype, Tsol, Tparc, Tprob, Talg} <: BifurcationKit.AbstractResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tprob}

Structure which holds the results after a call to continuation.

You can see the propertynames of a result br by using propertynames(br) or propertynames(br.branch).

Fields

  • branch::StructArrays.StructArray: holds the low-dimensional information about the branch. More precisely, branch[i+1] contains the following information (record_from_solution(u, param), param, itnewton, itlinear, ds, θ, n_unstable, n_imag, stable, step) for each continuation step i.

    • itnewton number of Newton iterations
    • itlinear total number of linear iterations during newton (corrector)
    • n_unstable number of eigenvalues with positive real part for each continuation step (to detect stationary bifurcation)
    • n_imag number of eigenvalues with positive real part and non zero imaginary part at current continuation step (useful to detect Hopf bifurcation).
    • stable stability of the computed solution for each continuation step. Hence, stable should match eig[step] which corresponds to branch[k] for a given k.
    • step continuation step (here equal i)
  • eig::Array{@NamedTuple{eigenvals::Teigvals, eigenvecs::Teigvec, converged::Bool, step::Int64}, 1} where {Teigvals, Teigvec}: A vector with eigen-elements at each continuation step.

  • sol::Any: Vector of solutions sampled along the branch. This is set by the argument save_sol_every_step::Int64 (default 0) in ContinuationPar.

  • contparams::Any: The parameters used for the call to continuation which produced this branch. Must be a ContinuationPar

  • kind::BifurcationKit.AbstractContinuationKind: Type of solutions computed in this branch. Default: EquilibriumCont()

  • prob::Any: Bifurcation problem used to compute the branch, useful for branch switching. For example, when computing periodic orbits, the functional PeriodicOrbitTrapProblem, ShootingProblem... will be saved here. Default: nothing

  • specialpoint::Vector: A vector holding the set of detected bifurcation points. See SpecialPoint for a list of special points.

  • alg::Any: Continuation algorithm used for the computation of the branch

Associated methods

  • length(br) number of the continuation steps
  • show(br) display information about the branch
  • eigenvals(br, ind) returns the eigenvalues for the ind-th continuation step
  • eigenvec(br, ind, indev) returns the indev-th eigenvector for the ind-th continuation step
  • get_normal_form(br, ind) compute the normal form of the ind-th points in br.specialpoint
  • getlens(br) return the parameter axis used for the branch
  • getlenses(br) return the parameter two axis used for the branch when 2 parameters continuation is used (Fold, Hopf, NS, PD)
  • br[k+1] gives information about the k-th step. A typical run yields the following
julia> br[1]
 (x = 0.0, param = 0.1, itnewton = 0, itlinear = 0, ds = -0.01, θ = 0.5, n_unstable = 2, n_imag = 2, stable = false, step = 0, eigenvals = ComplexF64[0.1 - 1.0im, 0.1 + 1.0im], eigenvecs = ComplexF64[0.7071067811865475 - 0.0im 0.7071067811865475 + 0.0im; 0.0 + 0.7071067811865475im 0.0 - 0.7071067811865475im])

which provides the value param of the parameter of the current point, its stability, information on the newton iterations, etc. The fields can be retrieved using propertynames(br.branch). This information is stored in br.branch which is a StructArray. You can thus extract the vector of parameters along the branch as

julia> br.param
 10-element Vector{Float64}:
  0.1
@@ -11,10 +11,10 @@
 -0.17899902778635765
 -0.3204203840236672
 -0.4618417402609767
--0.5
  • get_solx(br, k) returns the k-th solution on the branch
  • get_solp(br, k) returns the parameter value associated with k-th solution on the branch
  • getparams(br) Parameters passed to continuation and used in the equation F(x, par) = 0.
  • setparam(br, p0) set the parameter value p0 according to ::Lens for the parameters of the problem br.prob
  • getlens(br) get the lens used for the computation of the branch
  • continuation(br, ind) performs automatic branch switching (aBS) from ind-th bifurcation point. Typically branching from equilibrium to equilibrium, or periodic orbit to periodic orbit.
  • continuation(br, ind, lens2) performs two parameters (getLens(br), lens2) continuation of the ind-th bifurcation point.
  • continuation(br, ind, probPO::AbstractPeriodicOrbitProblem) performs aBS from ind-th bifurcation point (which must be a Hopf bifurcation point) to branch of periodic orbits.

Problems

BifurcationKit.BifFunctionType
struct BifFunction{Tf, Tdf, Tdfad, Tj, Tjad, Td2f, Td2fc, Td3f, Td3fc, Tsym, Tδ} <: BifurcationKit.AbstractBifurcationFunction

Structure to hold the vector field and its derivatives. It should rarely be called directly. Also, in essence, it is very close to SciMLBase.ODEFunction.

Fields

  • F::Any: Vector field. Function of type out-of-place result = f(x, p) or inplace f(result, x, p). For type stability, the types of x and result should match

  • dF::Any: Differential of F with respect to x, signature dF(x,p,dx)

  • dFad::Any: Adjoint of the Differential of F with respect to x, signature dFad(x,p,dx)

  • J::Any: Jacobian of F at (x, p). It can assume three forms. 1. Either J is a function and J(x, p) returns a ::AbstractMatrix. In this case, the default arguments of contparams::ContinuationPar will make continuation work. 2. Or J is a function and J(x, p) returns a function taking one argument dx and returning dr of the same type as dx. In our notation, dr = J * dx. In this case, the default parameters of contparams::ContinuationPar will not work and you have to use a Matrix Free linear solver, for example GMRESIterativeSolvers, 3. Or J is a function and J(x, p) returns a variable j which can assume any type. Then, you must implement a linear solver ls as a composite type, subtype of AbstractLinearSolver which is called like ls(j, rhs) and which returns the solution of the jacobian linear system. See for example examples/SH2d-fronts-cuda.jl. This linear solver is passed to NewtonPar(linsolver = ls) which itself passed to ContinuationPar. Similarly, you have to implement an eigensolver eig as a composite type, subtype of AbstractEigenSolver.

  • Jᵗ::Any: jacobian adjoint, it should be implemented in an efficient manner. For matrix-free methods, transpose is not readily available and the user must provide a dedicated method. In the case of sparse based jacobian, Jᵗ should not be passed as it is computed internally more efficiently, i.e. it avoids recomputing the jacobian as it would be if you pass Jᵗ = (x, p) -> transpose(dF(x, p)).

  • d2F::Any: Second Differential of F with respect to x, signature d2F(x,p,dx1,dx2)

  • d3F::Any: Third Differential of F with respect to x, signature d3F(x,p,dx1,dx2,dx3)

  • d2Fc::Any: [internal] Second Differential of F with respect to x which accept complex vectors dxi

  • d3Fc::Any: [internal] Third Differential of F with respect to x which accept complex vectors dxi

  • isSymmetric::Any: Whether the jacobian is auto-adjoint.

  • δ::Any: used internally to compute derivatives (with finite differences), for example for normal form computation and codim 2 continuation.

  • inplace::Bool: optionally sets whether the function is inplace or not

Methods

  • residual(pb::BifFunction, x, p) calls pb.F(x,p)
  • jacobian(pb::BifFunction, x, p) calls pb.J(x, p)
  • dF(pb::BifFunction, x, p, dx) calls pb.dF(x,p,dx)
  • etc
BifurcationKit.BifurcationProblemType
struct BifurcationProblem{Tvf, Tu, Tp, Tl<:Lens, Tplot, Trec} <: BifurcationKit.AbstractAllJetBifProblem

Structure to hold the bifurcation problem.

Fields

  • VF::Any: Vector field, typically a BifFunction

  • u0::Any: Initial guess

  • params::Any: parameters

  • lens::Lens: Typically a Setfield.Lens. It specifies which parameter axis among params is used for continuation. For example, if par = (α = 1.0, β = 1), we can perform continuation w.r.t. α by using lens = (@lens _.α). If you have an array par = [ 1.0, 2.0] and want to perform continuation w.r.t. the first variable, you can use lens = (@lens _[1]). For more information, we refer to SetField.jl.

  • plotSolution::Any: user function to plot solutions during continuation. Signature: plot_solution(x, p; kwargs...) for Plot.jl and plot_solution(ax, x, p; kwargs...) for the Makie package(s).

  • recordFromSolution::Any: record_from_solution = (x, p) -> norm(x) function used record a few indicators about the solution. It could be norm or (x, p) -> x[1]. This is also useful when saving several huge vectors is not possible for memory reasons (for example on GPU). This function can return pretty much everything but you should keep it small. For example, you can do (x, p) -> (x1 = x[1], x2 = x[2], nrm = norm(x)) or simply (x, p) -> (sum(x), 1). This will be stored in contres.branch where contres::ContResult is the continuation curve of the bifurcation problem. Finally, the first component is used for plotting in the continuation curve.

Methods

  • re_make(pb; kwargs...) modify a bifurcation problem
  • getu0(pb) calls pb.u0
  • getparams(pb) calls pb.params
  • getlens(pb) calls pb.lens
  • getparam(pb) calls get(pb.params, pb.lens)
  • setparam(pb, p0) calls set(pb.params, pb.lens, p0)
  • record_from_solution(pb) calls pb.recordFromSolution
  • plot_solution(pb) calls pb.plotSolution
  • is_symmetric(pb) calls is_symmetric(pb.prob)

Constructors

  • BifurcationProblem(F, u0, params, lens) all derivatives are computed using ForwardDiff.
  • BifurcationProblem(F, u0, params, lens; J, Jᵗ, d2F, d3F, kwargs...) and kwargs are the fields above. You can pass your own jacobian with J (see BifFunction for description of the jacobian function) and jacobian adjoint with Jᵗ. For example, this can be used to provide finite differences based jacobian using BifurcationKit.finiteDifferences.
BifurcationKit.DeflationOperatorType
struct DeflationOperator{Tp<:Real, Tdot, T<:Real, vectype} <: BifurcationKit.AbstractDeflationFactor

Structure for defining a custom distance.

This operator allows to handle the following situation. Assume you want to solve F(x)=0 with a Newton algorithm but you want to avoid the process to return some already known solutions $roots_i$. The deflation operator penalizes these roots. You can create a DeflationOperator to define a scalar function M(u) used to find, with Newton iterations, the zeros of the following function $F(u) \cdot Π_i(\|u - root_i\|^{-2p} + \alpha) := F(u) \cdot M(u)$ where $\|u\|^2 = dot(u, u)$. The fields of the struct DeflationOperator are as follows:

  • power::Real: power p. You can use an Int for example

  • dot::Any: function, this function has to be bilinear and symmetric for the linear solver to work well

  • α::Real: shift

  • roots::Vector: roots

  • tmp::Any

  • autodiff::Bool

  • δ::Real

Given defOp::DeflationOperator, one can access its roots via defOp[n] as a shortcut for defOp.roots[n]. Note that you can also use defOp[end].

Also, one can add (resp. remove) a new root by using push!(defOp, newroot) (resp. pop!(defOp)). Finally length(defOp) is a shortcut for length(defOp.roots)

Constructors

  • DeflationOperator(p::Real, α::Real, roots::Vector{vectype}; autodiff = false)
  • DeflationOperator(p::Real, dt, α::Real, roots::Vector{vectype}; autodiff = false)
  • DeflationOperator(p::Real, α::Real, roots::Vector{vectype}, v::vectype; autodiff = false)

The option autodiff triggers the use of automatic differentiation for the computation of the gradient of the scalar function M. This works only on AbstractVector for now.

Custom distance

You are asked to pass a scalar product like dot to build a DeflationOperator. However, in some cases, you may want to pass a custom distance dist(u, v). You can do this using

`DeflationOperator(p, CustomDist(dist), α, roots)`

Note that passing CustomDist(dist, true) will trigger the use of automatic differentiation for the gradient of M.

BifurcationKit.DeflatedProblemType
pb = DeflatedProblem(prob, M::DeflationOperator, jactype)

Create a DeflatedProblem.

This creates a deflated functional (problem) $M(u) \cdot F(u) = 0$ where M is a DeflationOperator which encodes the penalization term. prob is an AbstractBifurcationProblem which encodes the functional. It is not meant not be used directly albeit by advanced users.

Periodic orbits

BifurcationKit.PeriodicOrbitTrapProblemType

This composite type implements Finite Differences based on a Trapezoidal rule (Order 2 in time) to locate periodic orbits. More details (maths, notations, linear systems) can be found here.

Fields

  • prob a bifurcation problem
  • M::Int number of time slices
  • ϕ used to set a section for the phase constraint equation, of size N*M
  • used in the section for the phase constraint equation, of size N*M
  • linsolver: = DefaultLS() linear solver for each time slice, i.e. to solve J⋅sol = rhs. This is only needed for the computation of the Floquet multipliers in a full matrix-free setting.
  • ongpu::Bool whether the computation takes place on the gpu (Experimental)
  • massmatrix a mass matrix. You can pass for example a sparse matrix. Default: identity matrix.
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).

The scheme is as follows. We first consider a partition of $[0,1]$ given by $0<s_0<\cdots<s_m=1$ and one looks for T = x[end] such that

$M_a\cdot\left(x_{i} - x_{i-1}\right) - \frac{T\cdot h_i}{2} \left(F(x_{i}) + F(x_{i-1})\right) = 0,\ i=1,\cdots,m-1$

with $u_{0} := u_{m-1}$ and the periodicity condition $u_{m} - u_{1} = 0$ and

where $h_1 = s_i-s_{i-1}$. $M_a$ is a mass matrix. Finally, the phase of the periodic orbit is constrained by using a section (but you could use your own)

$\sum_i\langle x_{i} - x_{\pi,i}, \phi_{i}\rangle=0.$

Constructors

The structure can be created by calling PeriodicOrbitTrapProblem(;kwargs...). For example, you can declare such a problem without vector field by doing

PeriodicOrbitTrapProblem(M = 100)

Orbit guess

You will see below that you can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be a vector of size M * N + 1 where N is the number of unknowns in the state space and orbitguess[M*N+1] is an estimate of the period $T$ of the limit cycle. More precisely, using the above notations, orbitguess must be $orbitguess = [x_{1},x_{2},\cdots,x_{M}, T]$.

Note that you can generate this guess from a function solution using generateSolution.

Functional

A functional, hereby called G, encodes this problem. The following methods are available

  • pb(orbitguess, p) evaluates the functional G on orbitguess
  • pb(orbitguess, p, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du
  • pb(Val(:JacFullSparse), orbitguess, p) return the sparse matrix of the jacobian dG(orbitguess) at orbitguess without the constraints. It is called A_γ in the docs.
  • pb(Val(:JacFullSparseInplace), J, orbitguess, p). Same as pb(Val(:JacFullSparse), orbitguess, p) but overwrites J inplace. Note that the sparsity pattern must be the same independently of the values of the parameters or of orbitguess. In this case, this is significantly faster than pb(Val(:JacFullSparse), orbitguess, p).
  • pb(Val(:JacCyclicSparse), orbitguess, p) return the sparse cyclic matrix Jc (see the docs) of the jacobian dG(orbitguess) at orbitguess
  • pb(Val(:BlockDiagSparse), orbitguess, p) return the diagonal of the sparse matrix of the jacobian dG(orbitguess) at orbitguess. This allows to design Jacobi preconditioner. Use blockdiag.

Jacobian

Specify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.

  • For jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.
  • For jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.
  • For jacobian = :DenseAD, evaluate the jacobian using ForwardDiff
  • For jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.
  • For jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.
  • For jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.
  • For jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.
GPU call

For these methods to work on the GPU, for example with CuArrays in mode allowscalar(false), we face the issue that the function extract_period_fdtrap won't be well defined because it is a scalar operation. Note that you must pass the option ongpu = true for the functional to be evaluated efficiently on the gpu.

BifurcationKit.PeriodicOrbitOCollProblemType
pb = PeriodicOrbitOCollProblem(kwargs...)

This composite type implements an orthogonal collocation (at Gauss points) method of piecewise polynomials to locate periodic orbits. More details (maths, notations, linear systems) can be found here.

Arguments

  • prob a bifurcation problem
  • ϕ::AbstractVector used to set a section for the phase constraint equation
  • xπ::AbstractVector used in the section for the phase constraint equation
  • N::Int dimension of the state space
  • mesh_cache::MeshCollocationCache cache for collocation. See docs of MeshCollocationCache
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian = AutoDiffDenseAnalytical() describes the type of jacobian used in Newton iterations. Can only be AutoDiffDense(), AutoDiffDenseAnalytical(), FullSparse(), FullSparseInplace().
  • meshadapt::Bool = false whether to use mesh adaptation
  • verbose_mesh_adapt::Bool = true verbose mesh adaptation information
  • K::Float64 = 500 parameter for mesh adaptation, control new mesh step size

Methods

Here are some useful methods you can apply to pb

  • length(pb) gives the total number of unknowns
  • size(pb) returns the triplet (N, m, Ntst)
  • getmesh(pb) returns the mesh 0 = τ0 < ... < τNtst+1 = 1. This is useful because this mesh is born to vary during automatic mesh adaptation
  • get_mesh_coll(pb) returns the (static) mesh 0 = σ0 < ... < σm+1 = 1
  • get_times(pb) returns the vector of times (length 1 + m * Ntst) at the which the collocation is applied.
  • generate_solution(pb, orbit, period) generate a guess from a function t -> orbit(t) which approximates the periodic orbit.
  • POSolution(pb, x) return a function interpolating the solution x using a piecewise polynomials function

Orbit guess

You can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be of size 1 + N * (1 + m * Ntst) where N is the number of unknowns in the state space and orbitguess[end] is an estimate of the period $T$ of the limit cycle.

Constructors

  • PeriodicOrbitOCollProblem(Ntst::Int, m::Int; kwargs) creates an empty functional with Ntst and m.

Note that you can generate this guess from a function using generate_solution.

Functional

A functional, hereby called G, encodes this problem. The following methods are available

  • pb(orbitguess, p) evaluates the functional G on orbitguess
BifurcationKit.ShootingProblemType
pb = ShootingProblem(flow::Flow, ds, section; parallel = false)

Create a problem to implement the Standard Simple / Parallel Multiple Standard Shooting method to locate periodic orbits. More details (maths, notations, linear systems) can be found here. The arguments are as follows

  • flow::Flow: implements the flow of the Cauchy problem though the structure Flow.
  • ds: vector of time differences for each shooting. Its length is written M. If M == 1, then the simple shooting is implemented and the multiple one otherwise.
  • section: implements a phase condition. The evaluation section(x, T) must return a scalar number where x is a guess for one point on the periodic orbit and T is the period of the guess. Also, the method section(x, T, dx, dT) must be available and which returns the differential of section. The type of x depends on what is passed to the newton solver. See SectionSS for a type of section defined as a hyperplane.
  • parallel whether the shooting is computed in parallel (threading). Available through the use of Flows defined by EnsembleProblem (this is automatically set up for you).
  • par parameters of the model
  • lens parameter axis
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).

A functional, hereby called G, encodes the shooting problem. For example, the following methods are available:

  • pb(orbitguess, par) evaluates the functional G on orbitguess
  • pb(orbitguess, par, du; δ = 1e-9) evaluates the jacobian dG(orbitguess)⋅du functional at orbitguess on du. The optional argument δ is used to compute a finite difference approximation of the derivative of the section.
  • pb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.
  • pb(Val(:JacobianMatrix), x, par) same as above but out-of-place.

You can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N + 1 where N is the number of unknowns of the state space and orbitguess[M * N + 1] is an estimate of the period T of the limit cycle. This form of guess is convenient for the use of the linear solvers in IterativeSolvers.jl (for example) which only accept AbstractVectors. Another accepted guess is of the form BorderedArray(guess, T) where guess[i] is the state of the orbit at the ith time slice. This last form allows for non-vector state space which can be convenient for 2d problems for example, use GMRESKrylovKit for the linear solver in this case.

Note that you can generate this guess from a function solution using generate_solution.

Jacobian

  • jacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG
    • For MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.
    • For FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.
    • For AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
    • For FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.

Simplified constructors

  • The first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points:
pb = ShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)
  • A convenient way to build the functional is to use:
pb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, centers::AbstractVector; kwargs...)

where prob is an ODEProblem (resp. EnsembleProblem) which is used to create a flow using the ODE solver alg (for example Tsit5()). centers is list of M points close to the periodic orbit, they will be used to build a constraint for the phase. parallel = false is an option to use Parallel simulations (Threading) to simulate the multiple trajectories in the case of multiple shooting. This is efficient when the trajectories are relatively long to compute. Finally, the arguments kwargs are passed to the ODE solver defining the flow. Look at DifferentialEquations.jl for more information. Note that, in this case, the derivative of the flow is computed internally using Finite Differences.

  • Another way to create a Shooting problem with more options is the following where in particular, one can provide its own scalar constraint section(x)::Number for the phase:
pb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; parallel = false, kwargs...)

or

pb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, ds, section; parallel = false, kwargs...)
  • The next way is an elaboration of the previous one
pb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, M::Int, section; parallel = false, kwargs...)

or

pb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, ds, section; parallel = false, kwargs...)

where we supply now two ODEProblems. The first one prob1, is used to define the flow associated to F while the second one is a problem associated to the derivative of the flow. Hence, prob2 must implement the following vector field $\tilde F(x,y,p) = (F(x,p), dF(x,p)\cdot y)$.

BifurcationKit.PoincareShootingProblemType

pb = PoincareShootingProblem(flow::Flow, M, sections; δ = 1e-8, interp_points = 50, parallel = false)

This composite type implements the Poincaré Shooting method to locate periodic orbits by relying on Poincaré return maps. More details (maths, notations, linear systems) can be found here. The arguments are as follows

  • flow::Flow: implements the flow of the Cauchy problem though the structure Flow.
  • M: the number of Poincaré sections. If M == 1, then the simple shooting is implemented and the multiple one otherwise.
  • sections: function or callable struct which implements a Poincaré section condition. The evaluation sections(x) must return a scalar number when M == 1. Otherwise, one must implement a function section(out, x) which populates out with the M sections. See SectionPS for type of section defined as a hyperplane.
  • δ = 1e-8 used to compute the jacobian of the functional by finite differences. If set to 0, an analytical expression of the jacobian is used instead.
  • interp_points = 50 number of interpolation point used to define the callback (to compute the hitting of the hyperplane section)
  • parallel = false whether the shooting are computed in parallel (threading). Only available through the use of Flows defined by EnsembleProblem.
  • par parameters of the model
  • lens parameter axis
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).

Jacobian

  • jacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG
    • For MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.
    • For FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.
    • For AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
    • For FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.

Simplified constructors

  • The first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points pb = PoincareShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)

  • A convenient way is to create a functional is

pb = PoincareShootingProblem(prob::ODEProblem, alg, section; kwargs...)

for simple shooting or

pb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; kwargs...)

for multiple shooting . Here prob is an Union{ODEProblem, EnsembleProblem} which is used to create a flow using the ODE solver alg (for example Tsit5()). Finally, the arguments kwargs are passed to the ODE solver defining the flow. We refer to DifferentialEquations.jl for more information.

  • Another convenient call is

pb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, normals::AbstractVector, centers::AbstractVector; δ = 1e-8, kwargs...)

where normals (resp. centers) is a list of normals (resp. centers) which defines a list of hyperplanes $\Sigma_i$. These hyperplanes are used to define partial Poincaré return maps.

Computing the functionals

A functional, hereby called G encodes this shooting problem. You can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N where N is the number of unknowns in the state space and M is the number of Poincaré maps. Another accepted guess is such that guess[i] is the state of the orbit on the ith section. This last form allows for non-vector state space which can be convenient for 2d problems for example.

Note that you can generate this guess from a function solution using generate_solution.

  • pb(orbitguess, par) evaluates the functional G on orbitguess
  • pb(orbitguess, par, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du
  • pb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.
  • pb(Val(:JacobianMatrix), x, par) same as above but out-of-place.
Tip

You can use the function getperiod(pb, sol, par) to get the period of the solution sol for the problem with parameters par.

Waves

BifurcationKit.TWProblemType

TWProblem(prob, ∂::Tuple, u₀; DAE = 0, jacobian::Symbol = :AutoDiff)

This composite type implements a functional for freezing symmetries in order, for example, to compute travelling waves (TW). Note that you can freeze many symmetries, not just one, by passing many Lie generators. When you call pb(x, par), it computes:

                ┌                   ┐
+-0.5
  • get_solx(br, k) returns the k-th solution on the branch
  • get_solp(br, k) returns the parameter value associated with k-th solution on the branch
  • getparams(br) Parameters passed to continuation and used in the equation F(x, par) = 0.
  • setparam(br, p0) set the parameter value p0 according to ::Lens for the parameters of the problem br.prob
  • getlens(br) get the lens used for the computation of the branch
  • continuation(br, ind) performs automatic branch switching (aBS) from ind-th bifurcation point. Typically branching from equilibrium to equilibrium, or periodic orbit to periodic orbit.
  • continuation(br, ind, lens2) performs two parameters (getLens(br), lens2) continuation of the ind-th bifurcation point.
  • continuation(br, ind, probPO::AbstractPeriodicOrbitProblem) performs aBS from ind-th bifurcation point (which must be a Hopf bifurcation point) to branch of periodic orbits.

Problems

BifurcationKit.BifFunctionType
struct BifFunction{Tf, Tdf, Tdfad, Tj, Tjad, Td2f, Td2fc, Td3f, Td3fc, Tsym, Tδ} <: BifurcationKit.AbstractBifurcationFunction

Structure to hold the vector field and its derivatives. It should rarely be called directly. Also, in essence, it is very close to SciMLBase.ODEFunction.

Fields

  • F::Any: Vector field. Function of type out-of-place result = f(x, p) or inplace f(result, x, p). For type stability, the types of x and result should match

  • dF::Any: Differential of F with respect to x, signature dF(x,p,dx)

  • dFad::Any: Adjoint of the Differential of F with respect to x, signature dFad(x,p,dx)

  • J::Any: Jacobian of F at (x, p). It can assume three forms. 1. Either J is a function and J(x, p) returns a ::AbstractMatrix. In this case, the default arguments of contparams::ContinuationPar will make continuation work. 2. Or J is a function and J(x, p) returns a function taking one argument dx and returning dr of the same type as dx. In our notation, dr = J * dx. In this case, the default parameters of contparams::ContinuationPar will not work and you have to use a Matrix Free linear solver, for example GMRESIterativeSolvers, 3. Or J is a function and J(x, p) returns a variable j which can assume any type. Then, you must implement a linear solver ls as a composite type, subtype of AbstractLinearSolver which is called like ls(j, rhs) and which returns the solution of the jacobian linear system. See for example examples/SH2d-fronts-cuda.jl. This linear solver is passed to NewtonPar(linsolver = ls) which itself passed to ContinuationPar. Similarly, you have to implement an eigensolver eig as a composite type, subtype of AbstractEigenSolver.

  • Jᵗ::Any: jacobian adjoint, it should be implemented in an efficient manner. For matrix-free methods, transpose is not readily available and the user must provide a dedicated method. In the case of sparse based jacobian, Jᵗ should not be passed as it is computed internally more efficiently, i.e. it avoids recomputing the jacobian as it would be if you pass Jᵗ = (x, p) -> transpose(dF(x, p)).

  • d2F::Any: Second Differential of F with respect to x, signature d2F(x,p,dx1,dx2)

  • d3F::Any: Third Differential of F with respect to x, signature d3F(x,p,dx1,dx2,dx3)

  • d2Fc::Any: [internal] Second Differential of F with respect to x which accept complex vectors dxi

  • d3Fc::Any: [internal] Third Differential of F with respect to x which accept complex vectors dxi

  • isSymmetric::Any: Whether the jacobian is auto-adjoint.

  • δ::Any: used internally to compute derivatives (with finite differences), for example for normal form computation and codim 2 continuation.

  • inplace::Bool: optionally sets whether the function is inplace or not

Methods

  • residual(pb::BifFunction, x, p) calls pb.F(x,p)
  • jacobian(pb::BifFunction, x, p) calls pb.J(x, p)
  • dF(pb::BifFunction, x, p, dx) calls pb.dF(x,p,dx)
  • etc
BifurcationKit.BifurcationProblemType
struct BifurcationProblem{Tvf, Tu, Tp, Tl<:Lens, Tplot, Trec} <: BifurcationKit.AbstractAllJetBifProblem

Structure to hold the bifurcation problem.

Fields

  • VF::Any: Vector field, typically a BifFunction

  • u0::Any: Initial guess

  • params::Any: parameters

  • lens::Lens: Typically a Setfield.Lens. It specifies which parameter axis among params is used for continuation. For example, if par = (α = 1.0, β = 1), we can perform continuation w.r.t. α by using lens = (@lens _.α). If you have an array par = [ 1.0, 2.0] and want to perform continuation w.r.t. the first variable, you can use lens = (@lens _[1]). For more information, we refer to SetField.jl.

  • plotSolution::Any: user function to plot solutions during continuation. Signature: plot_solution(x, p; kwargs...) for Plot.jl and plot_solution(ax, x, p; kwargs...) for the Makie package(s).

  • recordFromSolution::Any: record_from_solution = (x, p) -> norm(x) function used record a few indicators about the solution. It could be norm or (x, p) -> x[1]. This is also useful when saving several huge vectors is not possible for memory reasons (for example on GPU). This function can return pretty much everything but you should keep it small. For example, you can do (x, p) -> (x1 = x[1], x2 = x[2], nrm = norm(x)) or simply (x, p) -> (sum(x), 1). This will be stored in contres.branch where contres::ContResult is the continuation curve of the bifurcation problem. Finally, the first component is used for plotting in the continuation curve.

Methods

  • re_make(pb; kwargs...) modify a bifurcation problem
  • getu0(pb) calls pb.u0
  • getparams(pb) calls pb.params
  • getlens(pb) calls pb.lens
  • getparam(pb) calls get(pb.params, pb.lens)
  • setparam(pb, p0) calls set(pb.params, pb.lens, p0)
  • record_from_solution(pb) calls pb.recordFromSolution
  • plot_solution(pb) calls pb.plotSolution
  • is_symmetric(pb) calls is_symmetric(pb.prob)

Constructors

  • BifurcationProblem(F, u0, params, lens) all derivatives are computed using ForwardDiff.
  • BifurcationProblem(F, u0, params, lens; J, Jᵗ, d2F, d3F, kwargs...) and kwargs are the fields above. You can pass your own jacobian with J (see BifFunction for description of the jacobian function) and jacobian adjoint with Jᵗ. For example, this can be used to provide finite differences based jacobian using BifurcationKit.finiteDifferences.
BifurcationKit.DeflationOperatorType
struct DeflationOperator{Tp<:Real, Tdot, T<:Real, vectype} <: BifurcationKit.AbstractDeflationFactor

Structure for defining a custom distance.

This operator allows to handle the following situation. Assume you want to solve F(x)=0 with a Newton algorithm but you want to avoid the process to return some already known solutions $roots_i$. The deflation operator penalizes these roots. You can create a DeflationOperator to define a scalar function M(u) used to find, with Newton iterations, the zeros of the following function $F(u) \cdot Π_i(\|u - root_i\|^{-2p} + \alpha) := F(u) \cdot M(u)$ where $\|u\|^2 = dot(u, u)$. The fields of the struct DeflationOperator are as follows:

  • power::Real: power p. You can use an Int for example

  • dot::Any: function, this function has to be bilinear and symmetric for the linear solver to work well

  • α::Real: shift

  • roots::Vector: roots

  • tmp::Any

  • autodiff::Bool

  • δ::Real

Given defOp::DeflationOperator, one can access its roots via defOp[n] as a shortcut for defOp.roots[n]. Note that you can also use defOp[end].

Also, one can add (resp. remove) a new root by using push!(defOp, newroot) (resp. pop!(defOp)). Finally length(defOp) is a shortcut for length(defOp.roots)

Constructors

  • DeflationOperator(p::Real, α::Real, roots::Vector{vectype}; autodiff = false)
  • DeflationOperator(p::Real, dt, α::Real, roots::Vector{vectype}; autodiff = false)
  • DeflationOperator(p::Real, α::Real, roots::Vector{vectype}, v::vectype; autodiff = false)

The option autodiff triggers the use of automatic differentiation for the computation of the gradient of the scalar function M. This works only on AbstractVector for now.

Custom distance

You are asked to pass a scalar product like dot to build a DeflationOperator. However, in some cases, you may want to pass a custom distance dist(u, v). You can do this using

`DeflationOperator(p, CustomDist(dist), α, roots)`

Note that passing CustomDist(dist, true) will trigger the use of automatic differentiation for the gradient of M.

BifurcationKit.DeflatedProblemType
pb = DeflatedProblem(prob, M::DeflationOperator, jactype)

Create a DeflatedProblem.

This creates a deflated functional (problem) $M(u) \cdot F(u) = 0$ where M is a DeflationOperator which encodes the penalization term. prob is an AbstractBifurcationProblem which encodes the functional. It is not meant not be used directly albeit by advanced users.

Periodic orbits

BifurcationKit.PeriodicOrbitTrapProblemType

This composite type implements Finite Differences based on a Trapezoidal rule (Order 2 in time) to locate periodic orbits. More details (maths, notations, linear systems) can be found here.

Fields

  • prob a bifurcation problem
  • M::Int number of time slices
  • ϕ used to set a section for the phase constraint equation, of size N*M
  • used in the section for the phase constraint equation, of size N*M
  • linsolver: = DefaultLS() linear solver for each time slice, i.e. to solve J⋅sol = rhs. This is only needed for the computation of the Floquet multipliers in a full matrix-free setting.
  • ongpu::Bool whether the computation takes place on the gpu (Experimental)
  • massmatrix a mass matrix. You can pass for example a sparse matrix. Default: identity matrix.
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).

The scheme is as follows. We first consider a partition of $[0,1]$ given by $0<s_0<\cdots<s_m=1$ and one looks for T = x[end] such that

$M_a\cdot\left(x_{i} - x_{i-1}\right) - \frac{T\cdot h_i}{2} \left(F(x_{i}) + F(x_{i-1})\right) = 0,\ i=1,\cdots,m-1$

with $u_{0} := u_{m-1}$ and the periodicity condition $u_{m} - u_{1} = 0$ and

where $h_1 = s_i-s_{i-1}$. $M_a$ is a mass matrix. Finally, the phase of the periodic orbit is constrained by using a section (but you could use your own)

$\sum_i\langle x_{i} - x_{\pi,i}, \phi_{i}\rangle=0.$

Constructors

The structure can be created by calling PeriodicOrbitTrapProblem(;kwargs...). For example, you can declare such a problem without vector field by doing

PeriodicOrbitTrapProblem(M = 100)

Orbit guess

You will see below that you can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be a vector of size M * N + 1 where N is the number of unknowns in the state space and orbitguess[M*N+1] is an estimate of the period $T$ of the limit cycle. More precisely, using the above notations, orbitguess must be $orbitguess = [x_{1},x_{2},\cdots,x_{M}, T]$.

Note that you can generate this guess from a function solution using generateSolution.

Functional

A functional, hereby called G, encodes this problem. The following methods are available

  • pb(orbitguess, p) evaluates the functional G on orbitguess
  • pb(orbitguess, p, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du
  • pb(Val(:JacFullSparse), orbitguess, p) return the sparse matrix of the jacobian dG(orbitguess) at orbitguess without the constraints. It is called A_γ in the docs.
  • pb(Val(:JacFullSparseInplace), J, orbitguess, p). Same as pb(Val(:JacFullSparse), orbitguess, p) but overwrites J inplace. Note that the sparsity pattern must be the same independently of the values of the parameters or of orbitguess. In this case, this is significantly faster than pb(Val(:JacFullSparse), orbitguess, p).
  • pb(Val(:JacCyclicSparse), orbitguess, p) return the sparse cyclic matrix Jc (see the docs) of the jacobian dG(orbitguess) at orbitguess
  • pb(Val(:BlockDiagSparse), orbitguess, p) return the diagonal of the sparse matrix of the jacobian dG(orbitguess) at orbitguess. This allows to design Jacobi preconditioner. Use blockdiag.

Jacobian

Specify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.

  • For jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.
  • For jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.
  • For jacobian = :DenseAD, evaluate the jacobian using ForwardDiff
  • For jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.
  • For jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.
  • For jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.
  • For jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.
GPU call

For these methods to work on the GPU, for example with CuArrays in mode allowscalar(false), we face the issue that the function extract_period_fdtrap won't be well defined because it is a scalar operation. Note that you must pass the option ongpu = true for the functional to be evaluated efficiently on the gpu.

BifurcationKit.PeriodicOrbitOCollProblemType
pb = PeriodicOrbitOCollProblem(kwargs...)

This composite type implements an orthogonal collocation (at Gauss points) method of piecewise polynomials to locate periodic orbits. More details (maths, notations, linear systems) can be found here.

Arguments

  • prob a bifurcation problem
  • ϕ::AbstractVector used to set a section for the phase constraint equation
  • xπ::AbstractVector used in the section for the phase constraint equation
  • N::Int dimension of the state space
  • mesh_cache::MeshCollocationCache cache for collocation. See docs of MeshCollocationCache
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian = DenseAnalytical() describes the type of jacobian used in Newton iterations. Can only be AutoDiffDense(), DenseAnalytical(), FullSparse(), FullSparseInplace().
  • meshadapt::Bool = false whether to use mesh adaptation
  • verbose_mesh_adapt::Bool = true verbose mesh adaptation information
  • K::Float64 = 500 parameter for mesh adaptation, control new mesh step size. More precisely, we set max(hᵢ) / min(hᵢ) ≤ K if hᵢ denotes the time steps.

Methods

Here are some useful methods you can apply to pb

  • length(pb) gives the total number of unknowns
  • size(pb) returns the triplet (N, m, Ntst)
  • getmesh(pb) returns the mesh 0 = τ0 < ... < τNtst+1 = 1. This is useful because this mesh is born to vary during automatic mesh adaptation
  • get_mesh_coll(pb) returns the (static) mesh 0 = σ0 < ... < σm+1 = 1
  • get_times(pb) returns the vector of times (length 1 + m * Ntst) at the which the collocation is applied.
  • generate_solution(pb, orbit, period) generate a guess from a function t -> orbit(t) which approximates the periodic orbit.
  • POSolution(pb, x) return a function interpolating the solution x using a piecewise polynomials function

Orbit guess

You can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be of size 1 + N * (1 + m * Ntst) where N is the number of unknowns in the state space and orbitguess[end] is an estimate of the period $T$ of the limit cycle.

Constructors

  • PeriodicOrbitOCollProblem(Ntst::Int, m::Int; kwargs) creates an empty functional with Ntst and m.

Note that you can generate this guess from a function using generate_solution.

Functional

A functional, hereby called G, encodes this problem. The following methods are available

  • pb(orbitguess, p) evaluates the functional G on orbitguess
BifurcationKit.ShootingProblemType
pb = ShootingProblem(flow::Flow, ds, section; parallel = false)

Create a problem to implement the Standard Simple / Parallel Multiple Standard Shooting method to locate periodic orbits. More details (maths, notations, linear systems) can be found here. The arguments are as follows

  • flow::Flow: implements the flow of the Cauchy problem though the structure Flow.
  • ds: vector of time differences for each shooting. Its length is written M. If M == 1, then the simple shooting is implemented and the multiple one otherwise.
  • section: implements a phase condition. The evaluation section(x, T) must return a scalar number where x is a guess for one point on the periodic orbit and T is the period of the guess. Also, the method section(x, T, dx, dT) must be available and which returns the differential of section. The type of x depends on what is passed to the newton solver. See SectionSS for a type of section defined as a hyperplane.
  • parallel whether the shooting is computed in parallel (threading). Available through the use of Flows defined by EnsembleProblem (this is automatically set up for you).
  • par parameters of the model
  • lens parameter axis
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).

A functional, hereby called G, encodes the shooting problem. For example, the following methods are available:

  • pb(orbitguess, par) evaluates the functional G on orbitguess
  • pb(orbitguess, par, du) evaluates the jacobian dG(orbitguess)⋅du functional at orbitguess on du.
  • pb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.
  • pb(Val(:JacobianMatrix), x, par) same as above but out-of-place.

You can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N + 1 where N is the number of unknowns of the state space and orbitguess[M * N + 1] is an estimate of the period T of the limit cycle. This form of guess is convenient for the use of the linear solvers in IterativeSolvers.jl (for example) which only accept AbstractVectors. Another accepted guess is of the form BorderedArray(guess, T) where guess[i] is the state of the orbit at the ith time slice. This last form allows for non-vector state space which can be convenient for 2d problems for example, use GMRESKrylovKit for the linear solver in this case.

Note that you can generate this guess from a function solution using generate_solution.

Jacobian

  • jacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG
    • For MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.
    • For FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.
    • For AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
    • For FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.

Simplified constructors

  • The first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points:
pb = ShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)
  • A convenient way to build the functional is to use:
pb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, centers::AbstractVector; kwargs...)

where prob is an ODEProblem (resp. EnsembleProblem) which is used to create a flow using the ODE solver alg (for example Tsit5()). centers is list of M points close to the periodic orbit, they will be used to build a constraint for the phase. parallel = false is an option to use Parallel simulations (Threading) to simulate the multiple trajectories in the case of multiple shooting. This is efficient when the trajectories are relatively long to compute. Finally, the arguments kwargs are passed to the ODE solver defining the flow. Look at DifferentialEquations.jl for more information. Note that, in this case, the derivative of the flow is computed internally using Finite Differences.

  • Another way to create a Shooting problem with more options is the following where in particular, one can provide its own scalar constraint section(x)::Number for the phase:
pb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; parallel = false, kwargs...)

or

pb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, ds, section; parallel = false, kwargs...)
  • The next way is an elaboration of the previous one
pb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, M::Int, section; parallel = false, kwargs...)

or

pb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, ds, section; parallel = false, kwargs...)

where we supply now two ODEProblems. The first one prob1, is used to define the flow associated to F while the second one is a problem associated to the derivative of the flow. Hence, prob2 must implement the following vector field $\tilde F(x,y,p) = (F(x,p), dF(x,p)\cdot y)$.

BifurcationKit.PoincareShootingProblemType

pb = PoincareShootingProblem(flow::Flow, M, sections; δ = 1e-8, interp_points = 50, parallel = false)

This composite type implements the Poincaré Shooting method to locate periodic orbits by relying on Poincaré return maps. More details (maths, notations, linear systems) can be found here. The arguments are as follows

  • flow::Flow: implements the flow of the Cauchy problem though the structure Flow.
  • M: the number of Poincaré sections. If M == 1, then the simple shooting is implemented and the multiple one otherwise.
  • sections: function or callable struct which implements a Poincaré section condition. The evaluation sections(x) must return a scalar number when M == 1. Otherwise, one must implement a function section(out, x) which populates out with the M sections. See SectionPS for type of section defined as a hyperplane.
  • δ = 1e-8 used to compute the jacobian of the functional by finite differences. If set to 0, an analytical expression of the jacobian is used instead.
  • interp_points = 50 number of interpolation point used to define the callback (to compute the hitting of the hyperplane section)
  • parallel = false whether the shooting are computed in parallel (threading). Only available through the use of Flows defined by EnsembleProblem.
  • par parameters of the model
  • lens parameter axis
  • update_section_every_step updates the section every update_section_every_step step during continuation
  • jacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).

Jacobian

  • jacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG
    • For MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.
    • For FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.
    • For AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
    • For FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.

Simplified constructors

  • The first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points pb = PoincareShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)

  • A convenient way is to create a functional is

pb = PoincareShootingProblem(prob::ODEProblem, alg, section; kwargs...)

for simple shooting or

pb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; kwargs...)

for multiple shooting . Here prob is an Union{ODEProblem, EnsembleProblem} which is used to create a flow using the ODE solver alg (for example Tsit5()). Finally, the arguments kwargs are passed to the ODE solver defining the flow. We refer to DifferentialEquations.jl for more information.

  • Another convenient call is

pb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, normals::AbstractVector, centers::AbstractVector; δ = 1e-8, kwargs...)

where normals (resp. centers) is a list of normals (resp. centers) which defines a list of hyperplanes $\Sigma_i$. These hyperplanes are used to define partial Poincaré return maps.

Computing the functionals

A functional, hereby called G encodes this shooting problem. You can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N where N is the number of unknowns in the state space and M is the number of Poincaré maps. Another accepted guess is such that guess[i] is the state of the orbit on the ith section. This last form allows for non-vector state space which can be convenient for 2d problems for example.

Note that you can generate this guess from a function solution using generate_solution.

  • pb(orbitguess, par) evaluates the functional G on orbitguess
  • pb(orbitguess, par, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du
  • pb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.
  • pb(Val(:JacobianMatrix), x, par) same as above but out-of-place.
Tip

You can use the function getperiod(pb, sol, par) to get the period of the solution sol for the problem with parameters par.

Waves

BifurcationKit.TWProblemType

TWProblem(prob, ∂::Tuple, u₀; DAE = 0, jacobian::Symbol = :AutoDiff)

This composite type implements a functional for freezing symmetries in order, for example, to compute travelling waves (TW). Note that you can freeze many symmetries, not just one, by passing many Lie generators. When you call pb(x, par), it computes:

                ┌                   ┐
                 │ f(x, par) - s⋅∂⋅x │
                 │   <x - u₀, ∂⋅u₀>  │
-                └                   ┘

Arguments

  • prob bifurcation problem with continuous symmetries
  • ∂::Tuple = (T1, T2, ⋯) tuple of Lie generators. In effect, each of these is an (differential) operator which can be specified as a (sparse) matrix or as an operator implementing LinearAlgebra.mul!.
  • u₀ reference solution

Additional Constructor(s)

pb = TWProblem(prob, ∂, u₀; kw...)

This simplified call handles the case where a single symmetry needs to be frozen.

Useful function

  • updatesection!(pb::TWProblem, u0) updates the reference solution of the problem using u0.
  • nb_constraints(::TWProblem) number of constraints (or Lie generators)

Newton

BifurcationKit.newtonFunction
    newton(prob::AbstractBifurcationProblem, options::NewtonPar; normN = norm, callback = (;x, fx, J, residual, step, itlinear, options, x0, residuals; kwargs...) -> true, kwargs...)

This is the Newton-Krylov Solver for F(x, p0) = 0 with Jacobian w.r.t. x written J(x, p0) and initial guess x0. The function normN allows to specify a norm for the convergence criteria. It is important to set the linear solver options.linsolver properly depending on your problem. This linear solver is used to solve $J(x, p_0)u = -F(x, p_0)$ in the Newton step. You can for example use linsolver = DefaultLS() which is the operator backslash: it works well for Sparse / Dense matrices. See Linear solvers (LS) for more informations.

Arguments:

  • prob a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.
  • options::NewtonPar variable holding the internal parameters used by the newton method
  • callback function passed by the user which is called at the end of each iteration. The default one is the following cb_default((x, fx, J, residual, step, itlinear, options, x0, residuals); k...) = true. Can be used to update a preconditionner for example. You can use for example cbMaxNorm to limit the residuals norms. If yo want to specify your own, the arguments passed to the callback are as follows
    • x current solution
    • fx current residual
    • J current jacobian
    • residual current norm of the residual
    • step current newton step
    • itlinear number of iterations to solve the linear system
    • options a copy of the argument options passed to newton
    • residuals the history of residuals
    • kwargs kwargs arguments, contain your initial guess x0
  • kwargs arguments passed to the callback. Useful when newton is called from continuation

Output:

Linear solver

Make sure that the linear solver (Matrix-Free...) corresponds to your jacobian (Matrix-Free vs. Matrix based).

newton(prob, defOp, options)
+                └                   ┘

Arguments

  • prob bifurcation problem with continuous symmetries
  • ∂::Tuple = (T1, T2, ⋯) tuple of Lie generators. In effect, each of these is an (differential) operator which can be specified as a (sparse) matrix or as an operator implementing LinearAlgebra.mul!.
  • u₀ reference solution

Additional Constructor(s)

pb = TWProblem(prob, ∂, u₀; kw...)

This simplified call handles the case where a single symmetry needs to be frozen.

Useful function

  • updatesection!(pb::TWProblem, u0) updates the reference solution of the problem using u0.
  • nb_constraints(::TWProblem) number of constraints (or Lie generators)

Newton

BifurcationKit.newtonFunction
    newton(prob::AbstractBifurcationProblem, options::NewtonPar; normN = norm, callback = (;x, fx, J, residual, step, itlinear, options, x0, residuals; kwargs...) -> true, kwargs...)

This is the Newton-Krylov Solver for F(x, p0) = 0 with Jacobian w.r.t. x written J(x, p0) and initial guess x0. The function normN allows to specify a norm for the convergence criteria. It is important to set the linear solver options.linsolver properly depending on your problem. This linear solver is used to solve $J(x, p_0)u = -F(x, p_0)$ in the Newton step. You can for example use linsolver = DefaultLS() which is the operator backslash: it works well for Sparse / Dense matrices. See Linear solvers (LS) for more informations.

Arguments:

  • prob a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.
  • options::NewtonPar variable holding the internal parameters used by the newton method
  • callback function passed by the user which is called at the end of each iteration. The default one is the following cb_default((x, fx, J, residual, step, itlinear, options, x0, residuals); k...) = true. Can be used to update a preconditionner for example. You can use for example cbMaxNorm to limit the residuals norms. If yo want to specify your own, the arguments passed to the callback are as follows
    • x current solution
    • fx current residual
    • J current jacobian
    • residual current norm of the residual
    • step current newton step
    • itlinear number of iterations to solve the linear system
    • options a copy of the argument options passed to newton
    • residuals the history of residuals
    • kwargs kwargs arguments, contain your initial guess x0
  • kwargs arguments passed to the callback. Useful when newton is called from continuation

Output:

Linear solver

Make sure that the linear solver (Matrix-Free...) corresponds to your jacobian (Matrix-Free vs. Matrix based).

newton(prob, defOp, options; ...)
 newton(prob, defOp, options, _linsolver; kwargs...)
 

This is the deflated version of the Krylov-Newton Solver for F(x, p0) = 0.

We refer to the regular newton for more information. It penalises the roots saved in defOp.roots. The other arguments are as for newton. See DeflationOperator for more information on defOp.

Arguments

Compared to newton, the only different arguments are

  • defOp::DeflationOperator deflation operator
  • linsolver linear solver used to invert the Jacobian of the deflated functional.
    • custom solver DeflatedProblemCustomLS() which requires solving two linear systems J⋅x = rhs.
    • For other linear solvers <: AbstractLinearSolver, a matrix free method is used for the deflated functional.
    • if passed Val(:autodiff), then ForwardDiff.jl is used to compute the jacobian Matrix of the deflated problem
    • if passed Val(:fullIterative), then a full matrix free method is used for the deflated problem.

This specific Newton-Krylov method first tries to converge to a solution sol0 close the guess x0. It then attempts to converge from the guess x1 while avoiding the previous converged solution close to sol0. This is very handy for branch switching. The method is based on a deflated Newton-Krylov solver.

newton(
     br,
@@ -30,7 +30,7 @@
 

This is the deflated Newton-Krylov Solver for computing a periodic orbit using a (Standard / Poincaré) Shooting method.

Arguments

Similar to newton except that prob is either a ShootingProblem or a PoincareShootingProblem.

Optional argument

  • jacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG
    • For MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.
    • For FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.
    • For AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
    • For FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.

Output:

newton(probPO, orbitguess, options; kwargs...)
 

This is the Krylov-Newton Solver for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.

Arguments:

  • prob a problem of type PeriodicOrbitTrapProblem encoding the functional G
  • orbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It should be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.
  • par parameters to be passed to the functional
  • options same as for the regular newton method

Specify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.

  • For jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.
  • For jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.
  • For jacobian = :DenseAD, evaluate the jacobian using ForwardDiff
  • For jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.
  • For jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.
  • For jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.
  • For jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.
newton(probPO, orbitguess, defOp, options; kwargs...)
 

This function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.

newton(probPO, orbitguess, options; kwargs...)
-

This is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.

Arguments

Similar to newton except that prob is a PeriodicOrbitOCollProblem.

  • prob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.
  • orbitguess a guess for the periodic orbit.
  • options same as for the regular newton method.

Optional argument

  • jacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG
    • For AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.
    • For AutoDiffDenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
newton(probPO, orbitguess, defOp, options; kwargs...)
+

This is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.

Arguments

Similar to newton except that prob is a PeriodicOrbitOCollProblem.

  • prob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.
  • orbitguess a guess for the periodic orbit.
  • options same as for the regular newton method.

Optional argument

  • jacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG
    • For AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.
    • For DenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
newton(probPO, orbitguess, defOp, options; kwargs...)
 

This function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.

Continuation

BifurcationKit.DotThetaType
struct DotTheta{Tdot, Ta}
  • dot::Any: dot product used in pseudo-arclength constraint

  • apply!::Any: Linear operator associated with dot product, i.e. dot(x, y) = <x, Ay>, where <,> is the standard dot product on R^N. You must provide an inplace function which evaluates A. For example x -> rmul!(x, 1/length(x)).

This parametric type allows to define a new dot product from the one saved in dt::dot. More precisely:

dt(u1, u2, p1::T, p2::T, theta::T) where {T <: Real}

computes, the weighted dot product $\langle (u_1,p_1), (u_2,p_2)\rangle_\theta = \theta \Re \langle u_1,u_2\rangle +(1-\theta)p_1p_2$ where $u_i\in\mathbb R^N$. The $\Re$ factor is put to ensure a real valued result despite possible complex valued arguments.

Info

This is used in the pseudo-arclength constraint with the dot product $\frac{1}{N} \langle u_1, u_2\rangle,\quad u_i\in\mathbb R^N$

BifurcationKit.continuationFunction
continuation(
     prob,
     alg,
@@ -39,7 +39,7 @@
     bothside,
     kwargs...
 )
-

Compute the continuation curve associated to the functional F which is stored in the bifurcation problem prob. General information is available in Continuation methods: introduction.

Arguments:

  • prob::AbstractBifurcationFunction a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.
  • alg continuation algorithm, for example Natural(), PALC(), Multiple(),.... See algos
  • contparams parameters for continuation. See ContinuationPar

Optional Arguments:

  • plot = false whether to plot the solution/branch/spectrum while computing the branch
  • bothside = true compute the branches on the two sides of p0, merge them and return it.
  • finalise_solution = (z, tau, step, contResult; kwargs...) -> true Function called at the end of each continuation step. Can be used to alter the continuation procedure (stop it by returning false), saving personal data, plotting... The notations are $z=(x, p)$ where x (resp. p) is the current solution (resp. parameter value), tau is the tangent at z, step is the index of the current continuation step and ContResult is the current branch. For advanced use, the current state::ContState of the continuation is passed in kwargs. Note that you can have a better control over the continuation procedure by using an iterator, see Iterator Interface.
  • verbosity::Int = 0 controls the amount of information printed during the continuation process. Must belong to {0,1,2,3}. In case contparams.newton_options.verbose = false, the following is valid (otherwise the newton iterations are shown). Each case prints more information than the previous one:
    • case 0: print nothing
    • case 1: print basic information about the continuation: used predictor, step size and parameter values
    • case 2: print newton iterations number, stability of solution, detected bifurcations / events
    • case 3: print information during bisection to locate bifurcations / events
  • normC = norm norm used in the Newton solves
  • filename to save the computed branch during continuation. The identifier .jld2 will be appended to this filename. This requires using JLD2.
  • callback_newton callback for newton iterations. See docs of newton. For example, it can be used to change preconditioners.
  • kind::AbstractContinuationKind [Internal] flag to describe continuation kind (equilibrium, codim 2, ...). Default = EquilibriumCont()

Output:

  • contres::ContResult composite type which contains the computed branch. See ContResult for more information.
Continuing the branch in the opposite direction

Just change the sign of ds in ContinuationPar.

continuation(
+

Compute the continuation curve associated to the functional F which is stored in the bifurcation problem prob. General information is available in Continuation methods: introduction.

Arguments:

  • prob::AbstractBifurcationFunction a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.
  • alg continuation algorithm, for example Natural(), PALC(), Multiple(),.... See algos
  • contparams::ContinuationPar parameters for continuation. See ContinuationPar

Optional Arguments:

  • plot = false whether to plot the solution/branch/spectrum while computing the branch
  • bothside = true compute the branches on the two sides of the initial parameter value p0, merge them and return it.
  • finalise_solution = (z, tau, step, contResult; kwargs...) -> true Function called at the end of each continuation step. Can be used to alter the continuation procedure (stop it by returning false), save personal data, plot... The notations are $z = BorderedArray(x, p)$ where x (resp. p) is the current solution (resp. parameter value), tau::BorderedArray is the tangent at z, step::Int is the index of the current continuation step and contResult is the current branch. For advanced use:
    • the current state::ContState of the continuation is passed in kwargs.
    • the switch bisection::Bool is passed whenever finalise_solution is called during bisection for locating bifurcation points / events. This allows to escape some personal code in this case.

Note that you can have a better control over the continuation procedure by using an iterator, see Iterator Interface.

  • verbosity::Int = 0 controls the amount of information printed during the continuation process. Must belong to {0,1,2,3}. In case contparams.newton_options.verbose = false, the following is valid (otherwise the newton iterations are shown). Each case prints more information than the previous one:
    • case 0: print nothing
    • case 1: print basic information about the continuation: used predictor, step size and parameter values
    • case 2: print newton iterations number, stability of solution, detected bifurcations / events
    • case 3: print information during bisection to locate bifurcations / events
  • normC = norm norm used in the Newton solves
  • filename to save the computed branch during continuation. The identifier .jld2 will be appended to this filename. This requires using JLD2.
  • callback_newton callback for newton iterations. See docs of newton. For example, it can be used to change the preconditioners.
  • kind::AbstractContinuationKind [Internal] flag to describe continuation kind (equilibrium, codim 2, ...). Default = EquilibriumCont()

Output:

  • contres::ContResult composite type which contains the computed branch. See ContResult for more information.
Continuing the branch in the opposite direction

Just change the sign of ds in ContinuationPar.

Debug mode

Use debug mode to access more irformation about the progression of the continuation run, like iterative solvers convergence, problem update, ...

continuation(
     prob,
     algdc,
     contParams;
@@ -52,7 +52,7 @@
     normC,
     kwcont...
 )
-

This function computes the set of curves of solutions γ(s) = (x(s), p(s)) to the equation F(x,p) = 0 based on the algorithm of deflated continuation as described in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. “The Computation of Disconnected Bifurcation Diagrams.” ArXiv:1603.00809 [Math], March 2, 2016. http://arxiv.org/abs/1603.00809.

Depending on the options in contParams, it can locate the bifurcation points on each branch. Note that you can specify different predictors using alg.

Arguments:

  • prob::AbstractBifurcationProblem bifurcation problem
  • alg::DefCont, deflated continuation algorithm, see DefCont
  • contParams parameters for continuation. See ContinuationPar for more information about the options

Optional Arguments:

  • plot = false whether to plot the solution while computing,
  • callback_newton callback for newton iterations. see docs for newton. Can be used to change preconditioners or affect the newton iterations. In the deflation part of the algorithm, when seeking for new branches, the callback is passed the keyword argument fromDeflatedNewton = true to tell the user can it is not in the continuation part (regular newton) of the algorithm,
  • verbosity::Int controls the amount of information printed during the continuation process. Must belong to {0,⋯,5},
  • normC = norm norm used in the Newton solves,
  • dot_palc = (x, y) -> dot(x, y) / length(x), dot product used to define the weighted dot product (resp. norm) $\|(x, p)\|^2_\theta$ in the constraint $N(x, p)$ (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...),

Outputs:

  • contres::DCResult composite type which contains the computed branches. See ContResult for more information,
continuation(br, ind_bif, lens2)
+

This function computes the set of curves of solutions γ(s) = (x(s), p(s)) to the equation F(x,p) = 0 based on the algorithm of deflated continuation as described in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. “The Computation of Disconnected Bifurcation Diagrams.” ArXiv:1603.00809 [Math], March 2, 2016. http://arxiv.org/abs/1603.00809.

Depending on the options in contParams, it can locate the bifurcation points on each branch. Note that you can specify different predictors using alg.

Arguments:

  • prob::AbstractBifurcationProblem bifurcation problem
  • alg::DefCont, deflated continuation algorithm, see DefCont
  • contParams parameters for continuation. See ContinuationPar for more information about the options

Optional Arguments:

  • plot = false whether to plot the solution while computing,
  • callback_newton callback for newton iterations. see docs for newton. Can be used to change preconditioners or affect the newton iterations. In the deflation part of the algorithm, when seeking for new branches, the callback is passed the keyword argument fromDeflatedNewton = true to tell the user can it is not in the continuation part (regular newton) of the algorithm,
  • verbosity::Int controls the amount of information printed during the continuation process. Must belong to {0,⋯,5},
  • normC = norm norm used in the Newton solves,
  • dot_palc = (x, y) -> dot(x, y) / length(x), dot product used to define the weighted dot product (resp. norm) $\|(x, p)\|^2_\theta$ in the constraint $N(x, p)$ (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...),

Outputs:

  • contres::DCResult composite type which contains the computed branches. See ContResult for more information,
continuation(br, ind_bif, lens2; ...)
 continuation(
     br,
     ind_bif,
@@ -72,9 +72,10 @@
     alg,
     lens,
     contParams;
+    bothside,
     kwargs...
 )
-

[Internal] This function is not meant to be called directly.

This function is the analog of continuation when the first two points on the branch are passed (instead of a single one). Hence x0 is the first point on the branch (with palc s=0) with parameter par0 and x1 is the second point with parameter set(par0, lens, p1).

continuation(br, ind_bif)
+

[Internal] This function is not meant to be called directly.

This function is the analog of continuation when the first two points on the branch are passed (instead of a single one). Hence x0 is the first point on the branch (with palc s=0) with parameter par0 and x1 is the second point with parameter set(par0, lens, p1).

continuation(br, ind_bif; ...)
 continuation(
     br,
     ind_bif,
@@ -117,7 +118,8 @@
     br,
     ind_bif,
     _contParams,
-    probPO;
+    pbPO;
+    prob_vf,
     alg,
     δp,
     ampfactor,
@@ -125,7 +127,7 @@
     nev,
     kwargs...
 )
-

Perform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.

Arguments

Optional arguments

  • alg = br.alg continuation algorithm
  • δp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.
  • ampfactor = 1 factor which alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.
  • usedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch
  • nev number of eigenvalues to be computed to get the right eigenvector
  • all kwargs from continuation

A modified version of prob is passed to plot_solution and finalise_solution.

Linear solver

You have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.

continuation(
+

Perform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.

Arguments

Optional arguments

  • alg = br.alg continuation algorithm
  • δp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.
  • ampfactor = 1 factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.
  • usedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch
  • nev number of eigenvalues to be computed to get the right eigenvector
  • all kwargs from continuation

A modified version of prob is passed to plot_solution and finalise_solution.

Linear solver

You have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.

continuation(
     br,
     ind_bif,
     _contParams;
@@ -135,6 +137,7 @@
     usedeflation,
     linear_algo,
     detailed,
+    prm,
     kwargs...
 )
 

Branch switching at a bifurcation point on a branch of periodic orbits (PO) specified by a br::AbstractBranchResult. The functional used to compute the PO is br.prob. A deflated Newton-Krylov solver can be used to improve the branch switching capabilities.

Arguments

Optional arguments

  • δp = 0.1 used to specify a particular guess for the parameter in the branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.
  • ampfactor = 1 factor which alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.
  • detailed = false whether to fully compute the normal form. The normal form is only used to collect the eigenvector for now.
  • usedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch
  • record_from_solution = (u, p) -> u[end], record method used in the bifurcation diagram, by default this records the period of the periodic orbit.
  • linear_algo = BorderingBLS(), same as for continuation
  • kwargs keywords arguments used for a call to the regular continuation and the ones specific to periodic orbits (POs).
continuation(
@@ -171,17 +174,18 @@
     verbosity,
     kwargs...
 )
-

Arguments

Continuation algorithms

BifurcationKit.PolynomialType
Polynomial Tangent predictor
  • n::Int64: Order of the polynomial

  • k::Int64: Length of the last solutions vector used for the polynomial fit

  • A::Matrix{T} where T<:Real: Matrix for the interpolation

  • tangent::BifurcationKit.AbstractTangentComputation: Algo for tangent when polynomial predictor is not possible

  • solutions::DataStructures.CircularBuffer: Vector of solutions

  • parameters::DataStructures.CircularBuffer{T} where T<:Real: Vector of parameters

  • arclengths::DataStructures.CircularBuffer{T} where T<:Real: Vector of arclengths

  • coeffsSol::Vector: Coefficients for the polynomials for the solution

  • coeffsPar::Vector{T} where T<:Real: Coefficients for the polynomials for the parameter

  • update::Bool: Update the predictor by adding the last point (x, p)? This can be disabled in order to just use the polynomial prediction. It is useful when the predictor is called mutiple times during bifurcation detection using bisection.

Constructor(s)

Polynomial(pred, n, k, v0)
+

Arguments

Continuation algorithms

BifurcationKit.NaturalType
Natural continuation algorithm. The predictor is the constant predictor and the parameter is incremented by `ContinuationPar().ds` at each continuation step.
BifurcationKit.PolynomialType
Polynomial Tangent predictor
  • n::Int64: Order of the polynomial

  • k::Int64: Length of the last solutions vector used for the polynomial fit

  • A::Matrix{T} where T<:Real: Matrix for the interpolation

  • tangent::BifurcationKit.AbstractTangentComputation: Algo for tangent when polynomial predictor is not possible

  • solutions::DataStructures.CircularBuffer: Vector of solutions

  • parameters::DataStructures.CircularBuffer{T} where T<:Real: Vector of parameters

  • arclengths::DataStructures.CircularBuffer{T} where T<:Real: Vector of arclengths

  • coeffsSol::Vector: Coefficients for the polynomials for the solution

  • coeffsPar::Vector{T} where T<:Real: Coefficients for the polynomials for the parameter

  • update::Bool: Update the predictor by adding the last point (x, p)? This can be disabled in order to just use the polynomial prediction. It is useful when the predictor is called mutiple times during bifurcation detection using bisection.

Constructor(s)

Polynomial(pred, n, k, v0)
 
-Polynomial(n, k, v0)
  • n order of the polynomial
  • k length of the last solutions vector used for the polynomial fit
  • v0 example of solution to be stored. It is only used to get the eltype of the tangent!!
BifurcationKit.MultipleType
Multiple Tangent continuation algorithm.
  • alg::PALC: Tangent predictor used Default: PALC()

  • τ::Any: Save the current tangent

  • α::Real: Damping in Newton iterations, 0 < α < 1

  • nb::Int64: Number of predictors

  • currentind::Int64: Index of the largest converged predictor Default: 0

  • pmimax::Int64: Index for lookup in residual history Default: 1

  • imax::Int64: Maximum index for lookup in residual history Default: 4

  • dsfact::Real: Factor to increase ds upon successful step Default: 1.5

Constructor(s)

Multiple(alg, x0, α, n)
+Polynomial(n, k, v0)
  • n order of the polynomial
  • k length of the last solutions vector used for the polynomial fit
  • v0 example of solution to be stored. It is only used to get the eltype of the tangent.

Can be used like

PALC(tangent = Polynomial(Bordered(), 2, 6, rand(1)))
BifurcationKit.MultipleType
Multiple Tangent continuation algorithm.
  • alg::PALC: Tangent predictor used Default: PALC()

  • τ::Any: Save the current tangent

  • α::Real: Damping in Newton iterations, 0 < α < 1

  • nb::Int64: Number of predictors

  • currentind::Int64: Index of the largest converged predictor Default: 0

  • pmimax::Int64: Index for lookup in residual history Default: 1

  • imax::Int64: Maximum index for lookup in residual history Default: 4

  • dsfact::Real: Factor to increase ds upon successful step Default: 1.5

Constructor(s)

Multiple(alg, x0, α, n)
 
 Multiple(pred, x0, α, n)
 
-Multiple(x0, α, n)
BifurcationKit.PALCType
struct PALC{Ttang<:BifurcationKit.AbstractTangentComputation, Tbls<:BifurcationKit.AbstractLinearSolver, T, Tdot} <: BifurcationKit.AbstractContinuationAlgorithm

Pseudo-arclength continuation algorithm.

Additional information is available on the website.

Fields

  • tangent::BifurcationKit.AbstractTangentComputation: Tangent predictor, must be a subtype of AbstractTangentComputation. For example Secant() or Bordered(), Default: Secant()

  • θ::Any: θ is a parameter in the arclength constraint. It is very important to tune it. It should be tuned for the continuation to work properly especially in the case of large problems where the < x - x0, dx0 > component in the constraint equation might be favoured too much. Also, large thetas favour p as the corresponding term in N involves the term 1-theta. Default: 0.5

  • _bothside::Bool: [internal], Default: false

  • bls::BifurcationKit.AbstractLinearSolver: Bordered linear solver used to invert the jacobian of the newton bordered problem. It is also used to compute the tangent for the predictor Bordered(), Default: MatrixBLS()

  • doArcLengthScaling::Bool: Unused for now, Default: false

  • gGoal::Any: Unused for now, Default: 0.5

  • gMax::Any: Unused for now, Default: 0.8

  • θMin::Any: Unused for now, Default: 0.001

  • dotθ::Any: dotθ = DotTheta(), this sets up a dot product (x, y) -> dot(x, y) / length(x) used to define the weighted dot product (resp. norm) $\|(x, p)\|^2_\theta$ in the constraint $N(x, p)$ (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...) Default: DotTheta()

BifurcationKit.MoorePenroseType
Moore-Penrose predictor / corrector

Moore-Penrose continuation algorithm.

Additional information is available on the website.

Constructors

alg = MoorePenrose()

alg = MoorePenrose(tangent = PALC())

Fields

  • tangent::Any: Tangent predictor, example PALC()

  • method::MoorePenroseLS: Use a direct linear solver. Can be BifurcationKit.direct, BifurcationKit.pInv or BifurcationKit.iterative

  • ls::BifurcationKit.AbstractLinearSolver: (Bordered) linear solver

BifurcationKit.DefContType
struct DefCont{Tdo, Talg, Tps, Tas, Tud, Tk} <: BifurcationKit.AbstractContinuationAlgorithm

Structure which holds the parameters specific to Deflated continuation.

Fields

  • deflation_operator::Any: Deflation operator, ::DeflationOperator Default: nothing

  • alg::Any: Used as a predictor, ::AbstractContinuationAlgorithm. For example PALC(), Natural(),... Default: PALC()

  • max_branches::Int64: maximum number of (active) branches to be computed Default: 100

  • seek_every_step::Int64: whether to seek new (deflated) solution at every step Default: 1

  • max_iter_defop::Int64: maximum number of deflated Newton iterations Default: 5

  • perturb_solution::Any: perturb function Default: _perturbSolution

  • accept_solution::Any: accept (solution) function Default: _acceptSolution

  • update_deflation_op::Any: function to update the deflation operator, ie pushing new solutions Default: _updateDeflationOp

  • jacobian::Any: jacobian for deflated newton. Can be DeflatedProblemCustomLS(), or Val(:autodiff), Val(:fullIterative) Default: DeflatedProblemCustomLS()

AsymptoticNumericalMethod.ANMType

Continuation algorithm based on Asymptotic Numerical Method. It can be used from the package https://github.com/bifurcationkit/AsymptoticNumericalMethod.jl

Fields

  • order::Int64: order of the polynomial approximation

  • tol::Any: tolerance which is used to estimate the neighbourhood on which the polynomial approximation is valid

References

  • Charpentier, Isabelle, Bruno Cochelin, and Komlanvi Lampoh. “Diamanlab - An Interactive Taylor-Based Continuation Tool in MATLAB,” n.d., 12.

  • Rubbert, Lennart, Isabelle Charpentier, Simon Henein, and Pierre Renaud. “Higher-Order Continuation Method for the Rigid-Body Kinematic Design of Compliant Mechanisms”, n.d., 18.

Events

BifurcationKit.DiscreteEventType
struct DiscreteEvent{Tcb, Tl} <: BifurcationKit.AbstractDiscreteEvent

Structure to pass a DiscreteEvent function to the continuation algorithm. A discrete call back returns a discrete value and we seek when it changes.

  • nb::Int64: number of events, ie the length of the result returned by the callback function

  • condition::Any: = (iter, state) -> NTuple{nb, Int64} callback function which at each continuation state, returns a tuple. For example, to detect a value change.

  • computeEigenElements::Bool: whether the event requires to compute eigen elements

  • labels::Any: Labels used to display information. For example labels[1] is used to qualify an event occurring in the first component. You can use labels = ("hopf",) or labels = ("hopf", "fold"). You must have labels::Union{Nothing, NTuple{N, String}}.

BifurcationKit.ContinuousEventType
struct ContinuousEvent{Tcb, Tl, T} <: BifurcationKit.AbstractContinuousEvent

Structure to pass a ContinuousEvent function to the continuation algorithm. A continuous call back returns a tuple/scalar value and we seek its zeros.

  • nb::Int64: number of events, ie the length of the result returned by the callback function

  • condition::Any: , (iter, state) -> NTuple{nb, T} callback function which, at each continuation state, returns a tuple. For example, to detect crossing 1.0 and -2.0, you can pass (iter, state) -> (getp(state)+2, getx(state)[1]-1)),. Note that the type T should match the one of the parameter specified by the ::Lens in continuation.

  • computeEigenElements::Bool: whether the event requires to compute eigen elements

  • labels::Any: Labels used to display information. For example labels[1] is used to qualify an event of the type (0,1.3213,3.434). You can use labels = ("hopf",) or labels = ("hopf", "fold"). You must have labels::Union{Nothing, NTuple{N, String}}.

  • tol::Any: Tolerance on event value to declare it as true event.

BifurcationKit.SetOfEventsType
struct SetOfEvents{Tc<:Tuple, Td<:Tuple} <: BifurcationKit.AbstractEvent

Multiple events can be chained together to form a SetOfEvents. A SetOfEvents is constructed by passing to the constructor ContinuousEvent, DiscreteEvent or other SetOfEvents instances:

SetOfEvents(cb1, cb2, cb3)

Example

 BifurcationKit.SetOfEvents(BK.FoldDetectCB, BK.BifDetectCB)

You can pass as many events as you like.

  • eventC::Tuple: Continuous event

  • eventD::Tuple: Discrete event

BifurcationKit.PairOfEventsType
struct PairOfEvents{Tc<:BifurcationKit.AbstractContinuousEvent, Td<:BifurcationKit.AbstractDiscreteEvent} <: BifurcationKit.AbstractEvent

Structure to pass a PairOfEvents function to the continuation algorithm. It is composed of a pair ContinuousEvent / DiscreteEvent. A PairOfEvents is constructed by passing to the constructor a ContinuousEvent and a DiscreteEvent:

PairOfEvents(contEvent, discreteEvent)

Fields

  • eventC::BifurcationKit.AbstractContinuousEvent: Continuous event

  • eventD::BifurcationKit.AbstractDiscreteEvent: Discrete event

Branch switching (branch point)

Missing docstring.

Missing docstring for continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar ; kwargs...). Check Documenter's build log for details.

Branch switching (Hopf point)

BifurcationKit.PALCType
struct PALC{Ttang<:BifurcationKit.AbstractTangentComputation, Tbls<:BifurcationKit.AbstractLinearSolver, T, Tdot} <: BifurcationKit.AbstractContinuationAlgorithm

Pseudo-arclength continuation algorithm.

Additional information is available on the website.

Fields

  • tangent::BifurcationKit.AbstractTangentComputation: Tangent predictor, must be a subtype of AbstractTangentComputation. For example Secant() or Bordered(), Default: Secant()

  • θ::Any: θ is a parameter in the arclength constraint. It is very important to tune it. It should be tuned for the continuation to work properly especially in the case of large problems where the < x - x0, dx0 > component in the constraint equation might be favoured too much. Also, large thetas favour p as the corresponding term in N involves the term 1-theta. Default: 0.5

  • _bothside::Bool: [internal], Default: false

  • bls::BifurcationKit.AbstractLinearSolver: Bordered linear solver used to invert the jacobian of the newton bordered problem. It is also used to compute the tangent for the predictor Bordered(), Default: MatrixBLS()

  • doArcLengthScaling::Bool: Unused for now, Default: false

  • gGoal::Any: Unused for now, Default: 0.5

  • gMax::Any: Unused for now, Default: 0.8

  • θMin::Any: Unused for now, Default: 0.001

  • dotθ::Any: dotθ = DotTheta(), this sets up a dot product (x, y) -> dot(x, y) / length(x) used to define the weighted dot product (resp. norm) $\|(x, p)\|^2_\theta$ in the constraint $N(x, p)$ (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...) Default: DotTheta()

BifurcationKit.MoorePenroseType
Moore-Penrose predictor / corrector

Moore-Penrose continuation algorithm.

Additional information is available on the website.

Constructors

alg = MoorePenrose()

alg = MoorePenrose(tangent = PALC())

Fields

  • tangent::Any: Tangent predictor, example PALC()

  • method::MoorePenroseLS: Use a direct linear solver. Can be BifurcationKit.direct, BifurcationKit.pInv or BifurcationKit.iterative

  • ls::BifurcationKit.AbstractLinearSolver: (Bordered) linear solver

BifurcationKit.DefContType
struct DefCont{Tdo, Talg, Tps, Tas, Tud, Tk} <: BifurcationKit.AbstractContinuationAlgorithm

Structure which holds the parameters specific to Deflated continuation.

Fields

  • deflation_operator::Any: Deflation operator, ::DeflationOperator Default: nothing

  • alg::Any: Used as a predictor, ::AbstractContinuationAlgorithm. For example PALC(), Natural(),... Default: PALC()

  • max_branches::Int64: maximum number of (active) branches to be computed Default: 100

  • seek_every_step::Int64: whether to seek new (deflated) solution at every step Default: 1

  • max_iter_defop::Int64: maximum number of deflated Newton iterations Default: 5

  • perturb_solution::Any: perturb function Default: _perturbSolution

  • accept_solution::Any: accept (solution) function Default: _acceptSolution

  • update_deflation_op::Any: function to update the deflation operator, ie pushing new solutions Default: _updateDeflationOp

  • jacobian::Any: jacobian for deflated newton. Can be DeflatedProblemCustomLS(), or Val(:autodiff), Val(:fullIterative) Default: DeflatedProblemCustomLS()

AsymptoticNumericalMethod.ANMType

Continuation algorithm based on Asymptotic Numerical Method. It can be used from the package https://github.com/bifurcationkit/AsymptoticNumericalMethod.jl

Fields

  • order::Int64: order of the polynomial approximation

  • tol::Any: tolerance which is used to estimate the neighbourhood on which the polynomial approximation is valid

References

  • Charpentier, Isabelle, Bruno Cochelin, and Komlanvi Lampoh. “Diamanlab - An Interactive Taylor-Based Continuation Tool in MATLAB,” n.d., 12.

  • Rubbert, Lennart, Isabelle Charpentier, Simon Henein, and Pierre Renaud. “Higher-Order Continuation Method for the Rigid-Body Kinematic Design of Compliant Mechanisms”, n.d., 18.

Events

BifurcationKit.DiscreteEventType
struct DiscreteEvent{Tcb, Tl} <: BifurcationKit.AbstractDiscreteEvent

Structure to pass a DiscreteEvent function to the continuation algorithm. A discrete call back returns a discrete value and we seek when it changes.

  • nb::Int64: number of events, ie the length of the result returned by the callback function

  • condition::Any: = (iter, state) -> NTuple{nb, Int64} callback function which at each continuation state, returns a tuple. For example, to detect a value change.

  • computeEigenElements::Bool: whether the event requires to compute eigen elements

  • labels::Any: Labels used to display information. For example labels[1] is used to qualify an event occurring in the first component. You can use labels = ("hopf",) or labels = ("hopf", "fold"). You must have labels::Union{Nothing, NTuple{N, String}}.

BifurcationKit.ContinuousEventType
struct ContinuousEvent{Tcb, Tl, T} <: BifurcationKit.AbstractContinuousEvent

Structure to pass a ContinuousEvent function to the continuation algorithm. A continuous call back returns a tuple/scalar value and we seek its zeros.

  • nb::Int64: number of events, ie the length of the result returned by the callback function

  • condition::Any: , (iter, state) -> NTuple{nb, T} callback function which, at each continuation state, returns a tuple. For example, to detect crossing 1.0 and -2.0, you can pass (iter, state) -> (getp(state)+2, getx(state)[1]-1)),. Note that the type T should match the one of the parameter specified by the ::Lens in continuation.

  • computeEigenElements::Bool: whether the event requires to compute eigen elements

  • labels::Any: Labels used to display information. For example labels[1] is used to qualify an event of the type (0, 1.3213, 3.434). You can use labels = ("hopf",) or labels = ("hopf", "fold"). You must have labels::Union{Nothing, NTuple{N, String}}.

  • tol::Any: Tolerance on event value to declare it as true event.

BifurcationKit.SetOfEventsType
struct SetOfEvents{Tc<:Tuple, Td<:Tuple} <: BifurcationKit.AbstractEvent

Multiple events can be chained together to form a SetOfEvents. A SetOfEvents is constructed by passing to the constructor ContinuousEvent, DiscreteEvent or other SetOfEvents instances:

SetOfEvents(cb1, cb2, cb3)

Example

 BifurcationKit.SetOfEvents(BK.FoldDetectCB, BK.BifDetectCB)

You can pass as many events as you like.

  • eventC::Tuple: Continuous event

  • eventD::Tuple: Discrete event

BifurcationKit.PairOfEventsType
struct PairOfEvents{Tc<:BifurcationKit.AbstractContinuousEvent, Td<:BifurcationKit.AbstractDiscreteEvent} <: BifurcationKit.AbstractEvent

Structure to pass a PairOfEvents function to the continuation algorithm. It is composed of a pair ContinuousEvent / DiscreteEvent. A PairOfEvents is constructed by passing to the constructor a ContinuousEvent and a DiscreteEvent:

PairOfEvents(contEvent, discreteEvent)

Fields

  • eventC::BifurcationKit.AbstractContinuousEvent: Continuous event

  • eventD::BifurcationKit.AbstractDiscreteEvent: Discrete event

Branch switching (branch point)

Missing docstring.

Missing docstring for continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar ; kwargs...). Check Documenter's build log for details.

Branch switching (Hopf point)

BifurcationKit.continuationMethod
continuation(
     br,
     ind_bif,
     _contParams,
-    probPO;
+    pbPO;
+    prob_vf,
     alg,
     δp,
     ampfactor,
@@ -189,7 +193,7 @@
     nev,
     kwargs...
 )
-

Perform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.

Arguments

Optional arguments

  • alg = br.alg continuation algorithm
  • δp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.
  • ampfactor = 1 factor which alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.
  • usedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch
  • nev number of eigenvalues to be computed to get the right eigenvector
  • all kwargs from continuation

A modified version of prob is passed to plot_solution and finalise_solution.

Linear solver

You have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.

Bifurcation diagram

BifurcationKit.bifurcationdiagramFunction
bifurcationdiagram(prob, alg, level, options; kwargs...)
+

Perform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.

Arguments

Optional arguments

  • alg = br.alg continuation algorithm
  • δp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.
  • ampfactor = 1 factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.
  • usedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch
  • nev number of eigenvalues to be computed to get the right eigenvector
  • all kwargs from continuation

A modified version of prob is passed to plot_solution and finalise_solution.

Linear solver

You have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.

Bifurcation diagram

BifurcationKit.bifurcationdiagramFunction
bifurcationdiagram(prob, alg, level, options; kwargs...)
 

Compute the bifurcation diagram associated with the problem F(x, p) = 0 recursively.

Arguments

  • prob::AbstractBifurcationProblem bifurcation problem
  • alg continuation algorithm
  • level maximum branching (or recursion) level for computing the bifurcation diagram
  • options = (x, p, level) -> contparams this function allows to change the continuation options depending on the branching level. The argument x, p denotes the current solution to F(x, p)=0.
  • kwargs optional arguments. Look at bifurcationdiagram! for more details.

Simplified call:

We also provide the method

bifurcationdiagram(prob, br::ContResult, level::Int, options; kwargs...)

where br is a branch computed after a call to continuation from which we want to compute the bifurcating branches recursively.

BifurcationKit.bifurcationdiagram!Function
bifurcationdiagram!(
     prob,
     node,
@@ -248,12 +252,15 @@
     nev,
     verbose,
     ζs,
+    ζs_ad,
     lens,
     Teigvec,
     scaleζ,
     detailed,
     autodiff,
-    bls
+    bls,
+    bls_adjoint,
+    bls_block
 )
 

Compute the normal form of the bifurcation point located at br.specialpoint[ind_bif].

Arguments

  • prob::AbstractBifurcationProblem
  • br result from a call to continuation
  • ind_bif index of the bifurcation point in br.specialpoint

Optional arguments

  • nev number of eigenvalues used to compute the spectral projection. This number has to be adjusted when used with iterative methods.
  • verbose whether to display information
  • ζs list of vectors spanning the kernel of dF at the bifurcation point. Useful to enforce the basis for the normal form.
  • lens::Lens specify which parameter to take the partial derivative ∂pF
  • scaleζ function to normalise the kernel basis. Indeed, when used with large vectors and norm, it results in ζs and the normal form coefficient being super small.
  • autodiff = true whether to use ForwardDiff for the differentiations w.r.t the parameters that are required to compute the normal form. Used for example for Bogdanov-Takens point. You can set to autodiff = false if you wish.
  • detailed = true whether to compute only a simplified normal form. Used for example for Bogdanov-Takens point.
  • bls = MatrixBLS() specify Bordered linear solver. Used for example for Bogdanov-Takens point.

Available method

You can directly call

get_normal_form(br, ind_bif ; kwargs...)

which is a shortcut for get_normal_form(getProb(br), br, ind_bif ; kwargs...).

Once the normal form nf has been computed, you can call predictor(nf, δp) to obtain an estimate of the bifurcating branch.

get_normal_form(
     prob,
@@ -269,4 +276,4 @@
     δ,
     detailed
 )
-

Compute the normal form of periodic orbits. Same arguments as the function get_normal_form for equilibria. We detail the additional keyword arguments specific to periodic orbits

Optional arguments

  • prm = true compute the normal form using Poincaré return map. For collocation, there will be another way to compute the normal form in the future.
+

Compute the normal form of periodic orbits. Same arguments as the function get_normal_form for equilibria. We detail the additional keyword arguments specific to periodic orbits

Optional arguments

  • prm = true compute the normal form using Poincaré return map. For collocation, there will be another way to compute the normal form in the future.
diff --git a/dev/linearsolver/index.html b/dev/linearsolver/index.html index 32446098..0af343ef 100644 --- a/dev/linearsolver/index.html +++ b/dev/linearsolver/index.html @@ -5,4 +5,4 @@ return J \ rhs, true, 1 end

Note that for newton to work, the linear solver must return 3 arguments. The first one is the result, the second one is whether the computation was successful and the third is the number of iterations required to perform the computation.

You can then call it as follows (and it will be called like this in newton)

ls = DefaultLS()
 J = rand(2, 2) # example of linear operator
-ls(J, rand(2))

List of implemented linear solvers

  1. Default \ solver based on LU or Cholesky depending on the type of the Jacobian. This works for sparse matrices as well. You can create one via linsolver = DefaultLS().
  2. GMRES from IterativeSolvers.jl. You can create one via linsolver = GMRESIterativeSolvers() and pass appropriate options.
  3. GMRES from KrylovKit.jl. You can create one via linsolver = GMRESKrylovKit() and pass appropriate options.
Different linear solvers

By tuning the options of GMRESKrylovKit, you can select CG, GMRES... see KrylovKit.jl.

Other solvers

It is very straightforward to implement the Conjugate Gradients from IterativeSolvers.jl by copying the interface done for gmres. Same goes for minres,... Not needing them, I did not implement this.

Preconditioner

Preconditioners should be considered when using Matrix Free methods such as GMRES. GMRESIterativeSolvers provides a very simple interface for using them. For GMRESKrylovKit, we implemented a left preconditioner. Note that, for GMRESKrylovKit, you are not restricted to use Vectors anymore. Finally, here are some packages to use preconditioners

  1. IncompleteLU.jl an ILU like preconditioner
  2. AlgebraicMultigrid.jl Algebraic Multigrid (AMG) preconditioners. This works especially well for symmetric positive definite matrices.
  3. Preconditioners.jl A convenient interface to conveniently called most of the above preconditioners using a single syntax.
  4. We provide a preconditioner based on deflation of eigenvalues (also called preconditioner based on Leading Invariant Subspaces) using a partial Schur decomposition. There are two ways to define one i.e. PrecPartialSchurKrylovKit and PrecPartialSchurArnoldiMethod.
Using Preconditioners

Apart from setting a preconditioner for a linear solver, it can be advantageous to change the preconditioner during computations, e.g. during a call to continuation or newton. This can be achieved by taking advantage of the callbacks to these methods. See the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS).

+ls(J, rand(2))

List of implemented linear solvers

  1. Default \ solver based on LU or Cholesky depending on the type of the Jacobian. This works for sparse matrices as well. You can create one via linsolver = DefaultLS().
  2. GMRES from IterativeSolvers.jl. You can create one via linsolver = GMRESIterativeSolvers() and pass appropriate options.
  3. GMRES from KrylovKit.jl. You can create one via linsolver = GMRESKrylovKit() and pass appropriate options.
Different linear solvers

By tuning the options of GMRESKrylovKit, you can select CG, GMRES... see KrylovKit.jl.

Other solvers

It is very straightforward to implement the Conjugate Gradients from IterativeSolvers.jl by copying the interface done for gmres. Same goes for minres,... Not needing them, I did not implement this.

Preconditioner

Preconditioners should be considered when using Matrix Free methods such as GMRES. GMRESIterativeSolvers provides a very simple interface for using them. For GMRESKrylovKit, we implemented a left preconditioner. Note that, for GMRESKrylovKit, you are not restricted to use Vectors anymore. Finally, here are some packages to use preconditioners

  1. IncompleteLU.jl an ILU like preconditioner
  2. AlgebraicMultigrid.jl Algebraic Multigrid (AMG) preconditioners. This works especially well for symmetric positive definite matrices.
  3. Preconditioners.jl A convenient interface to conveniently called most of the above preconditioners using a single syntax.
  4. We provide a preconditioner based on deflation of eigenvalues (also called preconditioner based on Leading Invariant Subspaces) using a partial Schur decomposition. There are two ways to define one i.e. PrecPartialSchurKrylovKit and PrecPartialSchurArnoldiMethod.
Using Preconditioners

Apart from setting a preconditioner for a linear solver, it can be advantageous to change the preconditioner during computations, e.g. during a call to continuation or newton. This can be achieved by taking advantage of the callbacks to these methods. See the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS).

diff --git a/dev/migration/index.html b/dev/migration/index.html index 01a1bb1e..ff89ed82 100644 --- a/dev/migration/index.html +++ b/dev/migration/index.html @@ -1,2 +1,2 @@ -Migration from old versions · Bifurcation Analysis in Julia

Migration from previous versions

Migration from v0.1.x to v0.2.x

IMPORTANT NOTICE

New version of the package with modified interface. You are now required to define a BifurcationProblem to perform continuation or bifurcation analysis. The previous interface is available under the tag 0.1.12 which can be installed by doing

] add BifurcationKit@0.1.12

The new version provides many bugs fix though. (Please note that the docs are up to date).

Introduction

In v0.2.x, we introduced problem based bifurcation diagram, meaning that you have now to wrap your vector field in a BifurcationProblem. You also need to pass your plot/record functions.

Don't use AD yourself

There is nothing wrong with doing so but this is done in the constructor of BifurcationPoblem, so if myJacAD is the jacobian computed using ForwardDiff, the declaration

prob = BifurcationProblem(F, x, p, lens ; J = myJacAD) 

should be

prob = BifurcationProblem(F, x, p, lens) 

There is nothing wrong in passing your own jacobian though

Error: no method matching iterate(::BifurcationKit.ContResult

This is because you use the old syntax

br, = continuation(...)

instead of (no comma)

br = continuation(...)

Arguments to continuation

recordFromSolution and plotFromSolution should be passed to BifurcationProblem instead of continuation.

Migration from v0.2.x to v0.3.x

A new version v0.3 has been tagged in which the function names, keyword arguments,... follow the Julia convention. There are a lot of breaking changes. For example, callbackN has been changed to callback_newton.

+Migration from old versions · Bifurcation Analysis in Julia

Migration from previous versions

Migration from v0.1.x to v0.2.x

IMPORTANT NOTICE

New version of the package with modified interface. You are now required to define a BifurcationProblem to perform continuation or bifurcation analysis. The previous interface is available under the tag 0.1.12 which can be installed by doing

] add BifurcationKit@0.1.12

The new version provides many bugs fix though. (Please note that the docs are up to date).

Introduction

In v0.2.x, we introduced problem based bifurcation diagram, meaning that you have now to wrap your vector field in a BifurcationProblem. You also need to pass your plot/record functions.

Don't use AD yourself

There is nothing wrong with doing so but this is done in the constructor of BifurcationPoblem, so if myJacAD is the jacobian computed using ForwardDiff, the declaration

prob = BifurcationProblem(F, x, p, lens ; J = myJacAD) 

should be

prob = BifurcationProblem(F, x, p, lens) 

There is nothing wrong in passing your own jacobian though

Error: no method matching iterate(::BifurcationKit.ContResult

This is because you use the old syntax

br, = continuation(...)

instead of (no comma)

br = continuation(...)

Arguments to continuation

recordFromSolution and plotFromSolution should be passed to BifurcationProblem instead of continuation.

Migration from v0.2.x to v0.3.x

A new version v0.3 has been tagged in which the function names, keyword arguments,... follow the Julia convention. There are a lot of breaking changes. For example, callbackN has been changed to callback_newton.

diff --git a/dev/modulated_wave_fd/index.html b/dev/modulated_wave_fd/index.html index eb97276e..6c375fc3 100644 --- a/dev/modulated_wave_fd/index.html +++ b/dev/modulated_wave_fd/index.html @@ -3,4 +3,4 @@ \begin{array}{l} F(x, p) - s\cdot T\cdot x=0 \\ \langle T\cdot x_{ref},x-x_{ref}\rangle=0 -\end{array}\right.\tag{FE}\]

This provides a travelling wave solution $

References

  • Beyn

    Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

+\end{array}\right.\tag{FE}\]

This provides a travelling wave solution $

References

  • Beyn

    Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

diff --git a/dev/newton/index.html b/dev/newton/index.html index 1ce1350e..84474544 100644 --- a/dev/newton/index.html +++ b/dev/newton/index.html @@ -6,4 +6,4 @@ sol = newton(prob, NewtonPar(verbose = true))
NonLinearSolution{Vector{Float64}, BifurcationProblem{BifFunction{typeof(Main.F), BifurcationKit.var"#8#24", Nothing, BifurcationKit.var"#6#22", Nothing, BifurcationKit.var"#11#28"{BifurcationKit.var"#d1Fad#26"}, BifurcationKit.var"#13#30", BifurcationKit.var"#15#32", BifurcationKit.var"#17#34", Bool, Float64}, Vector{Float64}, Nothing, Setfield.IdentityLens, typeof(BifurcationKit.plot_default), typeof(BifurcationKit.record_sol_default)}, Vector{Float64}, Int64}([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], ┌─ Bifurcation Problem with uType Vector{Float64}
 ├─ Inplace:  false
 ├─ Symmetric: false
-└─ Parameter: p, [2.857122356962538, 321595.12304840895, 95287.0890256422, 28232.85674167823, 8364.93612397875, 2478.1450063734915, 733.9110991862943, 217.10224864680382, 63.97626016608187, 18.611605166883276, 5.187032997647922, 1.2580409715103955, 0.20077507380993673, 0.010279671408633798, 3.453646501637747e-5, 3.975446649353566e-10, 0.0], true, 16, 16)

Example

The (basic) tutorial Temperature model presents all cases (direct and iterative ones).

+└─ Parameter: p, [2.566122804223772, 9203.278247917104, 2726.6304983603895, 807.6242569533529, 239.03109034784725, 70.56198929503124, 20.650159347506822, 5.869611258089642, 1.5130181849121846, 0.2833355318677746, 0.020340143080068707, 0.00013485863695716915, 6.061375401600344e-9, 0.0], true, 13, 13)

Example

The (basic) tutorial Temperature model presents all cases (direct and iterative ones).

diff --git a/dev/nonsimplebp/index.html b/dev/nonsimplebp/index.html index 4b16e604..53cb05d3 100644 --- a/dev/nonsimplebp/index.html +++ b/dev/nonsimplebp/index.html @@ -1,5 +1,5 @@ -Non-simple branch point · Bifurcation Analysis in Julia

Non-simple branch point

References

The general method is exposed in Golubitsky, Martin, David G Schaeffer, and Ian Stewart. Singularities and Groups in Bifurcation Theory. New York: Springer-Verlag, 1985, VI.1.d page 295

Example

An example of use of the methods presented here is provided in 2d generalized Bratu–Gelfand problem.

We expose our method to study non-simple branch points. Such branch point $(x_0,p_0)$ for the problem $F(x,p)=0$ satisfies $d=\dim \ker dF(x_0,p_0) > 1$ and the eigenvalues have zero imaginary part. At such point, we can apply Lyapunov-Schmidt reduction to transform the initial problem in large dimensions to a $d$-dimensional polynomial equation, called the reduced equation.

More precisely, it is possible to write $x = u + v$ where $u\in \ker dF(x_0,p_0)$ and $v\approx 0$ belongs to a vector space complement of $\ker dF(x_0,p_0)$. It can be shown that $u$ solves $\Phi(u,\delta p)=0$ with $\Phi(u,\delta p) = (I-\Pi)F(u+\psi(u,\delta p),p_0+\delta p)$ where $\psi$ is known implicitly and $\Pi$ is the spectral projector on $\ker dF(x_0,p_0)$. Fortunately, one can compute the Taylor expansion of $\Phi$ up to order 3. Computing the bifurcation diagram of this $d$-dimensional multivariate polynomials can be done using brute force methods.

Once the zeros of $\Phi$ have been located, we can use them as initial guess for continuation but for the original $F$ !!

Reduced equation computation

The reduced equation (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. It returns a point with all requested information:

mutable struct NdBranchPoint{Tv, T, Tevl, Tevr, Tnf} <: BranchPoint
+Non-simple branch point · Bifurcation Analysis in Julia

Non-simple branch point

References

The general method is exposed in Golubitsky, Martin, David G Schaeffer, and Ian Stewart. Singularities and Groups in Bifurcation Theory. New York: Springer-Verlag, 1985, VI.1.d page 295

Example

An example of use of the methods presented here is provided in 2d generalized Bratu–Gelfand problem.

We expose our method to study non-simple branch points. Such branch point $(x_0,p_0)$ for the problem $F(x,p)=0$ satisfies $d=\dim \ker dF(x_0,p_0) > 1$ and the eigenvalues have zero imaginary part. At such point, we can apply Lyapunov-Schmidt reduction to transform the initial problem in large dimensions to a $d$-dimensional polynomial equation, called the reduced equation.

More precisely, it is possible to write $x = u + v$ where $u\in \ker dF(x_0,p_0)$ and $v\approx 0$ belongs to a vector space complement of $\ker dF(x_0,p_0)$. It can be shown that $u$ solves $\Phi(u,\delta p)=0$ with $\Phi(u,\delta p) = (I-\Pi)F(u+\psi(u,\delta p),p_0+\delta p)$ where $\psi$ is known implicitly and $\Pi$ is the spectral projector on $\ker dF(x_0,p_0)$. Fortunately, one can compute the Taylor expansion of $\Phi$ up to order 3. Computing the bifurcation diagram of this $d$-dimensional multivariate polynomials can be done using brute force methods.

Once the zeros of $\Phi$ have been located, we can use them as initial guess for continuation but for the original $F$ !!

Reduced equation computation

The reduced equation (E) can be automatically computed as follows

get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. It returns a point with all requested information:

mutable struct NdBranchPoint{Tv, T, Tevl, Tevr, Tnf} <: BranchPoint
 	"bifurcation point"
 	x0::Tv
 
@@ -20,4 +20,4 @@
 end

Using the reduced equation

Once a branch point has been computed bp = get_normal_form(...), you can do all sort of things.

  • For example, quoted from the file test/testNF.jl, you can print the 2d reduced equation as follows:
julia> BifurcationKit.nf(bp2d)
 2-element Array{String,1}:
  " + (3.23 + 0.0im) * x1 * p + (-0.123 + 0.0im) * x1^3 + (-0.234 + 0.0im) * x1 * x2^2"
- " + (-0.456 + 0.0im) * x1^2 * x2 + (3.23 + 0.0im) * x2 * p + (-0.123 + 0.0im) * x2^3"
  • You can evaluate the reduced equation as bp2d(Val(:reducedForm), rand(2), 0.2). This can be used to find all the zeros of the reduced equation by sampling on a grid or using a general solver like Roots.jl.

  • Finally, given a $d$-dimensional vector $x$ and a parameter $\delta p$, you can have access to an initial guess $u$ (see above) by calling bp2d(rand(2), 0.1)

Branching from bifurcation point

It may happen that the general procedure fails. We thus expose the procedure multicontinuation in order to let the user tune it to its need.

The first step is to compute the reduced equation, say of the first bifurcation point in br.

bp = get_normal_form(br, 1)

Next, we want to find the zeros of the reduced equation. This is usually achieved by calling the predictor

pred = predictor(bp, δp)

which returns zeros of bp before and after the bifurcation point. You could also use your prefered procedure from Roots.jl (or other) to find the zeros of the polynomials bp(Val(:reducedForm), z, p).

We can use these zeros to form guesses to apply Newton for the full functional:

pts = BifurcationKit.getFirstPointsOnBranch(br, bp, pred, opts; δp =  δp)

We can then use this to continue the different branches

brbp = BifurcationKit.multicontinuation(br, bp, pts.before, pts.after, opts)
+ " + (-0.456 + 0.0im) * x1^2 * x2 + (3.23 + 0.0im) * x2 * p + (-0.123 + 0.0im) * x2^3"
  • You can evaluate the reduced equation as bp2d(Val(:reducedForm), rand(2), 0.2). This can be used to find all the zeros of the reduced equation by sampling on a grid or using a general solver like Roots.jl.

  • Finally, given a $d$-dimensional vector $x$ and a parameter $\delta p$, you can have access to an initial guess $u$ (see above) by calling bp2d(rand(2), 0.1)

diff --git a/dev/ns/index.html b/dev/ns/index.html index 0f1bdd53..569274b9 100644 --- a/dev/ns/index.html +++ b/dev/ns/index.html @@ -2,4 +2,4 @@ Neimarck-Sacker · Bifurcation Analysis in Julia

Neimark-Sacker point

At a Neimark-Sacker (NS) bifurcation of a periodic orbit $\gamma$ (with period $T$) for parameter value $p_0$ for the Cauchy problem

\[\frac{du}{dt}=F(u,p),\tag{E}\]

the eigenvalues (Floquet coefficients) of the monodromy operator $\mathcal M=Y(T)$ solution to

\[\frac{dY}{dt}=A(t)Y(t), Y(0)=I_n\]

contain the eigenvalues $e^{\pm i \theta}$ with $\theta$ and

\[e^{i q \theta}-1 \neq 0, \quad q=1,2,3,4 \text { (no strong resonances). }\]

There are two ways to compute the normal form of this bifurcation

  1. using the Poincaré return map [Kuznetsov]
  2. using the method of [Iooss], see also [Kuz2]

You can obtain the normal form of a NS bifurcation using

pd = get_normal_form(br, ind; prm = false)

where prm indicates whether you want to use the method based on Poincaré return map (PRM) or the one based on Iooss method.

Normal form based on Poincaré return map

Given a transversal section $\Sigma$ to $\gamma$ at $\gamma(0)$, the Poincaré return map $\mathcal P$ associates to each point $x\in\Sigma$ close to $\gamma(0)$ the first point $\mathcal P(x,p)\in\Sigma$ where the orbit of (E) with initial condition $x$ intersects again $\Sigma$ at $\mathcal P(x,p)$. Hence, the discrete map $x_{n+1}=\mathcal P(x_n,p)$ has normal form

\[z_{n+1} = z_ne^{i\theta}(1+d|z_n|^2)\]

where[Kuz2]

\[d=\frac{1}{2} e^{-i \theta}\left\langle v^*, \mathcal{C}(v, v, \bar{v})+2 \mathcal{B}\left(v,\left(I_{n-1}-\mathcal{A}\right)^{-1} \mathcal{B}(v, \bar{v})\right)+\mathcal{B}\left(\bar{v},\left(e^{2 i \theta} I_{n-1}-\mathcal{A}\right)^{-1} \mathcal{B}(v, v)\right)\right\rangle\]

where $\mathcal C=d^3\mathcal P(\gamma(0))$, $\mathcal B = d^2\mathcal P(\gamma(0))$ and $\mathcal A = d\mathcal P(\gamma(0))$. Also:

\[\mathcal{A} v=e^{i \theta} v, \mathcal{A}^{\mathrm{T}} v^*=e^{-i \theta} v^*, \text { and }\left\langle v^*, v\right\rangle=1\]

Normal form based on Iooss method

This is based on [Iooss],[Kuz2]. Suppose that the $T$ periodic orbit $\gamma(\tau)$ has a Neimark-Sacker bifurcation for a parameter value $p_0$. We also assume that there are no strong resonances. Locally, the orbits can be represented by

\[x(\tau) = \gamma(\tau)+Q_0(\tau)\xi+\Phi(\tau, \xi)\]

where

\[\left\{\begin{aligned} \frac{d \tau}{d t} & =1+a|\xi|^2+\cdots \\ \frac{d \xi}{d t} & =\frac{i \theta}{T} \xi+d \xi|\xi|^2+\cdots -\end{aligned}\right.\]

with center manifold correction $\Phi(\tau, \xi)$ being $T$ periodic in $\tau$ and $Q_0(\tau)$ is the Floquet operator.

References

  • Kuznetsov

    Yu. A. Kuznetsov, "Elements of Applied Bifurcation Theory", 2nd ed., 1998.

  • Kuz2

    Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”

  • Iooss

    Iooss, "Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.", 1988

+\end{aligned}\right.\]

with center manifold correction $\Phi(\tau, \xi)$ being $T$ periodic in $\tau$ and $Q_0(\tau)$ is the Floquet operator.

References

  • Kuznetsov

    Yu. A. Kuznetsov, "Elements of Applied Bifurcation Theory", 2nd ed., 1998.

  • Kuz2

    Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”

  • Iooss

    Iooss, "Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.", 1988

diff --git a/dev/overview/index.html b/dev/overview/index.html index 173d850d..01606d9c 100644 --- a/dev/overview/index.html +++ b/dev/overview/index.html @@ -1,2 +1,2 @@ -Overview · Bifurcation Analysis in Julia

Overview of BifurcationKit.jl

The general workflow for using the package is as follows:

  • Define a problem
  • Solve the problem
  • Analyze the output

Defining Problems

Problems are specified via a type interface. The problem types are designed to contain the necessary information to fully define their associated continuation method. For example, a bifurcation problem is defined by

\[F(u, pars) = 0\]

with some parameters pars, some initial guess u0, and scalar parameter axis lens contained in pars. Therefore the BifurcationProblem is defined by those components:

prob = BifurcationProblem(F, u0, pars, lens)

Note that the number types in the solution will match the types you designate in the problem. However complex types are not advised as they mess up the detection of bifurcation points.

Continuing from the initial guess

Each type of bifurcation problem has its own problem type which allow the solvers to dispatch to the right methods. The common interface for calling the solvers is:

br = continuation(prob, alg; kwargs)

Into the command, one passes the bifurcation problem that was defined prob, choose an algorithm alg, and change the properties of the solver using keyword arguments. The solver returns a branch object br which holds all the details for the branch.

Analyzing the branch

The solution type has a common interface, which makes handling the solution similar between the different types of bifurcation problems. Tools such as interpolations are seamlessly built into the solution interface to make analysis easy. This interface is described in the ContResult.

Plotting functionality is provided by a recipe to Plots.jl. To use plot branches, simply call the plot(br) and the plotter will generate appropriate plots. Plots can be customized using all the keyword arguments provided by Plots.jl. Please see Plots.jl's documentation for more information.

+Overview · Bifurcation Analysis in Julia

Overview of BifurcationKit.jl

The general workflow for using the package is as follows:

  • Define a problem
  • Solve the problem
  • Analyze the output

Defining Problems

Problems are specified via a type interface. The problem types are designed to contain the necessary information to fully define their associated continuation method. For example, a bifurcation problem is defined by

\[F(u, pars) = 0\]

with some parameters pars, some initial guess u0, and scalar parameter axis lens contained in pars. Therefore the BifurcationProblem is defined by those components:

prob = BifurcationProblem(F, u0, pars, lens)

Note that the number types in the solution will match the types you designate in the problem. However complex types are not advised as they mess up the detection of bifurcation points.

Continuing from the initial guess

Each type of bifurcation problem has its own problem type which allow the solvers to dispatch to the right methods. The common interface for calling the solvers is:

br = continuation(prob, alg; kwargs)

Into the command, one passes the bifurcation problem that was defined prob, choose an algorithm alg, and change the properties of the solver using keyword arguments. The solver returns a branch object br which holds all the details for the branch.

Analyzing the branch

The solution type has a common interface, which makes handling the solution similar between the different types of bifurcation problems. Tools such as interpolations are seamlessly built into the solution interface to make analysis easy. This interface is described in the ContResult.

Plotting functionality is provided by a recipe to Plots.jl. To use plot branches, simply call the plot(br) and the plotter will generate appropriate plots. Plots can be customized using all the keyword arguments provided by Plots.jl. Please see Plots.jl's documentation for more information.

diff --git a/dev/pd/index.html b/dev/pd/index.html index 00b49543..0024692f 100644 --- a/dev/pd/index.html +++ b/dev/pd/index.html @@ -2,4 +2,4 @@ Period-doubling · Bifurcation Analysis in Julia

Period-doubling point

At a period-doubling (PD) bifurcation of a periodic orbit $\gamma$ (with period $T$) for parameter value $p_0$ for the Cauchy problem

\[\frac{du}{dt}=F(u,p),\tag{E}\]

the eigenvalues (Floquet coefficients) of the monodromy operator $\mathcal M=Y(T)$ solution to

\[\frac{dY}{dt}=A(t)Y(t), Y(0)=I_n\]

contain the simple eigenvalue $\mu=-1$.

There are two ways to compute the normal form of this bifurcation

  1. using the Poincaré return map [Kuznetsov]
  2. using the method of [Iooss] see also [Kuz2]

You can obtain the normal form of a PD bifurcation using

pd = get_normal_form(br, ind; prm = false)

where prm indicates whether you want to use the method based on Poincaré return map (PRM) or the one based on Iooss method.

Normal form based on Poincaré return map

Given a transversal section $\Sigma$ to $\gamma$ at $\gamma(0)$, the Poincaré return map $\mathcal P$ associates to each point $x\in\Sigma$ close to $\gamma(0)$ the first point $\mathcal P(x,p)\in\Sigma$ where the orbit of (E) with initial condition $x$ intersects again $\Sigma$ at $\mathcal P(x,p)$. Hence, the discrete map $x_{n+1}=\mathcal P(x_n,p)$ has normal form

\[x_{n+1} = -x_n+cx_n^3+...\]

where [Kuz2]

\[c =\frac{1}{6}\left\langle p^*, \mathcal{C}(p, p, p)+3 \mathcal{B}\left(p,\left(I_{n-1}-\mathcal{A}\right)^{-1} \mathcal{B}(p, p)\right)\right\rangle\]

where $\mathcal C=d^3\mathcal P(\gamma(0))$, $\mathcal B = d^2\mathcal P(\gamma(0))$ and $\mathcal A = d\mathcal P(\gamma(0))$. Also:

\[\mathcal{A} p=-p, \mathcal{A}^{\mathrm{T}} p^*=-p^*\]

Normal form based on Iooss method

This is based on [Iooss],[Kuz2]. Suppose that the $T$ periodic orbit $\gamma(\tau)$ has a Period-Doubling bifurcation for a parameter value $p_0$. Locally, the orbits can be represented by

\[x(\tau) = \gamma(\tau)+Q_0(\tau)\xi+\Phi(\tau, \xi)\]

where

\[\left\{\begin{array}{l} \frac{d \tau}{d t}=1+a_0\cdot(p-p_0)+a \xi^2+\cdots \\ \frac{d \xi}{d \tau}=c_0\cdot(p-p_0)\xi+c \xi^3+\cdots -\end{array}\right.\]

with center manifold correction $\Phi(\tau, \xi)$ being $2T$ periodic in $\tau$ and $Q_0(\tau)$ is the Floquet operator.

References

  • Kuznetsov

    Yu. A. Kuznetsov, "Elements of Applied Bifurcation Theory", 2nd ed., 1998.

  • Kuz2

    Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”

  • Iooss

    Iooss, "Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.", 1988

+\end{array}\right.\]

with center manifold correction $\Phi(\tau, \xi)$ being $2T$ periodic in $\tau$ and $Q_0(\tau)$ is the Floquet operator.

References

  • Kuznetsov

    Yu. A. Kuznetsov, "Elements of Applied Bifurcation Theory", 2nd ed., 1998.

  • Kuz2

    Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”

  • Iooss

    Iooss, "Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.", 1988

diff --git a/dev/periodicOrbit/index.html b/dev/periodicOrbit/index.html index e606043d..562f7b8a 100644 --- a/dev/periodicOrbit/index.html +++ b/dev/periodicOrbit/index.html @@ -2,4 +2,4 @@ Introduction · Bifurcation Analysis in Julia

Periodic orbits computation

Consider the Cauchy problem

\[\frac{du}{dt}=F(u,p).\]

A periodic solution with period $T$ satisfies

\[\begin{align} \frac{du}{dt}&=F(u,p)\\ u(0)&=u(T). -\end{align}\]

We provide 4 methods for computing periodic orbits (PO):

  1. one (Trapezoid) based on finite differences to discretize a Cauchy problem,
  2. one (Collocation) based on orthogonal collocation to discretize a Cauchy problem,
  3. two (Shooting) based on the flow associated to a Cauchy problem.

It is important to understand the pro and cons of each method to compute PO in large dimensions.

Trapezoid method

The Trapezoid method (or the Collocation one) is usually faster than the ones based on Shooting but it requires more memory as it saves the whole orbit. However the main drawback of this method is that the associated linear solver is not "nice", being composed of a cyclic matrix for which no generic Matrix-free preconditioner is known. Hence, the Trapezoid method is often used with an ILU preconditioner which is severely constrained by memory. Also, when the period of the cycle is large, finer time discretization (or mesh adaptation which is not yet implemented) must be employed which is also a limiting factor both in term of memory and preconditioning.

Collocation method

The Collocation method is (for now) the slowest of the three methods implemented for computing periodic orbits. However, it is by far the most precise one. Additionally, the mesh can be automatically adapted during the continuation. The implementation will be improved for large dimensional systems like the Trapezoid method one.

Shooting method

The methods based on Shooting do not share the same drawbacks because the associated linear system is usually well conditioned, at least in the simple shooting case. There are thus often used without preconditioner at all. Even in the case of multiple shooting, this can be alleviated by a simple generic preconditioner based on deflation of eigenvalues (see Linear solvers (LS)). Also, the time stepper will automatically adapt to the stiffness of the problem, putting more time points where needed unlike the method based on finite differences which requires an adaptive (time) meshing to provide a similar property. Finally, we can use parallel Shooting to greatly increase the speed of computation.

The main drawback of the method is to find a fast time stepper, at least to compete with the method based on finite differences. The other drawback is the precision of the method which cannot compete with the collocation method.

Important notes

We regroup here some important notes which are valid for all methods above.

1. Accessing the periodic orbit

In record_from_solution, plot_solution or after the computation of a branch of periodic orbits, how do I obtain the periodic orbit, for plotting purposes for example? If x is the solution from newton for the parameter p, you can obtain the periodic orbit as follows

xtt = get_periodic_orbit(x, p)

where xtt.t contains the time mesh and xtt[:,:] contains the different components. Note that for Trapezoid and collocation methods, calling get_periodic_orbit is essentially free as it is a reshape of x. However, in the case of Shooting methods, this requires recomputing the periodic orbit which can be costly for large scale problems.

2. Finaliser

If you pass a finalise_solution function to continuation, the following occurs:

  1. If the newton solve was successful, we update the phase condition every update_section_every_step
  2. we call the user defined finalizer finalise_solution

3. Record from solution

You can pass your own function to continuation. In the particular case of periodic orbits, the method is called like record_from_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem. You can then obtain the current periodic orbit using (see above)

xtt = get_periodic_orbit(x, opt.p)

4. Plot solution

Similarly to record_from_solution, the method is called like plot_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem.

5. Most precise method for Floquet coefficients

The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.

6. Misc

set_params_po generate_ci_problem generate_solution

+\end{align}\]

We provide 4 methods for computing periodic orbits (PO):

  1. one (Trapezoid) based on finite differences to discretize a Cauchy problem,
  2. one (Collocation) based on orthogonal collocation to discretize a Cauchy problem,
  3. two (Shooting) based on the flow associated to a Cauchy problem.

It is important to understand the pro and cons of each method to compute PO in large dimensions.

Trapezoid method

The Trapezoid method (or the Collocation one) is usually faster than the ones based on Shooting but it requires more memory as it saves the whole orbit. However the main drawback of this method is that the associated linear solver is not "nice", being composed of a cyclic matrix for which no generic Matrix-free preconditioner is known. Hence, the Trapezoid method is often used with an ILU preconditioner which is severely constrained by memory. Also, when the period of the cycle is large, finer time discretization (or mesh adaptation which is not yet implemented) must be employed which is also a limiting factor both in term of memory and preconditioning.

Collocation method

The Collocation method is (for now) the slowest of the three methods implemented for computing periodic orbits. However, it is by far the most precise one. Additionally, the mesh can be automatically adapted during the continuation. The implementation will be improved for large dimensional systems like the Trapezoid method one.

Shooting method

The methods based on Shooting do not share the same drawbacks because the associated linear system is usually well conditioned, at least in the simple shooting case. There are thus often used without preconditioner at all. Even in the case of multiple shooting, this can be alleviated by a simple generic preconditioner based on deflation of eigenvalues (see Linear solvers (LS)). Also, the time stepper will automatically adapt to the stiffness of the problem, putting more time points where needed unlike the method based on finite differences which requires an adaptive (time) meshing to provide a similar property. Finally, we can use parallel Shooting to greatly increase the speed of computation.

The main drawback of the method is to find a fast time stepper, at least to compete with the method based on finite differences. The other drawback is the precision of the method which cannot compete with the collocation method.

Important notes

We regroup here some important notes which are valid for all methods above.

1. Accessing the periodic orbit

In record_from_solution, plot_solution or after the computation of a branch of periodic orbits, how do I obtain the periodic orbit, for plotting purposes for example? If x is the solution from newton for the parameter p, you can obtain the periodic orbit as follows

xtt = get_periodic_orbit(x, p)

where xtt.t contains the time mesh and xtt[:,:] contains the different components. Note that for Trapezoid and collocation methods, calling get_periodic_orbit is essentially free as it is a reshape of x. However, in the case of Shooting methods, this requires recomputing the periodic orbit which can be costly for large scale problems.

2. Finaliser

If you pass a finalise_solution function to continuation, the following occurs:

  1. If the newton solve was successful, we update the phase condition every update_section_every_step
  2. we call the user defined finalizer finalise_solution

3. Record from solution

You can pass your own function to continuation. In the particular case of periodic orbits, the method is called like record_from_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem. You can then obtain the current periodic orbit using (see above)

xtt = get_periodic_orbit(x, opt.p)

4. Plot solution

Similarly to record_from_solution, the method is called like plot_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem.

5. Most precise method for Floquet coefficients

The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.

6. Misc

set_params_po generate_ci_problem generate_solution

diff --git a/dev/periodicOrbitCollocation/index.html b/dev/periodicOrbitCollocation/index.html index 1c24719f..19811fca 100644 --- a/dev/periodicOrbitCollocation/index.html +++ b/dev/periodicOrbitCollocation/index.html @@ -1,4 +1,4 @@ -Collocation · Bifurcation Analysis in Julia

Periodic orbits based on orthogonal collocation

We compute Ntst time slices of a periodic orbit using orthogonal collocation. This is implemented in the structure PeriodicOrbitOCollProblem.

Large scale

The current implementation is optimized for ODE and for large scale problems for which the jacobian is sparse.

The general method is very well exposed in [Dankowicz],[Doedel] and we adopt the notations of [Dankowicz]. However our implementation is based on [Doedel] because it is more economical (less equations) when it enforces the continuity of the solution.

We look for periodic orbits as solutions $(x(0), T)$ of

\[\dot x = T\cdot F(x),\ x(0)=x(1)\in\mathbb R^n.\]

We focus on the differential equality and consider a partition of the time domain

\[0=\tau_{1}<\cdots<\tau_{j}<\cdots<\tau_{N_{tst}+1}=1\]

where the points are referred to as mesh points. On each mesh interval $[\tau_j,\tau_{j+1}]$ for $j=1,\cdots,N_{tst}$, we define the affine transformation

\[\tau=\tau^{(j)}(\sigma):=\tau_{j}+\frac{(1+\sigma)}{2}\left(\tau_{j+1}-\tau_{j}\right), \sigma \in[-1,1].\]

The functions $x^{(j)}$ defined on $[-1,1]$ by $x^{(j)}(\sigma) \equiv x(\tau_j(\sigma))$ satisfies the following equation on $[-1,1]$:

\[\dot x^{(j)} = T\frac{\tau_{j+1}-\tau_j}{2}\cdot F(x^{(j)})\tag{$E_j$}\]

with the continuity equation $x^{(j+1)}(-1) = x^{(j)}(1)$.

We now aim at solving $(E_j)$ by using an approximation with a polynomial of degree $m$. Following [Dankowicz], we define a (uniform) partition:

\[-1=\sigma_{1}<\cdots<\sigma_{i}<\cdots<\sigma_{m+1}=1.\]

The points $\tau_{i,j} = \tau^{(i)}(\sigma_j)$ are called the base points: they serve as collocation points.

The associated $m+1$ Lagrange polynomials of degree $m$ are:

\[\mathcal{L}_{i}(\sigma):=\prod_{k=1, k \neq i}^{m+1} \frac{\sigma-\sigma_{k}}{\sigma_{i}-\sigma_{k}}, i=1, \ldots, m+1.\]

We then introduce the approximation $p_j$ of $x^{(j)}$:

\[\mathcal p_j(\sigma)\equiv \sum\limits_{k=1}^{m+1}\mathcal L_k(\sigma)x_{j,k}\]

and the problem to be solved at the nodes $z_l$, $l=1,\cdots,m$:

\[\forall 1\leq l\leq m,\quad 1\leq j\leq N_{tst},\quad \dot p_j(z_l) = T\frac{\tau_{j+1}-\tau_j}{2}\cdot F(p_j(z_l))\tag{$E_j^2$}.\]

The nodes $(z_l)$ are associated with a Gauss–Legendre quadrature.

In order to have a unique solution, we need to remove the phase freedom. This is done by imposing a phase condition.

Number of unknowns

Putting the period unknown aside, we have to find the $x_{j,k}$ which gives $n\times N_{tst}\times (m+1)$ unknowns.

The equations $E_j^2$ provides $n\times N_{tst}\times m$ plus the $(N_{tst}-1)\times n$ equations for the continuity equations. This makes a total of $(N_{tst}-1)\times m\times n+n\times N_{tst}\times m = n[N_{tst}(m+1)-1]$ equations to which we add the $n$ equations for the periodic boundary condition. In total, we have

\[n\times N_{tst}\times (m+1)\]

equations which matches the number of unknowns.

Phase condition

To ensure uniqueness of the solution to the functional, we add the following phase condition

\[\frac{1}{T} \int_{0}^{T}\left\langle x(s), \dot x_0(s)\right\rangle d s =0\]

During continuation at step $k$, we use $\frac{1}{T} \int_{0}^{T}\left\langle x(s), \dot x_{k-1}(s)\right\rangle d s$

Interpolation

BifurcationKit.POSolutionType

Structure to encode the solution associated to a functional like ::PeriodicOrbitOCollProblem or ::ShootingProblem. In the particular case of ::PeriodicOrbitOCollProblem, this allows to use the collocation polynomials to interpolate the solution. Hence, if sol::POSolution, one can call

sol = BifurcationKit.POSolution(prob_coll, x)
-sol(t)

on any time t.

Mesh adaptation

The goal of this method[Russell] is to adapt the mesh $\tau_i$ in order to minimize the error. It is particularly helpful near homoclinic solutions where the period diverge. It can also be useful in order to use a smaller $N_{tst}$.

Encoding of the functional

The functional is encoded in the composite type PeriodicOrbitOCollProblem. See the link for more information, in particular on how to access the underlying functional, its jacobian...

Jacobian and linear solvers

We provide many different linear solvers to take advantage of the formulations or the dimensionality. These solvers are available through the argument jacobian in the constructor of PeriodicOrbitOCollProblem. For example, you can pass jacobian = FullSparse(). Note that all the internal solvers and jacobian are set up automatically, you don't need to do anything. However, for the sake of explanation, we detail how this works.

1. AutoDiffDenseAnalytical()

The jacobian is computed with an analytical formula, works for dense matrices. This is the default algorithm.

2. AutoDiffDense()

The jacobian is computed with automatic differentiation, works for dense matrices. Can be used for debugging.

3. FullSparse()

The jacobian is computed with an analytical formula, works for sparse matrices.

3. FullSparseInplace()

The jacobian is computed in place, limiting memory allocations, with an analytical formula when the sparsity of the jacobian of the vector field is constant. This is much faster than FulSparse().

Floquet multipliers computation

We provide three methods to compute the Floquet coefficients.

  • The algorithm (Default) FloquetColl is based on the condensation of parameters described in [Doedel]. It is the fastest method.
  • The algorithm FloquetCollGEV is a simplified version of the procedure described in [Fairgrieve]. It boils down to solving a large generalized eigenvalue problem. There is clearly room for improvements here but this can be used to check the results of the previous method.

These methods allow to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. However they may be imprecise[Lust].

  • The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.

Computation with newton

BifurcationKit.newtonMethod
newton(probPO, orbitguess, options; kwargs...)
-

This is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.

Arguments

Similar to newton except that prob is a PeriodicOrbitOCollProblem.

  • prob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.
  • orbitguess a guess for the periodic orbit.
  • options same as for the regular newton method.

Optional argument

  • jacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG
    • For AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.
    • For AutoDiffDenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.

We provide a simplified call to newton to locate the periodic orbits. newton will look for prob.jacobian in order to select the requested way to compute the jacobian.

The docs for this specific newton are located at newton.

Continuation

We refer to continuation for more information regarding the arguments. continuation will look for prob.jacobian in order to select the requested way to compute the jacobian.

References

  • Dankowicz

    Dankowicz, Harry, and Frank Schilder. Recipes for Continuation. Computational Science and Engineering Series. Philadelphia: Society for Industrial and Applied Mathematics, 2013.

  • Doedel

    Doedel, Eusebius, Herbert B. Keller, and Jean Pierre Kernevez. “NUMERICAL ANALYSIS AND CONTROL OF BIFURCATION PROBLEMS (II): BIFURCATION IN INFINITE DIMENSIONS.” International Journal of Bifurcation and Chaos 01, no. 04 (December 1991): 745–72.

  • Fairgrieve

    Fairgrieve, Thomas F., and Allan D. Jepson. “O. K. Floquet Multipliers.” SIAM Journal on Numerical Analysis 28, no. 5 (October 1991): 1446–62. https://doi.org/10.1137/0728075.

  • Russell

    Russell, R. D., and J. Christiansen. “Adaptive Mesh Selection Strategies for Solving Boundary Value Problems.” SIAM Journal on Numerical Analysis 15, no. 1 (February 1978): 59–80. https://doi.org/10.1137/0715004.

  • Lust

    Lust, Kurt. “Improved Numerical Floquet Multipliers.” International Journal of Bifurcation and Chaos 11, no. 09 (September 2001): 2389–2410. https://doi.org/10.1142/S0218127401003486.

+Collocation · Bifurcation Analysis in Julia

Periodic orbits based on orthogonal collocation

We compute Ntst time slices of a periodic orbit using orthogonal collocation. This is implemented in the structure PeriodicOrbitOCollProblem.

Large scale

The current implementation is optimized for ODE and for large scale problems for which the jacobian is sparse.

The general method is very well exposed in [Dankowicz],[Doedel] and we adopt the notations of [Dankowicz]. However our implementation is based on [Doedel] because it is more economical (less equations) when it enforces the continuity of the solution.

We look for periodic orbits as solutions $(x(0), T)$ of

\[\dot x = T\cdot F(x),\ x(0)=x(1)\in\mathbb R^n.\]

We focus on the differential equality and consider a partition of the time domain

\[0=\tau_{1}<\cdots<\tau_{j}<\cdots<\tau_{N_{tst}+1}=1\]

where the points are referred to as mesh points. On each mesh interval $[\tau_j,\tau_{j+1}]$ for $j=1,\cdots,N_{tst}$, we define the affine transformation

\[\tau=\tau^{(j)}(\sigma):=\tau_{j}+\frac{(1+\sigma)}{2}\left(\tau_{j+1}-\tau_{j}\right), \sigma \in[-1,1].\]

The functions $x^{(j)}$ defined on $[-1,1]$ by $x^{(j)}(\sigma) \equiv x(\tau_j(\sigma))$ satisfies the following equation on $[-1,1]$:

\[\dot x^{(j)} = T\frac{\tau_{j+1}-\tau_j}{2}\cdot F(x^{(j)})\tag{$E_j$}\]

with the continuity equation $x^{(j+1)}(-1) = x^{(j)}(1)$.

We now aim at solving $(E_j)$ by using an approximation with a polynomial of degree $m$. Following [Dankowicz], we define a (uniform) partition:

\[-1=\sigma_{1}<\cdots<\sigma_{i}<\cdots<\sigma_{m+1}=1.\]

The points $\tau_{i,j} = \tau^{(i)}(\sigma_j)$ are called the base points: they serve as collocation points.

The associated $m+1$ Lagrange polynomials of degree $m$ are:

\[\mathcal{L}_{i}(\sigma):=\prod_{k=1, k \neq i}^{m+1} \frac{\sigma-\sigma_{k}}{\sigma_{i}-\sigma_{k}}, i=1, \ldots, m+1.\]

We then introduce the approximation $p_j$ of $x^{(j)}$:

\[\mathcal p_j(\sigma)\equiv \sum\limits_{k=1}^{m+1}\mathcal L_k(\sigma)x_{j,k}\]

and the problem to be solved at the nodes $z_l$, $l=1,\cdots,m$:

\[\forall 1\leq l\leq m,\quad 1\leq j\leq N_{tst},\quad \dot p_j(z_l) = T\frac{\tau_{j+1}-\tau_j}{2}\cdot F(p_j(z_l))\tag{$E_j^2$}.\]

The nodes $(z_l)$ are associated with a Gauss–Legendre quadrature.

In order to have a unique solution, we need to remove the phase freedom. This is done by imposing a phase condition.

Number of unknowns

Putting the period unknown aside, we have to find the $x_{j,k}$ which gives $n\times N_{tst}\times (m+1)$ unknowns.

The equations $E_j^2$ provides $n\times N_{tst}\times m$ plus the $(N_{tst}-1)\times n$ equations for the continuity equations. This makes a total of $(N_{tst}-1)\times m\times n+n\times N_{tst}\times m = n[N_{tst}(m+1)-1]$ equations to which we add the $n$ equations for the periodic boundary condition. In total, we have

\[n\times N_{tst}\times (m+1)\]

equations which matches the number of unknowns.

Phase condition

To ensure uniqueness of the solution to the functional, we add the following phase condition

\[\frac{1}{T} \int_{0}^{T}\left\langle x(s), \dot x_0(s)\right\rangle d s =0\]

During continuation at step $k$, we use $\frac{1}{T} \int_{0}^{T}\left\langle x(s), \dot x_{k-1}(s)\right\rangle d s$

Discretization of the BVP and jacobian

We only focus on the differential part. Summing up, we obtained the following equations for the $x_{j,l}\in\mathbb R^n$:

\[\sum\limits_{k=1}^{m+1}\mathcal L_k'(z_l)x_{j,k} = F\left(\sum\limits_{k=1}^{m+1}\mathcal L_k(z_l)x_{j,k}\right)\]

The jacobian in the case $m=2$ is given by:

$x_{0,0}$$x_{0,1}$$x_{1,0}$$x_{1,1}$$x_{2,0}$$x_{2,1}$$x_{3,0}$T
$H_{0,0}^0$$H_{0,1}^0$$H_{1,0}^0$*
$H_{0,0}^1$$H_{0,1}^1$$H_{1,0}^1$*
$H_{1,0}^0$$H_{1,1}^0$$H_{2,0}^0$*
$H_{1,0}^1$$H_{1,1}^1$$H_{2,0}^1$*
$H_{2,0}^0$$H_{2,1}^0$$H_{3,0}^0$*
$H_{2,0}^1$$H_{2,1}^1$$H_{3,0}^1$*
$I$$-I$*
********

where

\[H_{k,l}^{l_2} = \mathcal L'_{l_2,l}\cdot I_n - T\frac{\tau_{j+1}-\tau_j}{2}\cdot\mathcal L_{l_2,l}\cdot dF\left(x_{k,l}\right).\]

Interpolation

BifurcationKit.POSolutionType

Structure to encode the solution associated to a functional like ::PeriodicOrbitOCollProblem or ::ShootingProblem. In the particular case of ::PeriodicOrbitOCollProblem, this allows to use the collocation polynomials to interpolate the solution. Hence, if sol::POSolution, one can call

sol = BifurcationKit.POSolution(prob_coll, x)
+sol(t)

on any time t.

Mesh adaptation

The goal of this method[Russell] is to adapt the mesh $\tau_i$ in order to minimize the error. It is particularly helpful near homoclinic solutions where the period diverge. It can also be useful in order to use a smaller $N_{tst}$.

Encoding of the functional

The functional is encoded in the composite type PeriodicOrbitOCollProblem. See the link for more information, in particular on how to access the underlying functional, its jacobian...

Jacobian and linear solvers

We provide many different linear solvers to take advantage of the formulations or the dimensionality. These solvers are available through the argument jacobian in the constructor of PeriodicOrbitOCollProblem. For example, you can pass jacobian = FullSparse(). Note that all the internal solvers and jacobian are set up automatically, you don't need to do anything. However, for the sake of explanation, we detail how this works.

1. DenseAnalytical()

The jacobian is computed with an analytical formula, works for dense matrices. This is the default algorithm.

2. AutoDiffDense()

The jacobian is computed with automatic differentiation, works for dense matrices. Can be used for debugging.

3. FullSparse()

The jacobian is computed with an analytical formula, works for sparse matrices.

3. FullSparseInplace()

The jacobian is computed in place, limiting memory allocations, with an analytical formula when the sparsity of the jacobian of the vector field is constant. This is much faster than FulSparse().

Floquet multipliers computation

We provide two methods to compute the Floquet coefficients.

  • The algorithm (Default) FloquetColl is based on the condensation of parameters described in [Doedel]. It is the fastest method.
  • The algorithm FloquetCollGEV is a simplified version of the procedure described in [Fairgrieve]. It boils down to solving a large generalized eigenvalue problem. There is clearly room for improvements here but this can be used to check the results of the previous method.

These methods allow to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. However they may be imprecise[Lust].

  • The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.

Computation with newton

BifurcationKit.newtonMethod
newton(probPO, orbitguess, options; kwargs...)
+

This is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.

Arguments

Similar to newton except that prob is a PeriodicOrbitOCollProblem.

  • prob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.
  • orbitguess a guess for the periodic orbit.
  • options same as for the regular newton method.

Optional argument

  • jacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG
    • For AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.
    • For DenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.

We provide a simplified call to newton to locate the periodic orbits. newton will look for prob.jacobian in order to select the requested way to compute the jacobian.

The docs for this specific newton are located at newton.

Continuation

We refer to continuation for more information regarding the arguments. continuation will look for prob.jacobian in order to select the requested way to compute the jacobian.

References

  • Dankowicz

    Dankowicz, Harry, and Frank Schilder. Recipes for Continuation. Computational Science and Engineering Series. Philadelphia: Society for Industrial and Applied Mathematics, 2013.

  • Doedel

    Doedel, Eusebius, Herbert B. Keller, and Jean Pierre Kernevez. “NUMERICAL ANALYSIS AND CONTROL OF BIFURCATION PROBLEMS (II): BIFURCATION IN INFINITE DIMENSIONS.” International Journal of Bifurcation and Chaos 01, no. 04 (December 1991): 745–72.

  • Fairgrieve

    Fairgrieve, Thomas F., and Allan D. Jepson. “O. K. Floquet Multipliers.” SIAM Journal on Numerical Analysis 28, no. 5 (October 1991): 1446–62. https://doi.org/10.1137/0728075.

  • Russell

    Russell, R. D., and J. Christiansen. “Adaptive Mesh Selection Strategies for Solving Boundary Value Problems.” SIAM Journal on Numerical Analysis 15, no. 1 (February 1978): 59–80. https://doi.org/10.1137/0715004.

  • Lust

    Lust, Kurt. “Improved Numerical Floquet Multipliers.” International Journal of Bifurcation and Chaos 11, no. 09 (September 2001): 2389–2410. https://doi.org/10.1142/S0218127401003486.

diff --git a/dev/periodicOrbitShooting/index.html b/dev/periodicOrbitShooting/index.html index f8f0efa5..4553c8e5 100644 --- a/dev/periodicOrbitShooting/index.html +++ b/dev/periodicOrbitShooting/index.html @@ -35,4 +35,4 @@ plot_solution, kwargs... ) -

This is the continuation method for computing a periodic orbit using a (Standard / Poincaré) Shooting method.

Arguments

Similar to continuation except that probPO is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.

Optional arguments

  • eigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD
  • jacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG
    • For MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.
    • For FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.
    • For AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
    • For FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.

References

  • Lust

    Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust Kurt, 1997.

  • Umbria

    J. S. Umbría and M. Net. Numerical continuation methods for large-scale dissipative dynamical systems. The European Physical Journal Special Topics, 225(13):2465–2486, 2016.

+

This is the continuation method for computing a periodic orbit using a (Standard / Poincaré) Shooting method.

Arguments

Similar to continuation except that probPO is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.

Optional arguments

  • eigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD
  • jacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG
    • For MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
    • For AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.
    • For FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.
    • For AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.
    • For FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.

References

  • Lust

    Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust Kurt, 1997.

  • Umbria

    J. S. Umbría and M. Net. Numerical continuation methods for large-scale dissipative dynamical systems. The European Physical Journal Special Topics, 225(13):2465–2486, 2016.

diff --git a/dev/periodicOrbitTrapeze/index.html b/dev/periodicOrbitTrapeze/index.html index 742572a2..0158fa3d 100644 --- a/dev/periodicOrbitTrapeze/index.html +++ b/dev/periodicOrbitTrapeze/index.html @@ -28,4 +28,4 @@ linear_algo, kwargs... ) -

This is the continuation routine for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.

Arguments

  • prob::PeriodicOrbitTrapProblem encodes the functional G
  • orbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It could be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.
  • alg continuation algorithm
  • contParams same as for the regular continuation method

Keyword arguments

Specify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.

  • For jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.
  • For jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.
  • For jacobian = :DenseAD, evaluate the jacobian using ForwardDiff
  • For jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.
  • For jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.
  • For jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.
  • For jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.

Note that by default, the method prints the period of the periodic orbit as function of the parameter. This can be changed by providing your record_from_solution argument.

References

  • Uecker

    Uecker, Hannes. Hopf Bifurcation and Time Periodic Orbits with Pde2path – Algorithms and Applications. Communications in Computational Physics 25, no. 3 (2019)

  • Lust

    Lust, Kurt, Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, PhD thesis, 1997.

+

This is the continuation routine for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.

Arguments

  • prob::PeriodicOrbitTrapProblem encodes the functional G
  • orbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It could be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.
  • alg continuation algorithm
  • contParams same as for the regular continuation method

Keyword arguments

Specify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.

  • For jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.
  • For jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.
  • For jacobian = :DenseAD, evaluate the jacobian using ForwardDiff
  • For jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.
  • For jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.
  • For jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.
  • For jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.
  • For jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.

Note that by default, the method prints the period of the periodic orbit as function of the parameter. This can be changed by providing your record_from_solution argument.

References

  • Uecker

    Uecker, Hannes. Hopf Bifurcation and Time Periodic Orbits with Pde2path – Algorithms and Applications. Communications in Computational Physics 25, no. 3 (2019)

  • Lust

    Lust, Kurt, Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, PhD thesis, 1997.

diff --git a/dev/plotting/index.html b/dev/plotting/index.html index 986e23f2..1d07156b 100644 --- a/dev/plotting/index.html +++ b/dev/plotting/index.html @@ -18,4 +18,4 @@ prob = BifurcationProblem(F, [0.8], 1., (@lens _); record_from_solution = (x,p) -> x[1]) opts = ContinuationPar(dsmax = 0.1, dsmin = 1e-3, ds = -0.001, p_min = -1., p_max = 1.) br = continuation(prob, PALC(), opts) -BifurcationKit.plot(br) +BifurcationKit.plot(br) diff --git a/dev/search/index.html b/dev/search/index.html index f070a800..ef88346c 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · Bifurcation Analysis in Julia

Loading search...

    +Search · Bifurcation Analysis in Julia

    Loading search...

      diff --git a/dev/search_index.js b/dev/search_index.js index 17557817..744f0875 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"bt/#Normal-form-of-the-Bogdanov-Takens-bifurcation","page":"Bogdanov-Takens","title":"Normal form of the Bogdanov-Takens bifurcation","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We follow the book[Haragus] and consider a Cauchy problem","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"dot x=mathbf F(xp)","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"mathbfL zeta_0=0 quad mathbfL zeta_1=zeta_0","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We can also select a basis:","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"mathbfL^* zeta_1^*=0 quad mathbfL^* zeta_0^*=zeta_1^*","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"such that","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"leftlanglezeta_0 zeta_0^*rightrangle=1 quadleftlanglezeta_1 zeta_0^*rightrangle=0 quadleftlanglezeta_0 zeta_1^*rightrangle=0 quadleftlanglezeta_1 zeta_1^*rightrangle=1","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"Under some conditions, x(t)approx x_0+A(t)zeta_0 + B(t)zeta_1 where AB satisfy the normal form:","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\nfracd Ad t=B \nfracd Bd t=alpha_1(mu)+alpha_2(mu) A+alpha_3(mu) B+b A B+a A^2widetilderho(A B mu)\nendalignedtagE","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"where p = p_0+mu and with coefficients","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\na=leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_1^*rightrangle \nb=leftlangle 2 mathbfF_20left(zeta_0 zeta_1right)-2 Psi_200 zeta_1^*rightrangle\nendaligned","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"The Psis satisfy","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\na zeta_1 =mathbfL Psi_200+mathbfF_20left(zeta_0 zeta_0right) \nb zeta_1+2 Psi_200 =mathbfL Psi_110+2 mathbfF_20left(zeta_0 zeta_1right) \nPsi_110 =mathbfL Psi_020+mathbfF_20left(zeta_1 zeta_1right)\nendaligned","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"which gives","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"0=leftlanglePsi_200 zeta_1^*rightrangle + leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_0^*rightrangle","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We conclude that","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\na=leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_1^*rightrangle \nb=2leftlangle mathbfF_20left(zeta_0 zeta_1right) zeta_1^*rightrangle + 2leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_0^*rightrangle\nendaligned","category":"page"},{"location":"bt/#Computation-of-the-basis","page":"Bogdanov-Takens","title":"Computation of the basis","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"To build the basis leftzeta_0 zeta_1right, we follow the procedure described in [AlHdaibat] on page 972.","category":"page"},{"location":"bt/#Computation-of-the-parameter-transform","page":"Bogdanov-Takens","title":"Computation of the parameter transform","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"To invert the mapping muto (alpha_1(mu)alpha_2(mu)alpha_3(mu)), we follow the procedure described in [AlHdaibat] on page 956 forward.","category":"page"},{"location":"bt/#Normal-form-computation","page":"Bogdanov-Takens","title":"Normal form computation","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"get_normal_form(br::ContResult, ind_bif::Int ;\n\tnev = 5, verbose = false, ζs = nothing, autodiff = true, detailed = true)","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The option detailed controls the computation of a simplified version of the normal form. autodiff controls the use of ForwardDiff during the normal form computation.","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BogdanovTakens.","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"bt/#References","page":"Bogdanov-Takens","title":"References","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"[Haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"[AlHdaibat]: Al-Hdaibat, B., W. Govaerts, Yu. A. Kuznetsov, and H. G. E. Meijer. “Initialization of Homoclinic Solutions near Bogdanov–Takens Points: Lindstedt–Poincaré Compared with Regular Perturbation Method.” SIAM Journal on Applied Dynamical Systems 15, no. 2 (January 2016): 952–80. https://doi.org/10.1137/15M1017491.","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/#Neural-mass-equation","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"The following model is taken from [Cortes]:","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"leftbeginarrayl\ntau dotE=-E+gleft(J u x E+E_0right) \ndotx=tau_D^-1(1-x)-u E x \ndotu=U E(1-u)-tau_F^-1(u-U)\nendarrayright","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"We use this model as a mean to introduce the basics of BifurcationKit.jl, namely the continuation of equilibria.","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# vector field\nfunction TMvf(z, p)\n\t@unpack J, α, E0, τ, τD, τF, U0 = p\n\tE, x, u = z\n\tSS0 = J * u * x * E + E0\n\tSS1 = α * log(1 + exp(SS0 / α))\n\t[\n\t (-E + SS1) / τ,\n (1.0 - x) / τD - u * x * E,\n\t (U0 - u) / τF + U0 * (1.0 - u) * E\n\t]\nend\n\n# parameter values\npar_tm = (α = 1.5, τ = 0.013, J = 3.07, E0 = -2.0, τD = 0.200, U0 = 0.3, τF = 1.5, τS = 0.007)\n\n# initial condition\nz0 = [0.238616, 0.982747, 0.367876]\n\n# Bifurcation Problem\nprob = BifurcationProblem(TMvf, z0, par_tm, (@lens _.E0);\n\trecord_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]),)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"We first compute the branch of equilibria ","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"# continuation options, we limit the parameter range for E0\nopts_br = ContinuationPar(p_min = -4.0, p_max = -0.9)\n\n# continuation of equilibria\nbr = continuation(prob, PALC(), opts_br;\n\t# we want to compute both sides of the branch of the initial\n\t# value of E0 = -2\n\tbothside = true)\n\nscene = plot(br, legend=:topleft)","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"br","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"If you don't want to compute just the branch without the bifurcations (more information is provided here ), change the continuation options to","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"opts_br = ContinuationPar(p_min = -4.0, p_max = -0.9,\n\tdetect_bifurcation = 0)\n\t\n# continuation of equilibria\nbr = continuation(prob, PALC(), opts_br;\n\t# we want to compute both sides of the branch of the initial\n\t# value of E0 = -2\n\tbothside = true)\n\nscene = plot(br, plotfold=true)","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/#References","page":"🟢 Neural mass equation","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"[Cortes]: Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.","category":"page"},{"location":"tutorials/BrusselatorFF/#Brusselator-1d-with-periodic-BC-using-FourierFlows.jl","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"Pages = [\"BrusselatorFF.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"info: Acknowledgment\nThe example was done in collaboration with Navid C. Constantinou. ","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We look at the Brusselator in 1d, see [Tzou]. The equations are","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"beginaligned frac partial u partial t = D frac partial ^ 2 u partial z ^ 2 + u ^ 2 v - ( B + 1 ) u + E frac partial v partial t = frac partial ^ 2 v partial z ^ 2 + B u - u ^ 2 v endalignedtagE","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"with periodic boundary conditions. These equations have been introduced to reproduce an oscillating chemical reaction.","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We focus on computing a snaking branch of periodic orbits using spectral methods implemented in Brusselator.jl:","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"using Revise, BifurcationKit\nusing Brusselator, Plots, Parameters, ForwardDiff, LinearAlgebra, Setfield, DiffEqBase\nusing FFTW: irfft\nconst BK = BifurcationKit\n\ndev = CPU()\t\t\t\t\t# Device (CPU/GPU)\n\nnx = 512\t\t\t\t# grid resolution\nstepper = \"FilteredRK4\"\t\t# timestepper\ndt \t= 0.01\t\t# timestep\nnsteps = 9000\t\t# total number of time-steps\nnsubs\t= 20\t\t# number of time-steps for intermediate logging/plotting (nsteps must be multiple of nsubs)\n\n# parameters for the model used by Tzou et al. (2013)\nE = 1.4\nL = 137.37\t\t\t\t # Domain length\nε = 0.1\nμ = 25\nρ = 0.178\n\nD_c = ((sqrt(1 + E^2) - 1) / E)^2\nB_H = (1 + E * sqrt(D_c))^2\n\nB = B_H + ε^2 * μ\nD = D_c + ε^2 * ρ\n\nkc = sqrt(E / sqrt(D))\n\n# building the model\ngrid = OneDGrid(dev, nx, L)\nparams = Brusselator.Params(B, D, E)\nvars = Brusselator.Vars(dev, grid)\nequation = Brusselator.Equation(dev, params, grid)\nprob = FourierFlows.Problem(equation, stepper, dt, grid, vars, params, dev)\n\nget_u(prob) = irfft(prob.sol[:, 1], prob.grid.nx)\nget_v(prob) = irfft(prob.sol[:, 2], prob.grid.nx)\nu_solution = Diagnostic(get_u, prob; nsteps=nsteps+1)\ndiags = [u_solution]","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We now integrate the model to find a periodic orbit:","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"l = 28\nθ = @. (grid.x > -l/2) & (grid.x < l/2)\n\nau, av = -(E^2 + kc^2) / B, -1\ncu, cv = -E * (E + im) / B, 1\n\n# initial condition\nu0 = @.\t E + ε * real( au * exp(im * kc * grid.x) * θ + cu * (1 - θ) )\nv0 = @. B/E + ε * real( av * exp(im * kc * grid.x) * θ + cv * (1 - θ) )\nset_uv!(prob, u0, v0)\n\nplot_output(prob)\n\n# move forward in time to capture the periodic orbit\nfor j=0:Int(nsteps/nsubs)\n\tupdatevars!(prob)\n\tstepforward!(prob, diags, nsubs)\nend\n\n# estimate of the periodic orbit, will be used as initial condition for a Krylov-Newton\ninitpo = copy(vcat(vcat(prob.vars.u, prob.vars.v), 4.9))\n\nusing RecursiveArrayTools\n\nt = u_solution.t[1:10:nsteps]\nU_xt = reduce(hcat, [ u_solution.data[j] for j=1:10:nsteps ])\nheatmap(grid.x, t, U_xt', c = :viridis, clims = (1, 3))","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"which gives","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"(Image: )","category":"page"},{"location":"tutorials/BrusselatorFF/#Building-the-Shooting-problem","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"Building the Shooting problem","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We compute the periodic solution of (E) with a shooting algorithm. We thus define a function to compute the flow and its differential.","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# update the states\nfunction _update!(out, pb::FourierFlows.Problem, N)\n\tout[1:N] .= pb.vars.u\n\tout[N+1:end] .= pb.vars.v\n\tout\nend\n\n# update the parameters in pb\nfunction _setD!(D, pb::FourierFlows.Problem)\n\tpb.eqn.L[:, 1] .*= D / prob.params.D\n\tpb.params.D = D\nend\n\n# compute the flow from x up to time t\nfunction ϕ(x, p, t)\n\t@unpack pb, D, N = p\n\t_setD!(D, pb)\n\n\t# set initial condition\n\t@views set_uv!(pb, x[1:N], x[N+1:2N])\n\tpb.clock.t=0.; pb.clock.step=0\n\t# determine number of time steps\n\tdt = pb.clock.dt\n\tnsteps = div(t, dt) |> Int\n\t# compute flow\n\tstepforward!(pb, nsteps)\n\n\trest = t - nsteps * dt\n\tdt = pb.clock.dt\n\tpb.clock.dt = rest\n\tstepforward!(pb, 1)\n\tpb.clock.dt = dt\n\tupdatevars!(pb)\n\tout = similar(x)\n\t_update!(out, pb, N)\n\treturn (t=t, u=out)\nend\n\n# differential of the flow by FD\nfunction dϕ(x, p, dx, t; δ = 1e-8)\n\tphi = ϕ(x, p, t).u\n\tdphi = (ϕ(x .+ δ .* dx, p, t).u .- phi) ./ δ\n\treturn (t=t, u=phi, du=dphi)\nend","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We also need the vector field","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"function vf(x, p)\n\t@unpack pb, D, N = p\n\t# set parameter in prob\n\tpb.eqn.L[:, 1] .*= D / pb.params.D\n\tpb.params.D = D\n\tu = @view x[1:N]\n\tv = @view x[N+1:end]\n\t# set initial condition\n\tset_uv!(pb, u, v)\n\trhs = Brusselator.get_righthandside(pb)\n\t# rhs is in Fourier space, put back to real space\n\tout = similar(x)\n\tldiv!((@view out[1:N]), pb.grid.rfftplan, rhs[:, 1])\n\tldiv!((@view out[N+1:end]), pb.grid.rfftplan, rhs[:, 2])\n\treturn out\nend","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We then specify the shooting problem","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# parameters to be passed to ϕ\npar_bru = (pb = prob, N = nx, nsubs = nsubs, D = D)\n\n# example of vector passed to ϕ\nx0 = vcat(u0,v0)\n\n# here we define the problem which encodes the standard shooting\nflow = Flow(vf, ϕ, dϕ)\n\n# the first section is centered around a stationary state\n_center = vcat(E*ones(nx), B/E*ones(nx))\n\n# section for the flow\nsectionBru = BK.SectionSS(vf(initpo[1:end-1], par_bru), _center)\nprobSh = ShootingProblem(M = 1, flow = flow, ds = diff(LinRange(0, 1, 1 + 1)), section = sectionBru, par = par_bru, lens = (@lens _.D), jacobian = :FiniteDifferences)","category":"page"},{"location":"tutorials/BrusselatorFF/#Finding-a-periodic-orbit","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"Finding a periodic orbit","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# linear solver for the Shooting problem\nls = GMRESIterativeSolvers(N = 2nx+1, reltol = 1e-4)\n\n# parameters for Krylov-Newton\noptn = NewtonPar(tol = 1e-9, verbose = true,\n\t# linear solver\n\tlinsolver = ls,\n\t# eigen solver\n\teigsolver = EigKrylovKit(dim = 30, x₀ = rand(2nx), verbose = 1 )\n\t)\n\n# Newton-Krylov method to check convergence and tune parameters\nsolp = @time newton(probSh, initpo, optn,\n\tnormN = x->norm(x,Inf))","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"and you should see (the guess was not that good)","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.6216e+03 │ 0 │\n│ 1 │ 4.4376e+01 │ 6 │\n│ 2 │ 9.0109e-01 │ 15 │\n│ 3 │ 4.9044e-02 │ 32 │\n│ 4 │ 4.1139e-03 │ 27 │\n│ 5 │ 6.0704e-03 │ 33 │\n│ 6 │ 2.4721e-04 │ 33 │\n│ 7 │ 3.7889e-05 │ 34 │\n│ 8 │ 6.6836e-07 │ 31 │\n│ 9 │ 2.0295e-09 │ 39 │\n│ 10 │ 2.1685e-12 │ 41 │\n└─────────────┴──────────────────────┴────────────────┘\n 83.615047 seconds (284.31 M allocations: 24.250 GiB, 6.28% gc time)","category":"page"},{"location":"tutorials/BrusselatorFF/#Computation-of-the-snaking-branch","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"Computation of the snaking branch","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# you can detect bifurcations with the option detect_bifurcation = 3\noptc = ContinuationPar(newton_options = optn, ds = -1e-3, dsmin = 1e-7, dsmax = 2e-3, p_max = 0.295, plot_every_step = 2, max_steps = 1000, detect_bifurcation = 0)\nbd = continuation(probSh,\n\tsolp, PALC(bls = MatrixFreeBLS(@set ls.N = 2nx+2)), optc;\n\tplot = true,\n\tverbosity = 3,\n\tplot_solution = (x,p ; kw...) -> plot!(x[1:nx];kw...),\n\tnormC = x->norm(x,Inf))","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"which leads to","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"(Image: )","category":"page"},{"location":"tutorials/BrusselatorFF/#References","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"References","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"[Tzou]: Tzou, J. C., Y.-P. Ma, A. Bayliss, B. J. Matkowsky, and V. A. Volpert. Homoclinic Snaking near a Codimension-Two Turing-Hopf Bifurcation Point in the Brusselator Model.” Physical Review E 87, no. 2 (February 14, 2013): 022908. https://doi.org/10.1103/PhysRevE.87.022908.","category":"page"},{"location":"tutorials/tutorialsPD/#Period-doubling-in-the-Barrio-Varea-Aragon-Maini-model","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"","category":"section"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"Pages = [\"tutorialsPD.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"The purpose of this example is to show how to handle period doubling bifurcations of periodic orbits. Note that we do not use automatic branch switching here although this is possible (but not yet for branching from period doubling points).","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"unknown: References\nThis example is taken from Aragón, J. L., R. A. Barrio, T. E. Woolley, R. E. Baker, and P. K. Maini. “Nonlinear Effects on Turing Patterns: Time Oscillations and Chaos.” Physical Review E 86, no. 2 (2012)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"info: Method and performance\nWe focus on the Shooting method but we could have based the computation of periodic orbits on finite differences instead. Performances of the current tutorial are directly linked to the ones of DifferentialEquations.jl. ","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We focus on the following 1D model:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"tagEbeginaligned\nfracpartial upartial t=D nabla^2 u+etaleft(u+a v-C u v-u v^2right)\nfracpartial vpartial t=nabla^2 v+etaleft(b v+H u+C u v+u v^2right)\nendaligned","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"with Neumann boundary conditions. We start by encoding the model","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"using Revise\nusing DiffEqOperators, ForwardDiff, DifferentialEquations, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\nf(u, v, p) = p.η * ( u + p.a * v - p.C * u * v - u * v^2)\ng(u, v, p) = p.η * (p.H * u + p.b * v + p.C * u * v + u * v^2)\n\nfunction Laplacian(N, lx, bc = :Dirichlet)\n\thx = 2lx/N\n\tD2x = CenteredDifference(2, 2, hx, N)\n\tif bc == :Neumann\n\t\tQx = Neumann0BC(hx)\n\telseif bc == :Dirichlet\n\t\tQx = Dirichlet0BC(typeof(hx))\n\tend\n\tD2xsp = sparse(D2x * Qx)[1]\nend\n\nfunction NL!(dest, u, p, t = 0.)\n\tN = div(length(u), 2)\n\tu1 = @view (u[1:N])\n\tu2 = @view (u[N+1:end])\n\tdest[1:N] .= f.(u1, u2, Ref(p))\n\tdest[N+1:end] .= g.(u1, u2, Ref(p))\n\treturn dest\nend\n\nfunction Fbr!(f, u, p)\n\tNL!(f, u, p)\n\tmul!(f, p.Δ, u,1,1)\n\tf\nend\n\nNL(u, p) = NL!(similar(u), u, p)\nFbr(x, p, t = 0.) = Fbr!(similar(x), x, p)\n\n# this is not very efficient but simple enough ;)\nJbr(x,p) = sparse(ForwardDiff.jacobian(x -> Fbr(x, p), x))","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We can now perform bifurcation of the following Turing solution:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"N = 100\nn = 2N\nlx = 3pi /2\nX = LinRange(-lx,lx, N)\n\nΔ = Laplacian(N, lx, :Neumann)\nD = 0.08\npar_br = (η = 1.0, a = -1., b = -3/2., H = 3.0, D = D, C = -0.6, Δ = blockdiag(D*Δ, Δ))\n\nu0 = 1.0 * cos.(2X)\nsolc0 = vcat(u0, u0)\n\nprobBif = BK.BifurcationProblem(Fbr, solc0, par_br, (@lens _.C) ;J = Jbr,\n\t\trecord_from_solution = (x, p) -> norm(x, Inf),\n\t\tplot_solution = (x, p; kwargs...) -> plot!(x[1:end÷2];label=\"\",ylabel =\"u\", kwargs...))\n\n# parameters for continuation\neigls = EigArpack(0.5, :LM)\nopt_newton = NewtonPar(eigsolver = eigls, verbose=true, max_iterations = 3200, tol=1e-9)\nopts_br = ContinuationPar(dsmax = 0.04, ds = -0.01, p_min = -1.8,\n\tdetect_bifurcation = 3, nev = 21, plot_every_step = 50, newton_options = opt_newton, max_steps = 400)\n\nbr = continuation(re_make(probBif, params = (@set par_br.C = -0.2)), PALC(), opts_br;\n\tplot = true, verbosity = 3)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"which yields","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsPD/#Periodic-orbits-from-the-Hopf-point-(Standard-Shooting)","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"Periodic orbits from the Hopf point (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We continue the periodic orbit form the first Hopf point around Capprox -08598 using a Standard Simple Shooting method (see Periodic orbits based on the shooting method). To this end, we define a SplitODEProblem from DifferentialEquations.jl which is convenient for solving semilinear problems of the form","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"dot x = Ax+g(x)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"where A is the infinitesimal generator of a C_0-semigroup. We use the exponential-RK scheme ETDRK2 ODE solver to compute the solution of (E) just after the Hopf point.","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"# parameters close to the Hopf bifurcation\npar_br_hopf = @set par_br.C = -0.86\n# parameters for the ODEProblem\nf1 = DiffEqArrayOperator(par_br.Δ)\nf2 = NL!\nprob_sp = SplitODEProblem(f1, f2, solc0, (0.0, 280.0), @set par_br.C = -0.86)\n\nsol = @time solve(prob_sp, ETDRK2(krylov=true); abstol=1e-14, reltol=1e-14, dt = 0.1)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We estimate the period of the limit cycle to be around Tapprox 3. We then use this as a guess for the shooting method:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"# compute the guess for the shooting method\norbitsection = Array(sol[:, end])\ninitpo = vcat(vec(orbitsection), 3.)\n\n# define the functional for the standard simple shooting based on the\n# ODE solver ETDRK2. SectionShooting implements an appropriate phase condition\nprobSh = ShootingProblem(prob_sp, ETDRK2(krylov=true),\n\t[sol(280.0)]; abstol=1e-14, reltol=1e-14, dt = 0.1,\n lens = (@lens _.C),\n jacobian = BK.FiniteDifferencesMF())\n\n# parameters for the Newton-Krylov solver\nls = GMRESIterativeSolvers(reltol = 1e-7, N = length(initpo), maxiter = 50, verbose = false)\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 120, linsolver = ls)\n# Newton-Krylov solver\nout_po_sh = @time newton(probSh, initpo, optn; normN = norminf)\nBK.converged(out_po_sh) && printstyled(color=:red, \"--> T = \", out_po_sh.u[end], \", amplitude = \", BK.getamplitude(probSh, out_po_sh.u, par_br_hopf; ratio = 2),\"\\n\")","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"which gives","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"--> T = 2.94557883943451, amplitude = 0.05791350025709674","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We can now continue this periodic orbit:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"eig = DefaultEig()\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.01, ds= 0.005, p_min = -1.8, max_steps = 170, newton_options = (@set optn.eigsolver = eig),\n\tnev = 10, tol_stability = 1e-2, detect_bifurcation = 3)\nbr_po_sh = @time continuation(probSh, out_po_sh.u, PALC(), opts_po_cont; verbosity = 3,\n\tplot = true,\n\tlinear_algo = MatrixFreeBLS(@set ls.N = probSh.M*n+2),\n plot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], 1; kwargs...),\n record_from_solution = (u, p) -> BK.getmaximum(probSh, u, (@set par_br_hopf.C = p.p); ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We plot the result using plot(br_po_sh, br, label = \"\"):","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"tip: Numerical precision for stability\nThe Floquet multipliers are not very precisely computed here using the Shooting method. We know that 1=exp(0) should be a Floquet multiplier but this is only true here at precision ~1e-3. In order to prevent spurious bifurcation detection, there is a threshold tol_stability in ContinuationPar for declaring an unstable eigenvalue. Another way would be to use Poincaré Shooting so that this issue does not show up.","category":"page"},{"location":"tutorials/tutorialsPD/#Periodic-orbits-from-the-PD-point-(Standard-Shooting)","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"Periodic orbits from the PD point (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We now compute the periodic orbits branching of the first Period-Doubling bifurcation point. It is straightforward to obtain an initial guess using the flow around the bifurcation point:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"par_br_pd = @set par_br.C = -1.32\nprob_sp = SplitODEProblem(f1, f2, solc0, (0.0, 300.0), par_br_pd)\n# solution close to the PD point.\nsolpd = @time solve(prob_sp, ETDRK2(krylov=true); abstol=1e-14, reltol=1e-14, dt = 0.1)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"The estimated period is T_pd=62:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"orbitsectionpd = Array(solpd[:,end-100])\ninitpo_pd = vcat(vec(orbitsectionpd), 6.2)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"For educational purposes, we show the newton outputs:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"out_po_sh_pd = newton(BK.set_params_po(probSh, par_br_pd), initpo_pd , optn; normN = norminf)\nBK.converged(out_po_sh_pd) && printstyled(color=:red, \"--> T = \", out_po_sh_pd.u[end], \", amplitude = \", BK.getamplitude(probSh, out_po_sh_pd.u, (@set par_br.C = -0.86); ratio = 2),\"\\n\")","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"which gives","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 4.3061e+00 │ 0 │\n│ 1 │ 5.3254e-02 │ 10 │\n│ 2 │ 5.5053e-03 │ 12 │\n│ 3 │ 1.6203e-03 │ 13 │\n│ 4 │ 5.6236e-05 │ 12 │\n│ 5 │ 7.6290e-07 │ 12 │\n│ 6 │ 3.0634e-08 │ 13 │\n│ 7 │ 1.2282e-09 │ 12 │\n│ 8 │ 4.9233e-11 │ 13 │\n└─────────────┴──────────────────────┴────────────────┘\n 4.249150 seconds (497.85 k allocations: 2.030 GiB, 11.13% gc time)\n--> T = 6.126399996979465, amplitude = 1.410164896740365","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We also compute the branch of periodic orbits using the following command:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"opts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= 0.001, p_min = -1.8, max_steps = 100, newton_options = (@set optn.eigsolver = eig), nev = 5, tol_stability = 1e-3, detect_bifurcation = 2)\nbr_po_sh_pd = @time continuation(BK.set_params_po(probSh,par_br_pd), out_po_sh_pd.u, PALC(),\topts_po_cont;\n verbosity = 2, plot = true,\n linear_algo = MatrixFreeBLS(@set ls.N = probSh.M*n+2),\n plot_solution = (x, p; kwargs...) -> (BK.plot_periodic_shooting!(x[1:end-1], 1; kwargs...); plot!(br_po_sh; subplot=1, legend=false)),\n record_from_solution = (u, p; k...) -> BK.getmaximum(probSh, u, (@set par_br_pd.C = p.p); ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"and plot it using plot(br_po_sh, br, br_po_sh_pd, label = \"\"):","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"(Image: )","category":"page"},{"location":"tutorials/autocatalyticAuto/#Fronts-in-1d-autocatalytic-model-(Automatic)","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Pages = [\"autocatalyticAuto.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We consider the following model [Balmforth][Malham] which is also treated in [Beyn]","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"beginarrayl\nu_t=a u_x x-u f(v) quad a0 u v mathbbR rightarrow mathbbR \nv_t=v_x x+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"where f(u) = u^m 1_ugeq 0. We chose the boundary conditions","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"left(u_- v_-right)=(01)quad left(u_+ v_+right)=(10)tagBC","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"It is straightforward to implement this problem as follows:","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"using Revise\nusing ForwardDiff, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\n# supremum norm\nnorminf(x) = norm(x, Inf)\nf(u) = u^9 # solutions are positive, so remove the heaviside\n\n# helper function to plot solutions\nfunction plotsol!(x; k...)\n\tu = @view x[1:end÷2]\n\tv = @view x[end÷2:end]\n\tplot!(u; label=\"u\", k...)\n\tplot!(v; label=\"v\", k...)\nend\nplotsol(x; k...) = (plot();plotsol!(x; k...))\n\n# encode the nonlinearity\n@views function NL!(dest, U, p, t = 0.)\n\tN = p.N\n\tu = U[1:N]\n\tv = U[N+1:2N]\n\tdest[1:N] .= -u .* f.(v)\n\tdest[N+1:2N] .= -dest[1:N]#u .* f.(v)\n\treturn dest\nend\n\n# function for the differential with specific boundary conditions\n# for fronts\n@views function applyD_add!(f, U, p, a)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tc1 = 1 / (2p.h)\n\tf[1] += a * (uL - u[2] ) * c1\n\tf[end] += a * (v[n-1] - vR ) * c1\n\n\tf[n] += a * (u[n-1] - uR ) * c1\n\tf[n+1] += a * ( vL - v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += a * (u[i-1] - u[i+1]) * c1\n\t\tf[n+i] += a * (v[i-1] - v[i+1]) * c1\n\tend\n\treturn f\nend\n\n# function which encodes the full PDE\n@views function Fcat!(f, U, p, t = 0)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\t# nonlinearity\n\tNL!(f, U, p)\n\n\t# Dirichlet boundary conditions\n\th2 = p.h * p.h\n\tc1 = 1 / h2\n\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tf[1] += p.a * (uL - 2u[1] + u[2] ) * c1\n\tf[end] += (v[n-1] - 2v[n] + vR ) * c1\n\n\tf[n] += p.a * (u[n-1] - 2u[n] + uR ) * c1\n\tf[n+1] += (vL - 2v[1] + v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += p.a * (u[i-1] - 2u[i] + u[i+1]) * c1\n\t\tf[n+i] += (v[i-1] - 2v[i] + v[i+1]) * c1\n\tend\n\treturn f\nend\nFcat(x, p, t = 0.) = Fcat!(similar(x), x, p, t)\nJcat(x,p) = sparse(ForwardDiff.jacobian(x -> Fcat(x, p), x))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We chose the following parameters:","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"N = 200\nlx = 25.\nX = LinRange(-lx,lx, N)\npar_cat = (N = N, a = 0.18, h = 2lx/N)\n\nu0 = @. (tanh(2X)+1)/2\nU0 = vcat(u0, 1 .- u0)\n\n# we define a problem to hold the vector field\nprob = BifurcationProblem(Fcat, u0, par_cat, (@lens _.a); J = Jcat)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/#Freezing-method","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"Freezing method","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"The problem may feature fronts, that is solutions of the form u(xt) = tilde u(x-st) (same for v) for a fixed value of the profile tilde u and the speed s. The equation for the front profile is, up to an abuse of notations (we removed the tildes)","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"beginarrayl\n0=a u_xixi+scdot u_xi-u f(v)\n0=v_xixi+scdot v_xi+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"with unknowns uvs. The front is solution of these equations but it is not uniquely determined because of the phase invariance. Hence, we add the phase condition (see [Beyn])","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"0 = leftlangle (uv) partial_xi (u_0v_0) rightrangle","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"where U_0=(u_0v_0) is some fixed profile. This is encoded in the problem TWProblem","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"using LinearAlgebra\n\n# this structure encodes the Lie generator\nstruct Advection{T}\n\tp::T\nend\n\nfunction LinearAlgebra.mul!(f, aD::Advection, U, α, β)\n\trmul!(f, β)\n\tapplyD_add!(f, U, aD.p, α)\nend\n\nuold = vcat(u0, (1 .- u0))\n\n# we create a TW problem\nprobTW = BK.TWProblem(prob, Advection(par_cat), copy(uold))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We now define the U_0 profile","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"uold = vcat(u0, (1 .- u0))\nDuold = zero(uold); applyD_add!(Duold, uold, par_cat,1)\n\n# update problem parameters for front problem\npar_cat_wave = (par_cat..., u0Du0 = dot(uold, Duold), Du0 = Duold, uold = uold)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Let us find the front using newton","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"front = newton(probTW, vcat(U0, 0.1), NewtonPar(verbose = true))\nprintln(\"norm front = \", front.u[1:end-1] |> norminf, \", speed = \", front.u[end])","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"plotsol(front.u[1:end-1], title=\"front solution\")","category":"page"},{"location":"tutorials/autocatalyticAuto/#Continuation-of-front-solutions","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"Continuation of front solutions","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Following [Malham], the modulated fronts are solutions of the following DAE","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"beginarrayltagDAE\nu_t=a u_x x+scdot u_x-u f(v)\nv_t=v_x x+scdot v_x+u f(v)\n0 = leftlangle U partial_xi U_0\trightrangle\nendarray","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"which can be written with a PDE M_aU_t = G(u) with mass matrix M_a = (Id Id 0). We have already written the vector field of (MF) in the problem probTW.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Having found a front U^f, we can continue it as function of the parameter a and detect instabilities. The stability of the front is linked to the eigenelements (lambda V) solution of the generalized eigenvalue problem:","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"lambda M_acdot V = dG(U^f)cdot V","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"This is handled automatically when calling continuation on a TWProblem.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"optn = NewtonPar(tol = 1e-8)\nopt_cont_br = ContinuationPar(p_min = 0.015, p_max = 0.18, newton_options = optn, ds= -0.001, plot_every_step = 2, detect_bifurcation = 3, nev = 10, n_inversion = 6)\nbr_TW = continuation(probTW, front.u, PALC(), opt_cont_br)\nplot(br_TW, legend = :topright)","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts.","category":"page"},{"location":"tutorials/autocatalyticAuto/#References","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"References","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"[Balmforth]: N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"[Malham]: S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"[Beyn]: Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.","category":"page"},{"location":"tutorials/ode/lorenz84/#lorenz","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"Pages = [\"lorenz84.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"In this tutorial, we study the extended Lorenz-84 model which is also treated in MatCont [Kuznetsov]. This model is interesting because it features all codim 2 bifurcations of equilibria. It is thus convenient to test our algorithms.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"After this tutorial, you will be able to","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"detect codim 1 bifurcation Fold / Hopf / Branch point\nfollow Fold / Hopf points and detect codim 2 bifurcation points\nbranch from the detected codim 2 points to curves of Fold / Hopf points","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"The model is as follows","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"leftbeginarrayl\ndotX=-Y^2-Z^2-alpha X+alpha F-gamma U^2 \ndotY=X Y-beta X Z-Y+G \ndotZ=beta X Y+X Z-Z \ndotU=-delta U+gamma U X+T\nendarrayrighttagE","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We start with some imports:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"using Revise, Parameters, Setfield, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/lorenz84/#Problem-setting","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Problem setting","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We can now encode the vector field (E) in a function and use automatic differentiation to compute its various derivatives.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"# vector field\nfunction Lor(u, p)\n @unpack α,β,γ,δ,G,F,T = p\n\tX,Y,Z,U = u\n\t[\n\t\t-Y^2 - Z^2 - α*X + α*F - γ*U^2,\n\t\tX*Y - β*X*Z - Y + G,\n\t\tβ*X*Y + X*Z - Z,\n\t\t-δ*U + γ*U*X + T\n\t]\nend\n\n# parameter values\nparlor = (α = 1//4, β = 1, G = .25, δ = 1.04, γ = 0.987, F = 1.7620532879639, T = .0001265)\n\n# initial condition\nz0 = [2.9787004394953343, -0.03868302503393752, 0.058232737694740085, -0.02105288273117459]\n\n# bifurcation problem\nrecordFromSolutionLor(x, p) = (X = x[1], Y = x[2], Z = x[3], U = x[4])\nprob = BifurcationProblem(Lor, z0, setproperties(parlor; T=0.04, F=3.), (@lens _.F);\n record_from_solution = recordFromSolutionLor)\nnothing #hide","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-and-codim-1-bifurcations","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation and codim 1 bifurcations","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"Once the problem is set up, we can continue the state w.r.t. F to and detect codim 1 bifurcations. This is achieved as follows:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = -1.5, p_max = 3.0, ds = 0.002, dsmax = 0.15,\n\t# Optional: bisection options for locating bifurcations\n\tn_inversion = 6, max_bisection_steps = 25,\n\t# number of eigenvalues\n\tnev = 4, max_steps = 200)\n\n# compute the branch of solutions\nbr = continuation(prob, PALC(), opts_br;\n\tnormC = norminf,\n\tbothside = true)\n\nscene = plot(br, plotfold=false, markersize=4, legend=:topleft)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"br","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Fold-points","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Fold points","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We follow the Fold points in the parameter plane (TF). We tell the solver to consider br.specialpoint[5] and continue it.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"# function to record the current state\nsn_codim2 = continuation(br, 5, (@lens _.T), ContinuationPar(opts_br, p_max = 3.2, p_min = -0.1, detect_bifurcation = 1, dsmin=1e-5, ds = -0.001, dsmax = 0.005, n_inversion = 10, max_steps = 130, max_bisection_steps = 55) ; normC = norminf,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = false,\n\t# we save the different components for plotting\n\trecord_from_solution = recordFromSolutionLor,\n\t)\n\nscene = plot(sn_codim2, vars=(:X, :U), branchlabel = \"Folds\", ylims=(-0.5, 0.5))","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"sn_codim2","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"For example, we can compute the following normal form","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"get_normal_form(sn_codim2, 1; nev = 4)","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Hopf-points","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We follow the Hopf points in the parameter plane (TF). We tell the solver to consider br.specialpoint[3] and continue it.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_codim2_1 = continuation((@set br.alg.tangent = Bordered()), 3, (@lens _.T), ContinuationPar(opts_br, ds = -0.001, dsmax = 0.02, dsmin = 1e-4, n_inversion = 6, detect_bifurcation = 1) ; normC = norminf,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# we save the different components for plotting\n\trecord_from_solution = recordFromSolutionLor,\n\t# compute both sides of the initial condition\n\tbothside = true,\n\t)\n\nplot(sn_codim2, vars=(:X, :U), branchlabel = \"Folds\")\n\tplot!(hp_codim2_1, vars=(:X, :U), branchlabel = \"Hopfs\")\n\tylims!(-0.7,0.7);xlims!(1,1.3)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_codim2_1","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"For example, we can compute the following normal form","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"get_normal_form(hp_codim2_1, 3; nev = 4)","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Hopf-points-from-the-Bogdanov-Takens-point","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Hopf points from the Bogdanov-Takens point","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"When we computed the curve of Fold points, we detected a Bogdanov-Takens bifurcation. We can branch from it to get the curve of Hopf points. This is done as follows:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_bt = continuation((@set sn_codim2.alg.tangent = Bordered()), 4, ContinuationPar(opts_br, ds = -0.001, dsmax = 0.02, dsmin = 1e-4,\n\tn_inversion = 6, detect_bifurcation = 1) ; normC = norminf,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# we save the different components for plotting\n\trecord_from_solution = recordFromSolutionLor,\n\t)\n\nplot(sn_codim2, vars=(:X, :U), branchlabel = \"SN\")\n\tplot!(hp_codim2_1, vars=(:X, :U), branchlabel = \"Hopf1\")\n\tplot!(hp_from_bt, vars=(:X, :U), branchlabel = \"Hopf2\")\n\tylims!(-0.7,0.75);xlims!(0.95,1.3)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_bt","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Hopf-points-from-the-Zero-Hopf-point","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Hopf points from the Zero-Hopf point","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"When we computed the curve of Fold points, we detected a Zero-Hopf bifurcation. We can branch from it to get the curve of Hopf points. This is done as follows:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_zh = continuation((@set sn_codim2.alg.tangent = Bordered()), 2, ContinuationPar(opts_br, ds = 0.001, dsmax = 0.02, dsmin = 1e-4, n_inversion = 6, detect_bifurcation = 1, max_steps = 150) ;\n\tnormC = norminf,\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = true,\n\trecord_from_solution = recordFromSolutionLor,\n\tbothside = false,\n\tbdlinsolver = MatrixBLS(),\n\t)\n\nplot(sn_codim2,vars=(:X, :U),)\n\tplot!(hp_codim2_1, vars=(:X, :U), branchlabel = \"Hopf\")\n\tplot!(hp_from_bt, vars=(:X, :U), branchlabel = \"Hopf2\")\n\tplot!( hp_from_zh, vars=(:X, :U), branchlabel = \"Hopf\", plotspecialpoints = false, legend = :topleft)\n\tylims!(-0.7,0.75);xlims!(0.95,1.3)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_zh","category":"page"},{"location":"tutorials/ode/lorenz84/#References","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"References","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"[Kuznetsov]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.","category":"page"},{"location":"tutorials/ode/steinmetz/#steinmetz","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"","category":"section"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"Pages = [\"steinmetz.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"This example is found in the MatCont ecosystem.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"The Steinmetz-Larter model is studied in the MatCont ecosystem because it is a simple example where a Chenciner bifurcation occurs.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"tagEleftbeginarrayl\ndotA=-k_1 A B X-k_3 A B Y+k_7-k_-7 A \ndotB=-k_1 A B X-k_3 A B Y+k_8 \ndotX=k_1 A B X-2 k_2 X^2+2 k_3 A B Y-k_4 X+k_6 \ndotY=-k_3 A B Y+2 k_2 X^2-k_5 Y\nendarrayright","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"This tutorial is also useful in that we show how to start periodic orbits continuation from solutions obtained from solving ODEs. Being a relatively advanced tutorial, we do not give too many details.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"We start by coding the bifurcation problem.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"using Revise\nusing Test, ForwardDiff, Parameters, Plots\nusing BifurcationKit, Test\nconst BK = BifurcationKit\n\nfunction SL!(du, u, p, t = 0)\n\t@unpack k1, k2, k3, k4, k5, k6, k7, k₋₇, k8 = p\n\tA,B,X,Y = u\n\n\tdu[1] = -k1*A*B*X - k3*A*B*Y + k7 - k₋₇*A\n\tdu[2] = -k1*A*B*X - k3*A*B*Y + k8\n\tdu[3] = k1*A*B*X - 2*k2*X^2 + 2*k3*A*B*Y - k4*X+k6\n\tdu[4] = -k3*A*B*Y + 2*k2*X^2 - k5*Y\n\tdu\nend\n\nz0 = rand(4)\npar_sl = (k1=0.1631021, k2=1250., k3=0.046875, k4=20., k5=1.104, k6=0.001, k₋₇=0.1175, k7=1.5, k8=0.75)\nprob = BifurcationProblem(SL!, z0, par_sl, (@lens _.k8);)\n\n# record variables for plotting\nfunction recordFromSolution(x, p) \n\txtt = BK.get_periodic_orbit(p.prob, x, p.p)\n\treturn (max = maximum(xtt[1,:]),\n\t\t\tmin = minimum(xtt[1,:]),\n\t\t\tperiod = getperiod(p.prob, x, p.p))\nend\n\n# plotting function\nfunction plotSolution(x, p; k...)\n\txtt = BK.get_periodic_orbit(p.prob, x, p.p)\n\tplot!(xtt.t, xtt[:,:]'; label = \"\", k...)\nend\n\n# group parameters\nargspo = (record_from_solution = recordFromSolution,\n\tplot_solution = plotSolution)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"We obtain some trajectories as seeds for computing periodic orbits.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"using DifferentialEquations\nalg_ode = Rodas5()\nprob_de = ODEProblem(SL!, z0, (0,136.), par_sl)\nsol = solve(prob_de, alg_ode)\nprob_de = ODEProblem(SL!, sol.u[end], (0,30.), sol.prob.p, reltol = 1e-11, abstol = 1e-13)\nsol = solve(prob_de, alg_ode)\nplot(sol)","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"We generate a shooting problem form the computed trajectories and continue the periodic orbits as function of k_8","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"probsh, cish = generate_ci_problem( ShootingProblem(M=4), prob, prob_de, sol, 16.; reltol = 1e-10, abstol = 1e-12, parallel = true)\n\nopts_po_cont = ContinuationPar(p_min = 0., p_max = 20.0, ds = 0.002, dsmax = 0.05, n_inversion = 8, detect_bifurcation = 3, max_bisection_steps = 25, nev = 4, max_steps = 60, save_eigenvectors = true, tol_stability = 1e-3)\n@set! opts_po_cont.newton_options.verbose = false\n@set! opts_po_cont.newton_options.max_iterations = 10\nbr_sh = continuation(deepcopy(probsh), cish, PALC(tangent = Bordered()), opts_po_cont;\n\t#verbosity = 3, plot = true,\n\tcallback_newton = BK.cbMaxNorm(10),\n\targspo...)","category":"page"},{"location":"tutorials/ode/steinmetz/#Curve-of-Fold-points-of-periodic-orbits","page":"🟠 Steinmetz-Larter model","title":"Curve of Fold points of periodic orbits","text":"","category":"section"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"opts_posh_fold = ContinuationPar(br_sh.contparams, detect_bifurcation = 2, max_steps = 35, p_max = 1.9, plot_every_step = 10, dsmax = 4e-2, ds = 1e-2)\n@set! opts_posh_fold.newton_options.tol = 1e-12\n@set! opts_posh_fold.newton_options.verbose = true\nfold_po_sh = @time continuation(br_sh, 2, (@lens _.k7), opts_posh_fold;\n\t\t#verbosity = 3, plot = true,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tstart_with_eigen = false,\n\t\tusehessian = false,\n\t\tjacobian_ma = :minaug,\n\t\tnormC = norminf,\n\t\tcallback_newton = BK.cbMaxNorm(1e1),\n\t\tbdlinsolver = BorderingBLS(solver = DefaultLS(), check_precision = false),\n\t\t)\nplot(fold_po_sh)","category":"page"},{"location":"tutorials/ode/steinmetz/#Curve-of-NS-points-of-periodic-orbits","page":"🟠 Steinmetz-Larter model","title":"Curve of NS points of periodic orbits","text":"","category":"section"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"opts_posh_ns = ContinuationPar(br_sh.contparams, detect_bifurcation = 0, max_steps = 35, p_max = 1.9, plot_every_step = 10, dsmax = 4e-2, ds = 1e-2)\n@set! opts_posh_ns.newton_options.tol = 1e-12\nns_po_sh = continuation(br_sh, 1, (@lens _.k7), opts_posh_ns;\n\t\tverbosity = 2, plot = false,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tstart_with_eigen = false,\n\t\tusehessian = false,\n\t\tjacobian_ma = :minaug,\n\t\tnormC = norminf,\n\t\tcallback_newton = BK.cbMaxNorm(1e1),\n\t\t)","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"plot(ns_po_sh, fold_po_sh, branchlabel = [\"NS\",\"Fold\"])","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-predator-prey-model","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"Pages = [\"tutorialsCodim2PO.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"This example is found in the MatCont ecosystem.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"The following is a periodically forced predator-prey model studied in [Kuznetsov] using shooting techniques.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"tagEleftbeginaligned\ndotx =rleft(1-fracxKright) x-fraca x yb_0(1+varepsilon u)+x \ndoty =e fraca x yb_0(1+varepsilon u)+x-d y \ndotu =u-2 pi v-left(u^2+v^2right) u \ndotv =2 pi u+v-left(u^2+v^2right) v\nendalignedright","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"This tutorial is useful in that we show how to start periodic orbits continuation from solutions obtained from solving ODEs. We are interested in cases where (uv)neq (00) for which we have only periodic solutions. Thus, we cannot rely on branching from equilibria to find these periodic orbits.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nfunction Pop!(du, X, p, t = 0)\n\t@unpack r,K,a,ϵ,b0,e,d, = p\n\tx, y, u, v = X\n\tp = a * x / (b0 * (1 + ϵ * u) + x)\n\tdu[1] = r * (1 - x/K) * x - p * y\n\tdu[2] = e * p * y - d * y\n\ts = u^2 + v^2\n\tdu[3] = u-2pi * v - s * u\n\tdu[4] = 2pi * u + v - s * v\n\tdu\nend\n\npar_pop = ( K = 1., r = 6.28, a = 12.56, b0 = 0.25, e = 1., d = 6.28, ϵ = 0.2, )\n\nz0 = [0.1,0.1,1,0]\n\nprob = BifurcationProblem(Pop!, z0, par_pop, (@lens _.b0);\n\trecord_from_solution = (x, p) -> (x = x[1], y = x[2], u = x[3]))\n\nopts_br = ContinuationPar(p_min = 0., p_max = 20.0, ds = 0.002, dsmax = 0.01, n_inversion = 6, detect_bifurcation = 3, max_bisection_steps = 25, nev = 4, max_steps = 20000)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Simulation-of-the-model","page":"🟠 Periodic predator-prey model","title":"Simulation of the model","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"This is very straightforward thanks to SciML.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"using DifferentialEquations\nprob_de = ODEProblem(Pop!, z0, (0,200.), par_pop)\nsol = solve(prob_de, Rodas5())\nprob_de = ODEProblem(Pop!, sol.u[end], (0,3.), par_pop, reltol = 1e-8, abstol = 1e-10)\nsol = solve(prob_de, Rodas5())\nplot(sol)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Utility-functions","page":"🟠 Periodic predator-prey model","title":"Utility functions","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We start with two helper functions that record and plot the periodic orbits. The following works for shooting, collocation and trapezoid methods for computing periodic orbits.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"argspo = (record_from_solution = (x, p) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\t\tmin = minimum(xtt[1,:]),\n\t\t\t\tperiod = getperiod(p.prob, x, p.p))\n\tend,\n\tplot_solution = (x, p; k...) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\tplot!(xtt.t, xtt[1,:]; label = \"x\", k...)\n\t\tplot!(xtt.t, xtt[2,:]; label = \"y\", k...)\n\t\t# plot!(br; subplot = 1, putspecialptlegend = false)\n\tend)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-orbits-with-trapezoid-method","page":"🟠 Periodic predator-prey model","title":"Periodic orbits with trapezoid method","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We compute periodic orbits of (E) using the Trapezoid method. We are now equipped to build a periodic orbit problem from a solution sol::ODEProblem.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"# function to build probtrap from sol\nprobtrap, ci = BK.generate_ci_problem(PeriodicOrbitTrapProblem(M = 150),\n\tprob, sol, 2.)\n\nopts_po_cont = setproperties(opts_br, max_steps = 50, tol_stability = 1e-8)\nbrpo_fold = continuation(probtrap, ci, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\n\nscene = plot(brpo_fold)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue w.r.t. to epsilon and find a period-doubling bifurcation.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"prob2 = @set probtrap.prob_vf.lens = @lens _.ϵ\nbrpo_pd = continuation(prob2, ci, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\nscene = plot(brpo_pd)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-orbits-with-parallel-standard-shooting","page":"🟠 Periodic predator-prey model","title":"Periodic orbits with parallel standard shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We are now ready to build a periodic orbit problem from a solution sol::ODEProblem.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"probsh, cish = generate_ci_problem( ShootingProblem(M=3),\n\tprob, prob_de, sol, 2.; alg = Rodas5())\n\nopts_po_cont = setproperties(opts_br, max_steps = 50, tol_stability = 1e-3)\nbr_fold_sh = continuation(probsh, cish, PALC(tangent = Bordered()), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n)\n\nscene = plot(br_fold_sh)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue w.r.t. to epsilon and find a period-doubling bifurcation.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"probsh2 = @set probsh.lens = @lens _.ϵ\nbrpo_pd_sh = continuation(probsh2, cish, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\nscene = plot(brpo_pd_sh)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-orbits-with-orthogonal-collocation","page":"🟠 Periodic predator-prey model","title":"Periodic orbits with orthogonal collocation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We do the same as in the previous section but using orthogonal collocation. This is the most reliable and precise method for ODE. When the dimension of the ODE is large, it becomes prohibitive.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"# this is the function which builds probcoll from sol\nprobcoll, ci = generate_ci_problem(PeriodicOrbitOCollProblem(26, 3; update_section_every_step = 0),\n\tprob, sol, 2.)\n\nopts_po_cont = setproperties(opts_br, max_steps = 50, tol_stability = 1e-8)\nbrpo_fold = continuation(probcoll, ci, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\nscene = plot(brpo_fold)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue w.r.t. to epsilon and find a period-doubling bifurcation.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"prob2 = @set probcoll.prob_vf.lens = @lens _.ϵ\nbrpo_pd = continuation(prob2, ci, PALC(), ContinuationPar(opts_po_cont, dsmax = 5e-3);\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\n\nscene = plot(brpo_pd)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Continuation-of-Fold-/-PD-of-periodic-orbits-with-Shooting","page":"🟠 Periodic predator-prey model","title":"Continuation of Fold / PD of periodic orbits with Shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue the previously detected fold/period-doubling bifurcations as function of two parameters and detect codim 2 bifurcations. We first start with the computation of the curve of Folds.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"opts_posh_fold = ContinuationPar(br_fold_sh.contparams, detect_bifurcation = 3, max_steps = 100, p_min = 0.01, p_max = 1.2)\n@set! opts_posh_fold.newton_options.tol = 1e-12\n\nfold_po_sh2 = continuation(br_fold_sh, 1, (@lens _.ϵ), opts_posh_fold;\n\t\tverbosity = 2, plot = true,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tjacobian_ma = :minaug,\n\t\tstart_with_eigen = false,\n\t\tbothside = true,\n\t\tcallback_newton = BK.cbMaxNorm(1),\n\t\t)\n\nfold_po_sh1 = continuation(br_fold_sh, 2, (@lens _.ϵ), opts_posh_fold;\n\t\tverbosity = 2, plot = true,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tjacobian_ma = :minaug,\n\t\tstart_with_eigen = false,\n\t\tbothside = true,\n\t\tcallback_newton = BK.cbMaxNorm(1),\n\t\t)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We turn to the computation of the curve of PD points.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"par_pop2 = @set par_pop.b0 = 0.45\nsol2 = solve(remake(prob_de, p = par_pop2, u0 = [0.1,0.1,1,0], tspan=(0,1000)), Rodas5())\nsol2 = solve(remake(sol2.prob, tspan = (0,10), u0 = sol2[end]), Rodas5())\nplot(sol2, xlims= (8,10))\n\nprobshpd, ci = generate_ci_problem(ShootingProblem(M=3), re_make(prob, params = sol2.prob.p), remake(prob_de, p = par_pop2), sol2, 1.; alg = Rodas5())\n\nprob2 = @set probshpd.lens = @lens _.ϵ\nbrpo_pd = continuation(prob2, ci, PALC(), ContinuationPar(opts_po_cont, dsmax = 5e-3);\n\tverbosity = 3, plot = true,\n\targspo...,\n\tbothside = true,\n\t)\n\nopts_pocoll_pd = ContinuationPar(brpo_pd.contparams, detect_bifurcation = 3, max_steps = 40, p_min = 1.e-2, plot_every_step = 10, dsmax = 1e-2, ds = -1e-3)\n@set! opts_pocoll_pd.newton_options.tol = 1e-12\npd_po_sh2 = continuation(brpo_pd, 2, (@lens _.b0), opts_pocoll_pd;\n\t\tverbosity = 3,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tstart_with_eigen = false,\n\t\tusehessian = false,\n\t\tjacobian_ma = :minaug,\n\t\tnormC = norminf,\n\t\tcallback_newton = BK.cbMaxNorm(10),\n\t\tbothside = true,\n\t\t)\n\nplot(fold_po_sh1, fold_po_sh2, branchlabel = [\"FOLD\", \"FOLD\"])\nplot!(pd_po_sh2, vars = (:ϵ, :b0), branchlabel = \"PD\")","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#References","page":"🟠 Periodic predator-prey model","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"[Kuznetsov]: Yu.A. Kuznetsov, S. Muratori, and S. Rinaldi. Bifurcations and chaos in a periodic predator-prey model, Internat. J. Bifur. Chaos Appl. Sci. Engr., 2 (1992), 117-128.","category":"page"},{"location":"borderedlinearsolver/#Bordered-linear-solvers-(BLS)","page":"Bordered linear solvers","title":"Bordered linear solvers (BLS)","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"The bordered linear solvers must be subtypes of AbstractBorderedLinearSolver <: AbstractLinearSolver.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"The methods provided here solve bordered linear equations. More precisely, one is interested in the solution u to Jcdot u = v where","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"tag E J=left(beginarrayll\nA b \nc^T d\nendarrayright) text and v=left(beginarrayl\nv_1 \nv_2\nendarrayright)","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"Such linear solver bdlsolve will be called like sol, success, itnumber = bdlsolve(A, b, c, d, v1, v2) throughout the package.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"warning: Complex numbers\nIn the case where cinmathbb C^N, please note that the adjoint operator c^T involves a conjugate.","category":"page"},{"location":"borderedlinearsolver/#Full-matrix-MatrixBLS","page":"Bordered linear solvers","title":"Full matrix MatrixBLS","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"This easiest way to solve (E) is by forming the matrix J. In case it is sparse, it should be relatively efficient. You can create such bordered linear solver using bls = MatrixBLS(ls) where ls::AbstractLinearSolver is a linear solver (which defaults to \\) used to solve the linear problem associated to J. This is the default method used in the package. ","category":"page"},{"location":"borderedlinearsolver/#Bordering-method-BorderingBLS","page":"Bordered linear solvers","title":"Bordering method BorderingBLS","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"The general solution u=left(beginarrayl u_1 \nu_2 endarrayright) to (E) when A is non singular is","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"beginarrayl\nu_2 = frac1d - ccdot x_2(v_2 - ccdot x_1) \nu_1=x_1-u_2x_2\nendarray","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"where x_1=A^-1v_1 x_2=A^-1b. ","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"It is very efficient for large scale problems because it is entirely Matrix-Free and one can use preconditioners. You can create such bordered linear solver using bls = BorderingBLS(ls) where ls::AbstractLinearSolver is a linear solver which defaults to \\. The intermediate solutions x_1=A^-1v_1 x_2=A^-1b are formed using ls.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"In the case where ls = DefaultLS(), the factorisation of A is cached so the second linear solve is very fast","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"There are more options to BorderingBLS. First, the residual can be checked using the option check_precision = true. If the residual is above a prescribed tolerance, an iterative method is used based on several bordering transformations. This is the BEC+k algorithm in [Govaerts].","category":"page"},{"location":"borderedlinearsolver/#Full-Matrix-Free-MatrixFreeBLS","page":"Bordered linear solvers","title":"Full Matrix-Free MatrixFreeBLS","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"In cases where A is singular but J is not, the bordering method may fail. It can thus be advantageous to form the Matrix-Free version of J and call a generic linear solver to find the solution to (E). You can create such bordered linear solver using bls = MatrixFreeBLS(ls) where ls::AbstractLinearSolver is a (Matrix Free) linear solver which is used to invert J.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"For now, this linear solver only works with AbstractArray","category":"page"},{"location":"borderedlinearsolver/#References","page":"Bordered linear solvers","title":"References","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"[Govaerts]: Govaerts, W. “Stable Solvers and Block Elimination for Bordered Systems.” SIAM Journal on Matrix Analysis and Applications 12, no. 3 (July 1, 1991): 469–83. https://doi.org/10.1137/0612034.","category":"page"},{"location":"capabilities/#Overview-of-capabilities","page":"Overview of capabilities","title":"Overview of capabilities","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Pages = [\"capabilities.md\"]\nDepth = 3","category":"page"},{"location":"capabilities/#Main-features","page":"Overview of capabilities","title":"Main features","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Newton-Krylov solver with generic linear / eigen preconditioned solver. Idem for the arc-length continuation.\nNewton-Krylov solver with nonlinear deflation and preconditioner. It can be used for branch switching for example. It is used for deflated continuation.\nContinuation written as an iterator\nMonitoring user functions along curves computed by continuation, see events\nContinuation methods: PALC, Moore Penrose, Multiple, Polynomial, Deflated continuation, ANM, ...\nBifurcation points located with bisection","category":"page"},{"location":"capabilities/#Capabilities-related-to-equilibria","page":"Overview of capabilities","title":"Capabilities related to equilibria","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Detection of Branch, Fold, Hopf bifurcation points of stationary solutions and computation of their normal form.\nAutomatic branch switching at branch points (whatever the dimension of the kernel) to equilibria\nAutomatic computation of bifurcation diagrams of equilibria\nFold / Hopf continuation based on Minimally Augmented formulation, with Matrix Free / Sparse / Dense Jacobian.\nDetection of all codim 2 bifurcations of equilibria and computation of the normal forms of Bogdanov-Takens, Bautin and Cusp\nBranching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf points to Fold / Hopf curve","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Note that you can combine most solvers, like use Deflation for Periodic orbit computation or Fold of periodic orbits family.","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Custom state means, we can use something else than AbstractArray, for example your own struct.","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Features Matrix Free Custom state Tutorial GPU\n(Deflated) Krylov-Newton Yes Yes link Yes\nContinuation PALC (Natural, Secant, Tangent, Polynomial) Yes Yes All Yes\nDeflated Continuation Yes Yes link Yes\nBifurcation / Fold / Hopf point detection Yes Yes All / All / link Yes\nFold Point continuation Yes Yes PDE, PDE, ODE Yes\nHopf Point continuation Yes AbstractArray ODE \nBranch point / Fold / Hopf normal form Yes Yes Yes\nBranch switching at Branch points Yes AbstractArray link Yes\nAutomatic bifurcation diagram computation of equilibria Yes AbstractArray link \nBogdanov-Takens / Bautin / Cusp / Zero-Hopf / Hopf-Hopf point detection Yes Yes ODE \nBogdanov-Takens / Bautin / Cusp normal forms Yes AbstractArray ODE Yes\nBranching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf to Fold / Hopf curve Yes AbstractArray ODE ","category":"page"},{"location":"capabilities/#Capabilities-related-to-Periodic-orbits","page":"Overview of capabilities","title":"Capabilities related to Periodic orbits","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Periodic orbit computation and continuation using parallel (Standard or Poincaré) Shooting, Finite Differences or Orthogonal Collocation.\nAutomatic branch switching at simple Hopf points to periodic orbits\nDetection of Branch, Fold, Neimark-Sacker, Period Doubling bifurcation points of periodic orbits.\nContinuation of Fold of periodic orbits","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Legend for the table: Standard shooting (SS), Poincaré shooting (PS), Orthogonal collocation (OC), trapezoid (T).","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Features Method Matrix Free Custom state Tutorial GPU\nBranch switching at Hopf points SS/PS/OC/T See each ODE \nNewton / continuation T Yes AbstractVector PDE, PDE Yes\nNewton / continuation OC AbstractVector ODE \nNewton / continuation SS Yes AbstractArray ODE Yes\nNewton / continuation PS Yes AbstractArray PDE Yes\nFold, Neimark-Sacker, Period doubling detection SS/PS/OC/T See each AbstractVector link \nBranch switching at Branch point SS/PS/OC/T See each ODE \nBranch switching at PD point SS/PS/OC/T See each ODE \nContinuation of Fold points SS/PS/OC/T See each AbstractVector ODE PDE Yes\nContinuation of Period-doubling points SS/OC AbstractVector ODE \nContinuation of Neimark-Sacker points SS/OC AbstractVector ODE \ndetection of codim 2 bifurcations of periodic orbits SS/OC AbstractVector ODE \nBranch switching at Bautin point to curve of Fold of periodic orbits SS/OC AbstractVector ODE \nBranch switching at ZH/HH point to curve of NS of periodic orbits SS/OC AbstractVector ODE ","category":"page"},{"location":"capabilities/#Capabilities-related-to-Homoclinic-orbits","page":"Overview of capabilities","title":"Capabilities related to Homoclinic orbits","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"This is available through the plugin HclinicBifurcationKit.jl. Please see the specific docs for more information.","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"compute Homoclinic to Hyperbolic Saddle Orbits (HomHS) using Orthogonal collocation or Standard shooting\ncompute bifurcation of HomHS\nstart HomHS from a direct simulation\nautomatic branch switching to HomHS from Bogdanov-Takes bifurcation point","category":"page"},{"location":"migration/#Migration-from-previous-versions","page":"Migration from old versions","title":"Migration from previous versions","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"Pages = [\"migration.md\"]\nDepth = 2","category":"page"},{"location":"migration/#Migration-from-v0.1.x-to-v0.2.x","page":"Migration from old versions","title":"Migration from v0.1.x to v0.2.x","text":"","category":"section"},{"location":"migration/#IMPORTANT-NOTICE","page":"Migration from old versions","title":"IMPORTANT NOTICE","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"New version of the package with modified interface. You are now required to define a BifurcationProblem to perform continuation or bifurcation analysis. The previous interface is available under the tag 0.1.12 which can be installed by doing","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"] add BifurcationKit@0.1.12","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"The new version provides many bugs fix though. (Please note that the docs are up to date).","category":"page"},{"location":"migration/#Introduction","page":"Migration from old versions","title":"Introduction","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"In v0.2.x, we introduced problem based bifurcation diagram, meaning that you have now to wrap your vector field in a BifurcationProblem. You also need to pass your plot/record functions.","category":"page"},{"location":"migration/#Don't-use-AD-yourself","page":"Migration from old versions","title":"Don't use AD yourself","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"There is nothing wrong with doing so but this is done in the constructor of BifurcationPoblem, so if myJacAD is the jacobian computed using ForwardDiff, the declaration","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"prob = BifurcationProblem(F, x, p, lens ; J = myJacAD) ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"should be ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"prob = BifurcationProblem(F, x, p, lens) ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"There is nothing wrong in passing your own jacobian though","category":"page"},{"location":"migration/#Error:-no-method-matching-iterate(::BifurcationKit.ContResult","page":"Migration from old versions","title":"Error: no method matching iterate(::BifurcationKit.ContResult","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"This is because you use the old syntax ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"br, = continuation(...)","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"instead of (no comma)","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"br = continuation(...)","category":"page"},{"location":"migration/#Arguments-to-continuation","page":"Migration from old versions","title":"Arguments to continuation","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"recordFromSolution and plotFromSolution should be passed to BifurcationProblem instead of continuation.","category":"page"},{"location":"migration/#Migration-from-v0.2.x-to-v0.3.x","page":"Migration from old versions","title":"Migration from v0.2.x to v0.3.x","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"A new version v0.3 has been tagged in which the function names, keyword arguments,... follow the Julia convention. There are a lot of breaking changes. For example, callbackN has been changed to callback_newton.","category":"page"},{"location":"tutorials/ode/Colpitts/#Colpitts–type-Oscillator","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"","category":"section"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Pages = [\"Colpitts.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"In this tutorial, we show how to study parametrized quasilinear DAEs like:","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"A(mux)dot x = G(mux)","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"In particular, we detect a Hopf bifurcation and compute the periodic orbit branching from it using a multiple standard method.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"The following DAE model is taken from [Rabier]:","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"left(beginarraycccc\n-left(C_1+C_2right) C_2 0 0 \nC_2 -C_2 0 0 \nC_1 0 0 0 \n0 0 L 0\nendarrayright)left(beginarrayc\ndotx_1 \ndotx_2 \ndotx_3 \ndotx_4\nendarrayright)=left(beginarrayc\nR^-1left(x_1-Vright)+I Eleft(x_1 x_2right) \nx_3+I Cleft(x_1 x_2right) \n-x_3-x_4 \n-mu+x_2\nendarrayright)","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"It is easy to encode the DAE as follows. The mass matrix is defined next.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nusing LinearAlgebra # for eigen\nconst BK = BifurcationKit\n\n# function to record information from the soluton\nrecordFromSolution(x, p) = (u1 = norminf(x), x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4])\n\n# vector field\nf(x, p) = p.Is * (exp(p.q * x) - 1)\nIE(x1, x2, p) = -f(x2, p) + f(x1, p) / p.αF\nIC(x1, x2, p) = f(x2, p)/ p.αR - f(x1, p)\n\nfunction Colpitts!(dz, z, p, t = 0)\n\t@unpack C1, C2, L, R, Is, q, αF, αR, V, μ = p\n\tx1, x2, x3, x4 = z\n\tdz[1] = (x1 - V) / R + IE(x1, x2, p)\n\tdz[2] =\tx3 + IC(x1, x2, p)\n\tdz[3] = -x3-x4\n\tdz[4] = -μ+x2\n\tdz\nend\n\n# parameter values\npar_Colpitts = (C1 = 1.0, C2 = 1.0, L = 1.0, R = 1/4., Is = 1e-16, q = 40., αF = 0.99, αR = 0.5, μ = 0.5, V = 6.)\n\n# initial condition\nz0 = [0.9957,0.7650,19.81,-19.81]\n\n# mass matrix\nBe = [-(par_Colpitts.C1+par_Colpitts.C2) par_Colpitts.C2 0 0;par_Colpitts.C2 -par_Colpitts.C2 0 0;par_Colpitts.C1 0 0 0; 0 0 par_Colpitts.L 0]\n\n# we group the differentials together\nprob = BifurcationProblem(Colpitts!, z0, par_Colpitts, (@lens _.μ); record_from_solution = recordFromSolution)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"We first compute the branch of equilibria. But we need a generalized eigenvalue solver for this.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"# we need a specific eigensolver with mass matrix B\nstruct EigenDAE{Tb} <: BK.AbstractDirectEigenSolver\n\tB::Tb\nend\n\n# compute the eigen elements\nfunction (eig::EigenDAE)(Jac, nev; k...)\n\tF = eigen(Jac, eig.B)\n\tI = sortperm(F.values, by = real, rev = true)\n\treturn Complex.(F.values[I]), Complex.(F.vectors[:, I]), true, 1\nend\n\n# continuation options\noptn = NewtonPar(tol = 1e-13, max_iterations = 10, eigsolver = EigenDAE(Be))\nopts_br = ContinuationPar(p_min = -0.4, p_max = 0.8, ds = 0.01, dsmax = 0.01, nev = 4, plot_every_step = 3, max_steps = 1000, newton_options = optn)\n\topts_br = @set opts_br.newton_options.verbose = false\n\tbr = continuation(prob, PALC(), opts_br; normC = norminf)\n\nscene = plot(br, vars = (:param, :x1))","category":"page"},{"location":"tutorials/ode/Colpitts/#Periodic-orbits-with-Multiple-Standard-Shooting","page":"🟡 Colpitts–type Oscillator","title":"Periodic orbits with Multiple Standard Shooting","text":"","category":"section"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"We use shooting to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Thanks to [Lamour], we can just compute the Floquet coefficients to get the nonlinear stability of the periodic orbit. Two period doubling bifurcations are detected.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Note that we use Automatic Branch Switching from a Hopf bifurcation despite the fact the normal form implemented in BifurcationKit.jl is not valid for DAE. For example, it predicts a subciritical Hopf point whereas we see below that it is supercritical. Nevertheless, it provides a","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"using DifferentialEquations\n\n# this is the ODEProblem used with `DiffEqBase.solve`\n# we set the initial conditions\nprob_dae = ODEFunction(Colpitts!; mass_matrix = Be)\nprobFreez_ode = ODEProblem(prob_dae, z0, (0., 1.), par_Colpitts)\n\n# we lower the tolerance of newton for the periodic orbits\noptnpo = @set optn.tol = 1e-9\n@set! optnpo.eigsolver = DefaultEig()\n\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= -0.0001, p_min = 0.2, max_steps = 50, newton_options = optnpo, nev = 4, tol_stability = 1e-3, plot_every_step = 5)\n\n\n# Shooting functional. Note the stringent tolerances used to cope with\n# the extreme parameters of the model\nprobSH = ShootingProblem(10, probFreez_ode, Rodas5P(); reltol = 1e-10, abstol = 1e-13)\n\n# automatic branching from the Hopf point\nbr_po = continuation(br, 1, opts_po_cont, probSH;\n\tplot = true, verbosity = 3,\n\tlinear_algo = MatrixBLS(),\n\t# δp is use to parametrise the first parameter point on the\n\t# branch of periodic orbits\n\tδp = 0.001,\n\trecord_from_solution = (u, p) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, u, (@set par_Colpitts.μ=p.p))\n\t\tm = maximum(outt[1,:])\n\t\treturn (s = m, period = u[end])\n\tend,\n\t# plotting of a solution\n\tplot_solution = (x, p; k...) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, x, (@set par_Colpitts.μ=p.p))\n\t\tplot!(outt.t, outt[2,:], subplot = 3)\n\t\tplot!(br, vars = (:param, :x1), subplot = 1)\n\tend,\n\t# the newton Callback is used to reject residual > 1\n\t# this is to avoid numerical instabilities from DE.jl\n\tcallback_newton = BK.cbMaxNorm(1.0),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"(Image: )","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"with detailed information","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":" ┌─ Curve type: PeriodicOrbitCont from Hopf bifurcation point.\n ├─ Number of points: 38\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter μ starts at 0.7642229295455086, ends at 0.6352549726782099\n ├─ Algo: PALC\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, pd at μ ≈ +0.73116245 ∈ (+0.73116245, +0.73152250), |δp|=4e-04, [converged], δ = ( 1, 1), step = 17, eigenelements in eig[ 18], ind_ev = 1\n- # 2, pd at μ ≈ +0.67272920 ∈ (+0.67272920, +0.67310008), |δp|=4e-04, [converged], δ = (-1, -1), step = 27, eigenelements in eig[ 28], ind_ev = 1\n- # 3, endpoint at μ ≈ +0.63525497, step = 37","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Let us show that this bifurcation diagram is valid by showing evidences for the period doubling bifurcation.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"probFreez_ode = ODEProblem(prob_dae, br.specialpoint[1].x .+ 0.01rand(4), (0., 200.), @set par_Colpitts.μ = 0.733)\n\nsolFreez = @time solve(probFreez_ode, Rodas4(), progress = true;reltol = 1e-10, abstol = 1e-13)\n\nscene = plot(solFreez, vars = [2], xlims=(195,200), title=\"μ = $(probFreez_ode.p.μ)\")","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"and after the bifurcation","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"probFreez_ode = ODEProblem(prob_dae, br.specialpoint[1].x .+ 0.01rand(4), (0., 200.), @set par_Colpitts.μ = 0.72)\n\nsolFreez = @time solve(probFreez_ode, Rodas4(), progress = true;reltol = 1e-10, abstol = 1e-13)\n\nscene = plot(solFreez, vars = [2], xlims=(195,200), title=\"μ = $(probFreez_ode.p.μ)\")","category":"page"},{"location":"tutorials/ode/Colpitts/#References","page":"🟡 Colpitts–type Oscillator","title":"References","text":"","category":"section"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"[Rabier]: Rabier, Patrick J. “The Hopf Bifurcation Theorem for Quasilinear Differential-Algebraic Equations.” Computer Methods in Applied Mechanics and Engineering 170, no. 3–4 (March 1999): 355–71. https://doi.org/10.1016/S0045-7825(98)00203-5.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"[Lamour]: Lamour, René, Roswitha März, and Renate Winkler. “How Floquet Theory Applies to Index 1 Differential Algebraic Equations.” Journal of Mathematical Analysis and Applications 217, no. 2 (January 1998): 372–94. https://doi.org/10.1006/jmaa.1997.5714.","category":"page"},{"location":"constrainedproblem/#Constrained-problems","page":"Constrained problems","title":"Constrained problems","text":"","category":"section"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"compat: Experimental\nThis feature is still experimental. It has not been tested thoroughly and may not work, especially the case of multiple constraints and matrix-free functionals.","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"This section is dedicated to the study of an equation (in x) F(x,p)=0 where one wishes to add a constraint g(x,p)=0. Hence, one is interested in solving in the couple (xp):","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"left\nbeginarrayl\nF(xp)=0 \ng(xp)=0\nendarrayright","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"There are several situations where this proves useful:","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"the pseudo-arclength continuation method is such a constrained problem, see continuation for more details.\nwhen the equation F(x) has a continuous symmetry described by a Lie group G and action gcdot x for gin G. One can reduce the symmetry of the problem by considering the constrained problem:","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"left\nbeginarrayl\nF(x) + pcdot Tcdot x=0 \nlangle Tcdot x_refx-x_refrangle=0\nendarrayright","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"where T is a generator of the Lie algebra associated to G and x_ref is a reference solution. This is known as the freezing method.","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"unknown: Reference\nSee Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation. for more information on the freezing method.","category":"page"},{"location":"gettingstarted/#Getting-Started-with-BifurcationKit","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"This tutorial will introduce you to the functionality for computing bifurcation diagrams and follow branch of solutions.","category":"page"},{"location":"gettingstarted/#Example-1:-solving-the-perturbed-pitchfork-equation","page":"Getting Started with BifurcationKit","title":"Example 1: solving the perturbed pitchfork equation","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In this example, we will solve the equation","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"mu + x-fracx^33=0","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"as function of mu by looking at the solution in connected component of (x_0mu_0)approx(-2-1). Here uinmathbb R is the state variable and mu is our parameter. The general workflow is to define a problem, solve the problem, and then analyze the solution. The full code for solving this problem is:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using BifurcationKit, Plots\nF(x, p) = @. p.μ + x - x^3/3\nprob = BifurcationProblem(F, [-2.], (μ = -1.,), (@lens _.μ);\n record_from_solution = (x,p) -> (x = x[1]))\nopts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(), opts)\nplot(br)\nscene = plot(br) #hide","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"where the pieces are described below.","category":"page"},{"location":"gettingstarted/#Step-1:-Defining-a-Problem","page":"Getting Started with BifurcationKit","title":"Step 1: Defining a Problem","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"To solve this numerically, we define a problem type by giving it the equation, the initial condition, the parameters and the parameter axis to solve over:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using BifurcationKit\nF(x, p) = @. p.μ + x - x^3/3\nprob = BifurcationProblem(F, [-2.], (μ = -1.,), (@lens _.μ);\n record_from_solution = (x,p) -> (x = x[1]))","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Note that BifurcationKit.jl will choose the types for the problem based on the types used to define the problem type. For our example, notice that u0 is a Vector{Float64}, and therefore this will solve with the dependent variables being Vector{Float64}. You can use this to choose to solve with Float32 for example to run this on the GPU (see example).","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"You can customize a few scalar indicators for each step (for example if you don't want to save all solutions) by providing a function record_from_solution. You can also control how the solution is plotted during a continuation run by providing a function plot_solution. This is especially useful when studying PDE for example.","category":"page"},{"location":"gettingstarted/#Step-2:-Solving-a-Problem","page":"Getting Started with BifurcationKit","title":"Step 2: Solving a Problem","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"After defining a problem, you \"solve\" it using continuation.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(), opts)\nnothing #hide","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The solvers can be controlled using the available options ContinuationPar. For example, we can increase the maximum continuation step (in order to get a less points) by using the command dsmax = 0.25","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using Plots\nopts = ContinuationPar(p_min = -1., p_max = 1., dsmax = 0.25, max_steps = 1000)\nbr = continuation(prob, PALC(), opts)\nscene = plot(br)","category":"page"},{"location":"gettingstarted/#Choosing-a-continuation-Algorithm","page":"Getting Started with BifurcationKit","title":"Choosing a continuation Algorithm","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"BifurcationKit.jl offers a much wider variety of continuation algorithms than traditional continuation softwares. Many of these algorithms are from recent research and have their own strengths and weaknesses. Each algoritm comes with a doc string, for example:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"? PALC","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"For example, you can chose a different tangent predictor in PALC","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(tangent = Bordered()), opts)\nscene = plot(br)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"or you can use the Moore-Penrose continuation algorithm","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, MoorePenrose(), opts)\nscene = plot(br)","category":"page"},{"location":"gettingstarted/#Step-3:-Analyzing-the-Solution","page":"Getting Started with BifurcationKit","title":"Step 3: Analyzing the Solution","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The result of continuation is a solution object. A summary of the result is provided by the show method:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"show(br) # this is equivalent to the REPL julia> br","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"From there, you can see that the branch has 55 points, the algorithm is also recalled because it can be modified internally. This summary shows that two bifurcation points where detected. At each such point, the couple δ indicates how many real/complex eigenvalues crossed the imaginary axis. This is useful for debugging or when non generic bifurcations are encountered.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"We can access the 5th value of the branch with:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br[5]","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The solution contains many other fields:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"propertynames(br)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Hence, the eigenelements are saved in br.eig, the solutions are saved in br.sol and the bifurcation points in br.specialpoint.","category":"page"},{"location":"gettingstarted/#Plotting-branches","page":"Getting Started with BifurcationKit","title":"Plotting branches","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"While one can directly plot solution time points using the tools given above, convenience commands are defined by recipes for Plots.jl. To plot the solution object, simply call plot:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"#]add Plots # You need to install Plots.jl before your first time using it!\nusing Plots\n#plotly() # You can optionally choose a plotting backend\nplot(br)\nscene = plot(br) #hide","category":"page"},{"location":"gettingstarted/#Example-2:-simple-branching","page":"Getting Started with BifurcationKit","title":"Example 2: simple branching","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In this example, we will solve the equation","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"0 = xcdot(mu-x)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"as function of mu. Here uinmathbb R is the state variable and mu is our parameter.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In our example, we know by calculus that the solutions to this equation are u_0(mu)=0 and u_1(mu)=mu but we will use BifurcationKit.jl to solve this problem numerically, which is essential for problems where a symbolic solution is not known.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In case we know there are many branches, the best is to use an automatic method to compute them all. We will focus on bifurcationdiagram which computes the connected component of the initial guess in the plane (xmu). An alternative is to use Deflated Continuation.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"We define a problem type by giving it the equation, the initial condition, the parameters and the parameter axis to solve over:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using Plots\nusing BifurcationKit\n\nFbp(u, p) = @. u * (p.μ - u)\n\n# bifurcation problem\nprob = BifurcationProblem(Fbp, [0.0], (μ = -0.2,),\n\t# specify the continuation parameter\n\t(@lens _.μ), \n\trecord_from_solution = (x, p) -> x[1])","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"We then aim at calling bifurcationdiagram which will do the jobs of computing recursively the branches which are connected together. Compared to continuation, bifurcationdiagram requires the maximal level of recursion (in this case 2 because there are 2 branches) and a function providing the continuation parameters for each branch (which may differ from branch to branch if the user decides). This explains the following code: ","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"# options for continuation\nopts_br = ContinuationPar(\n\t# parameter interval\n\tp_max = 0.2, p_min = -0.2,\n\t# detect bifurcations with bisection method\n\t# we increase the precision of the bisection\n\tn_inversion = 4)\n\n# automatic bifurcation diagram computation\ndiagram = bifurcationdiagram(prob, PALC(),\n\t# very important parameter. This specifies the maximum amount of recursion\n\t# when computing the bifurcation diagram. It means we allow computing branches of branches\n\t# at most in the present case.\n\t2,\n\t(args...) -> opts_br,\n\t)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"You can plot the diagram like","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"plot(diagram)","category":"page"},{"location":"gettingstarted/#gt-hopf","page":"Getting Started with BifurcationKit","title":"Example 3: continuing periodic orbits","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In this example, we will compute periodic orbits of the Stuart-Landau oscillator:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"beginaligned\nfracdudt = r u - nu v - (u^2+v^2) (c_3 u - mu v) \nfracdvdt = r v + nu u - (u^2+v^2) (c_3 + mu u)\nendaligned","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The ODE is easily written with a function:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using BifurcationKit, Parameters, Plots\n\nfunction Fsl(X, p)\n @unpack r, μ, ν, c3 = p\n u, v = X\n\n ua = u^2 + v^2\n\n [\n r * u - ν * v - ua * (c3 * u - μ * v)\n r * v + ν * u - ua * (c3 * v + μ * u)\n ]\nend","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"and then we can use this to define a bifurcation problem:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"par_sl = (r = 0.1, μ = 0., ν = 1.0, c3 = 1.0)\nu0 = zeros(2)\nprob = BifurcationProblem(Fsl, u0, par_sl, (@lens _.r))","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"For this simple problem, we detect the existence of periodic orbits by locating a Hopf bifurcation. This is done as in the previous example by continuing the zero solution:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar()\nbr = continuation(prob, PALC(), opts, bothside = true)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Having found a Hopf bifurcation, we compute the branch of periodic orbits which is nearby. Thus, we provide the branch br, the index of the special point we want to branch from: 2 in this case and a method PeriodicOrbitOCollProblem(20, 5) to compute periodic orbits. You can look at Periodic orbits computation for a list of all methods. Suffice it to say that PeriodicOrbitOCollProblem is the default method in the case of ODEs.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po = continuation(br, 2, opts,\n PeriodicOrbitOCollProblem(20, 5)\n )","category":"page"},{"location":"gettingstarted/#Analyzing-the-Solution","page":"Getting Started with BifurcationKit","title":"Analyzing the Solution","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The branch of periodic orbits has been computed. You can look at what is recorded in the first point on the branch:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po[1]","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"It shows that the maximum/minimum/amplitude/period of the periodic orbit are recorded by default. You can also plot all the branches as follows","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"plot(br, br_po, branchlabel = [\"equilibria\", \"periodic orbits\"])","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Finally, if you are interested in the periodic orbits saved in br_po, for example to plot it, the method get_periodic_orbit is what you are looking for:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"sol = get_periodic_orbit(br_po, 10)\nplot(sol.t, sol[1,:], label = \"u\", xlabel = \"time\")\nplot!(sol.t, sol[2,:], label = \"v\", xlabel = \"time\")","category":"page"},{"location":"gettingstarted/#Plotting-the-periodic-orbit-during-continuation","page":"Getting Started with BifurcationKit","title":"Plotting the periodic orbit during continuation","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"If you plot the solution during continuation, you see that the right bottom panel is empty ; this panel is used to plot the solution at the current continuation step:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po = continuation(br, 2, opts,\n PeriodicOrbitOCollProblem(20, 5);\n plot = true,\n )\nscene = title!(\"\") #hide","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"(Note that the bottom panel is a plot of the eigenvalues of the jacobian in the complex plane at the current continuation step. )","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In order to plot the periodic solution during continuation, you need to supply a periodic_solution to continuation. This is not done by default because in some cases, obtaining the solution is costly (e.g. for Shooting methods). Based on the previous paragraph, it is straightforward to implement this plotting function:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po = continuation(br, 2, opts,\n PeriodicOrbitOCollProblem(20, 5);\n plot = true,\n plot_solution = (x, par; k...) -> begin\n # par is a Named tuple which contains \n # the problem for computing periodic orbits\n # and the value of the parameter at the current step\n sol = get_periodic_orbit(par.prob, x, par.p)\n plot!(sol.t, sol.u'; xlabel = \"time\", label=\"\", k...)\n end\n )\nscene = title!(\"\") #hide","category":"page"},{"location":"interfaceFlow/#Interface-for-Flow-of-Cauchy-problem","page":"Flow","title":"Interface for Flow of Cauchy problem","text":"","category":"section"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"Here is a description of the interface that is used to specify flows or semigroups of solutions of a Cauchy problem fracdudt = F(u p)quad u(0) = u_0","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"More precisely, we call flow the mapping Flow(x p t) = u(t).","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"The flow fl must be a subtype of the abstract type AbstractFlow. Note that in most cases, we only need u(t). However, for plotting, we need optionally the full trajectory with time stamps in 0T.","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"Another point is the need for implementing serial versions of multithreaded flows.","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"Required methods Brief description\nvf(fl, x, p) The vector field F(x, p) associated to a Cauchy problem. Used for the differential of the shooting problem. Must return F(x, p)\nevolve(fl, x, par, t; k...) the function implements the flow (or semigroup) (x, p, t) -> flow(x, p, t) associated to an autonomous Cauchy problem. Only the last time point must be returned in the form Named Tuple (u = ..., t = t). In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, x, par, Inf).\nOptional methods Brief description\nevolve(fl, x, par, t; k...) Same as above but for t::AbstractVector of some length M and x a matrix of size N x M. In this case, you are asked to compute several flows flow(x[:, i],p,t[i]). This can be done in parallel.\nevolve(fl, x, par, dx, t; k...) The differential dflow of the flow w.r.t. x, (x, p, dx, t) -> dflow(x, p, dx, t). One important thing is that we require dflow(x, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = dflow(x, p, dx, t)), the last component being the value of the derivative of the flow.\nevolve(fl, ::Val{:Full}, x, par, t; k...) The function implements the flow (or semigroup) associated to an autonomous Cauchy problem (x, p, t) -> flow(x, p, t). The whole solution on the time interval [0,t] must be returned. It is not strictly necessary to provide this, it is mainly used for plotting on the user side. In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, Val(:Full), x, par, Inf).\nevolve(fl, ::Val{:SerialTimeSol}, x, par, t; k...) Serial version of the flow. Used for Matrix based jacobian (Shooting and Poincaré Shooting) and diffPoincareMap\nevolve(fl, ::Val{:TimeSol}, x, par, t = Inf; k...) Flow which returns the tuple (t, u(t)). Optional, mainly used for plotting on the user side.\nevolve(fl, ::Val{:SerialdFlow}, x, par, dx, t; k...) Serial version of dflow. Used internally when using parallel multiple shooting. Named Tuple (u = ..., du = ..., t = t).","category":"page"},{"location":"tutorials/tutorialsCGLShoot/#cglshoot","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"","category":"section"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"Pages = [\"tutorialsCGLShoot.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"In this tutorial, we re-visit the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS) using a Standard Simple Shooting method. In the tutorial 1d Brusselator (advanced user), we used the implicit solver Rodas4P for the shooting. We will use the exponential-RK scheme ETDRK2 ODE solver to compute the solution of cGL equations. This method is convenient for solving semilinear problems of the form","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"dot x = Ax+g(x)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"where A is the infinitesimal generator of a C_0-semigroup. We use the same beginning as in 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS):","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"using Revise\n\tusing DiffEqOperators, DifferentialEquations\n\tusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\n\tconst BK = BifurcationKit\n\nfunction Laplacian2D(Nx, Ny, lx, ly)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Dirichlet0BC(typeof(hx))\n\tQy = Dirichlet0BC(typeof(hy))\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A, D2x\nend","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We then encode the PDE:","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"function NL!(f, u, p, t = 0.)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@. f1 .= r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1\n\t@. f2 .= r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\n\treturn f\nend\n\nfunction Fcgl!(f, u, p, t = 0.)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\nend\n\nNL(u, p) = NL!(similar(u), u, p)\nFcgl(u, p, t = 0.) = Fcgl!(similar(u), u, p, t)\n\nfunction Jcgl(u, p, t = 0.)\n\t@unpack r, μ, ν, c3, c5, Δ = p\n\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1u = zero(u1)\n\tf2u = zero(u1)\n\tf1v = zero(u1)\n\tf2v = zero(u1)\n\n\t@. f1u = r - 2 * u1 * (c3 * u1 - μ * u2) - c3 * ua - 4 * c5 * ua * u1^2 - c5 * ua^2\n\t@. f1v = -ν - 2 * u2 * (c3 * u1 - μ * u2) + μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2u = ν - 2 * u1 * (c3 * u2 + μ * u1) - μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2v = r - 2 * u2 * (c3 * u2 + μ * u1) - c3 * ua - 4 * c5 * ua * u2 ^2 - c5 * ua^2\n\n\tjacdiag = vcat(f1u, f2v)\n\n\tΔ + spdiagm(0 => jacdiag, n => f1v, -n => f2u)\nend","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"with parameters","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"Nx = 41\nNy = 21\nn = Nx*Ny\nlx = pi\nly = pi/2\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)[1]\npar_cgl = (r = 0.5, μ = 0.1, ν = 1.0, c3 = -1.0, c5 = 1.0, Δ = blockdiag(Δ, Δ))\nsol0 = 0.1rand(2Nx, Ny)\nsol0_f = vec(sol0)\n\nprob = BK.BifurcationProblem(Fcgl, sol0_f, par_cgl, (@lens _.r); J = Jcgl)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"and the ODE problem","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"f1 = DiffEqArrayOperator(par_cgl.Δ)\nf2 = NL!\nprob_sp = SplitODEProblem(f1, f2, sol0_f, (0.0, 120.0), (@set par_cgl.r = 1.2), dt = 0.1)\n# we solve the PDE!!!\nsol = @time solve(prob_sp, ETDRK2(krylov=true); abstol=1e-14, reltol=1e-14)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/#Automatic-branch-switching-from-the-Hopf-points","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"Automatic branch switching from the Hopf points","text":"","category":"section"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We show how to use automatic branch switching from the Hopf points computed in the previous section. To compute the periodic orbits, we use a Standard Shooting method.","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We first recompute the Hopf points as in the previous tutorial:","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"eigls = EigArpack(1.0, :LM)\nopt_newton = NewtonPar(tol = 1e-9, verbose = true, eigsolver = eigls, max_iterations = 20)\nopts_br = ContinuationPar(dsmax = 0.02, ds = 0.01, p_max = 2., detect_bifurcation = 3, nev = 15, newton_options = (@set opt_newton.verbose = false), n_inversion = 4)\n\nbr = @time continuation(prob, PALC(), opts_br, verbosity = 0)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We then compute the differentials of the vector field, this is needed by the branch switching method because it first computes the Hopf normal form. Thankfully, this is little work using Automatic Differentiation.","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We define the linear solvers to be use by the (Matrix-Free) shooting method","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"ls = GMRESIterativeSolvers(reltol = 1e-4, maxiter = 50, verbose = false)\neig = EigKrylovKit(tol = 1e-7, x₀ = rand(2Nx*Ny), verbose = 2, dim = 40)\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 25, linsolver = ls, eigsolver = eig)\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.02, ds= 0.01, p_max = 2.5, max_steps = 32, newton_options = optn, nev = 7, tol_stability = 1e-3, detect_bifurcation = 3, plot_every_step = 1)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"as","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"Mt = 1 # number of time sections\nbr_po = continuation(\n\t# we want to compute the bifurcated branch from\n\t# the first Hopf point\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n\t# this is how to pass the method to compute the periodic\n\t# orbits. We shall use 1 section and the ODE solver ETDRK2\n\tShootingProblem(Mt, prob_sp, ETDRK2(krylov = true); abstol = 1e-10, reltol = 1e-8, jacobian = BK.FiniteDifferencesMF()) ;\n\t# linear solver for bordered linear system\n\t# we combine the 2 solves. It is here faster than BorderingBLS()\n\tlinear_algo = MatrixFreeBLS(@set ls.N = Mt*2n+2),\n\t# to help branching from the Hopf point\n\tampfactor = 1.5, δp = 0.01,\n\t# regular parameters for the continuation\n\tverbosity = 3, plot = true,\n\t# a few parameters saved during run\n\trecord_from_solution = (u, p) -> (amp = BK.getamplitude(p.prob, u, (@set par_cgl.r = p.p)), period = u[end]),\n\t# plotting of a section\n\tplot_solution = (x, p; k...) -> heatmap!(reshape(x[1:Nx*Ny], Nx, Ny); color=:viridis, k...),\n\t# print the Floquet exponent\n\tfinalise_solution = (z, tau, step, contResult; k...) ->\n\t\t(Base.display(contResult.eig[end].eigenvals) ;true),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGLShoot/#Manual-branch-switching-from-the-Hopf-points","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"Manual branch switching from the Hopf points","text":"","category":"section"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"The goal of this section is to show how to use the package in case automatic branch switching fails. This can happen for tedious PDEs and \"one has to get his hands dirty\".","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We decide to use Standard Shooting and thus define a Shooting functional","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"probSh = ShootingProblem(\n\t# we pass the ODEProblem encoding the flow and the time stepper\n\tremake(prob_sp, p = (@set par_cgl.r = 1.2)), ETDRK2(krylov = true),\n\n\t# this is the phase condition\n\t[sol[:, end]];\n\n\t# parameter axis\n\tlens = (@lens _.r),\n\n\t# jacobian of the periodic orbit functional\n\tjacobian = BK.FiniteDifferencesMF(),\n\n\t# these are options passed to the ODE time stepper\n\tabstol = 1e-14, reltol = 1e-14)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We use the solution from the ODE solver as a starting guess for the shooting method.","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"# initial guess with period 6.9 using solution at time t = 116\ninitpo = vcat(sol(116.), 6.9) |> vec\n\n# linear solver for shooting functional\nls = GMRESIterativeSolvers(reltol = 1e-4, N = 2Nx * Ny + 1, maxiter = 50, verbose = false)\n\n# newton parameters\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 20, linsolver = ls)\n\n# continuation parameters\neig = EigKrylovKit(tol=1e-7, x₀ = rand(2Nx*Ny), verbose = 2, dim = 40)\nopts_po_cont = ContinuationPar(dsmin = 0.001,\n\t\t\t\tdsmax = 0.01,\n\t\t\t\tds = -0.01,\n\t\t\t\tp_max = 1.5,\n\t\t\t\tmax_steps = 60,\n\t\t\t\tnewton_options = (@set optn.eigsolver = eig),\n\t\t\t\tnev = 5,\n\t\t\t\ttol_stability = 1e-3,\n\t\t\t\tdetect_bifurcation = 0)\n\nbr_po = @time continuation(probSh,\n\tinitpo, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\tlinear_algo = MatrixFreeBLS(@set ls.N = probSh.M*2n+2),\n\tplot_solution = (x, p; kwargs...) -> heatmap!(reshape(x[1:Nx*Ny], Nx, Ny); color=:viridis, kwargs...),\n\trecord_from_solution = (u, p) -> BK.getamplitude(probSh, u, (@set par_cgl.r = p.p); ratio = 2), normC = norminf)","category":"page"},{"location":"deflatedproblem/#Deflated-problems","page":"Deflated problems","title":"Deflated problems","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"unknown: References\nP. E. Farrell, A. Birkisson, and S. W. Funke. Deflation techniques for finding distinct solutions of nonlinear partial differential equations. SIAM J. Sci. Comput., 2015.,","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Assume you want to solve F(x)=0 with a Newton algorithm but you want to avoid the algorithm to return some already known solutions x_i i=1cdots n.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"The idea proposed in the paper quoted above is to penalize these solutions by looking for the zeros of the function G(x)=F(x)M(x) where","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"M(x) = prod_i=1^nleft(x - x_i^-2p + alpharight)","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"and alpha0. Obviously F and G have the same zeros away from the x_is but the factor M penalizes the residual of the Newton iterations of G, effectively producing zeros of F different from x_i.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"tip: Tip\nIn some case, you may want to use a custom distance, in place of the squared norm cdot^2. Please see DeflationOperator for how to do this.","category":"page"},{"location":"deflatedproblem/#Encoding-of-the-functional","page":"Deflated problems","title":"Encoding of the functional","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"A composite type DeflationOperator implements this functional. Given a deflation operator M = DeflationOperator(p, dot, α, xis), you can build a deflated functional pb = DeflatedProblem(F, J, M) which you can use to access the values of G by doing pb(x). A Matrix-Free / Sparse linear solver is implemented which works on the GPU.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"the dot argument in DeflationOperator lets you specify a dot product from which the norm is derived in the expression of M.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"See example Snaking computed with deflation.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Note that you can add new solution x0 to M by doing push!(M, x0). Also M[i] returns xi.","category":"page"},{"location":"deflatedproblem/#Computation-with-newton","page":"Deflated problems","title":"Computation with newton","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Most newton functions can be used with a deflated problem, see for example Snaking computed with deflation. The idea is to pass the deflation operator M. For example, we have the following overloaded method, which works on GPUs:","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"newton(prob::BifurcationKit.AbstractBifurcationProblem,\n\t\tdefOp::DeflationOperator,\n\t\toptions::NewtonPar,\n\t\t_linsolver = DefProbCustomLinearSolver();\n\t\tkwargs...)","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"We refer to the regular newton for more information. This newton penalises the roots saved in defOp.roots. ","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Compared to newton, the only different arguments are","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"defOp::DeflationOperator deflation operator\nlinsolver linear solver used to invert the Jacobian of the deflated functional.\ncustom solver DefProbCustomLinearSolver() with requires solving two linear systems J⋅x = rhs.\nFor other linear solvers <: AbstractLinearSolver, a matrix free method is used for the deflated functional.\nif passed Val(:autodiff), then ForwardDiff.jl is used to compute the jacobian of the deflated problem\nif passed Val{:fullIterative}, then a full matrix free method is used.","category":"page"},{"location":"deflatedproblem/#Simple-example","page":"Deflated problems","title":"Simple example","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"In this basic example, we show how to get the different roots of F","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"using BifurcationKit, LinearAlgebra\nF(x, p) = @. (x-1) * (x-2)\n# define a deflation operator which deflates the \n# already know solution x = 1\ndeflationOp = DeflationOperator(2, dot, 0.1, [ones(1)])\n# define a problem, this compute jacobian automatically\nprob = BifurcationProblem(F, rand(1), nothing)\n# call deflated newton\nsol = newton(prob, deflationOp, NewtonPar())\nprintln(\"We found the additional root: \", sol.u)","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"tip: Tip\nYou can use this method for periodic orbits as well by passing the deflation operator M to the newton method","category":"page"},{"location":"tutorials/ode/tutorialCO/#CO-oxidation-(codim-2)","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"Pages = [\"tutorialCO.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"In this tutorial, we study the Bykov–Yablonskii–Kim model of CO oxidation (see [Govaerts]). The goal of the tutorial is to show a simple example of how to perform codimension 2 bifurcation detection.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"leftbeginarrayldotx=2 q_1 z^2-2 q_5 x^2-q_3 x y doty=q_2 z-q_6 y-q_3 x y dots=q_4 z-k q_4 sendarrayrighttagE","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"where z=1-x-y-s.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We start with some imports:","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nnothing # hide","category":"page"},{"location":"tutorials/ode/tutorialCO/#Problem-setting","page":"🟡 CO oxidation (codim 2)","title":"Problem setting","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We can now encode the vector field (E) in a function and use automatic differentiation to compute its various derivatives.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"# vector field of the problem\nfunction COm(u, p)\n\t@unpack q1,q2,q3,q4,q5,q6,k = p\n\tx, y, s = u\n\tz = 1-x-y-s\n\tout = similar(u)\n\tout[1] = 2q1 * z^2 - 2q5 * x^2 - q3 * x * y\n\tout[2] = q2 * z - q6 * y - q3 * x * y\n\tout[3] = q4 * z - k * q4 * s\n\tout\nend\n\n# parameters used in the model\npar_com = (q1 = 2.5, q2 = 0.6, q3 = 10., q4 = 0.0675, q5 = 1., q6 = 0.1, k = 0.4)\n\nrecordCO(x, p) = (x = x[1], y = x[2], s = x[3])\n\n# initial condition\nz0 = [0.07, 0.2, 05]\n\n# Bifurcation Problem\nprob = BifurcationProblem(COm, z0, par_com, (@lens _.q2); record_from_solution = recordCO)\nnothing # hide","category":"page"},{"location":"tutorials/ode/tutorialCO/#Continuation-and-codim-1-bifurcations","page":"🟡 CO oxidation (codim 2)","title":"Continuation and codim 1 bifurcations","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"Once the problem is set up, we can continue the state w.r.t. q_2 and detect codim 1 bifurcations. This is achieved as follows:","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"# continuation parameters\nopts_br = ContinuationPar(p_min = 0., p_max = 1.9, ds = 0.002, dsmax = 0.01)\n\n# compute the branch of solutions\nbr = continuation(prob, PALC(), opts_br; plot = true, verbosity = 2, normC = norminf)","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"# plot the branch\nscene = plot(br, xlims = (0.8,1.8))","category":"page"},{"location":"tutorials/ode/tutorialCO/#Continuation-of-Fold-points","page":"🟡 CO oxidation (codim 2)","title":"Continuation of Fold points","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We follow the Fold points in the parameter plane (q_2 k). We tell the solver to consider br.specialpoint[2] and continue it.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"sn_codim2 = continuation(br, 2, (@lens _.k),\n\tContinuationPar(opts_br, p_max = 2.2, ds = -0.001, dsmax = 0.05);\n\tnormC = norminf,\n\t# detection of codim 2 bifurcations\n\tdetect_codim2_bifurcation = 2,\n\t# update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# compute both sides of the initial condition\n\tbothside = true,)\n\nscene = plot(sn_codim2, vars = (:q2, :x), branchlabel = \"Fold\")\nplot!(scene, br, xlims=(0.8, 1.8))","category":"page"},{"location":"tutorials/ode/tutorialCO/#Continuation-of-Hopf-points","page":"🟡 CO oxidation (codim 2)","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We tell the solver to consider br.specialpoint[1] and continue it.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"hp_codim2 = continuation(br, 1, (@lens _.k),\n\tContinuationPar(opts_br, p_max = 2.8, ds = -0.001, dsmax = 0.05) ;\n\tnormC = norminf,\n\t# detection of codim 2 bifurcations\n\tdetect_codim2_bifurcation = 2,\n\t# tell to start the Hopf problem using eigen elements: compute left eigenvector\n\t#start_with_eigen = true,\n\t# we update the Hopf problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# compute both sides of the initial condition\n\tbothside = true,\n\t)\n\n# plotting\nscene = plot(sn_codim2, vars = (:q2, :x), branchlabel = \"Fold\")\nplot!(scene, hp_codim2, vars = (:q2, :x), branchlabel = \"Hopf\")\nplot!(scene, br, xlims = (0.6, 1.5))","category":"page"},{"location":"tutorials/ode/tutorialCO/#References","page":"🟡 CO oxidation (codim 2)","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"tutorials/cgl1dwave/#1d-Ginzburg-Landau-equation-(TW)","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"","category":"section"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"Pages = [\"cgl1dwave.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We look at the Ginzburg-Landau equations in 1d with periodic boundary condition. The goal of this tutorial is to show how one can study a Hopf bifurcation with symmetry group O(2). It is known that this bifurcation supports standing / travelling waves. Using the tools for periodic orbits, it is easy to compute the standing wave. We thus focus on the computation of the travelling wave.","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"The equations are as follows","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"partial_t u=Delta u+(r+mathrmi v) u-left(c_3+mathrmi muright)u^2 u-c_5u^4 u quad u=u(t x) in mathbbC","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"with periodic boundary conditions. We discretize the circle Omega = (-pipi) with n points. We start by writing the Laplacian:","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\nconst FD = ForwardDiff\n\n# plotting utilities\nplotsol!(x, m, n; np = n, k...) = heatmap!(reshape(x[1:end-1],m,n)[1:np,:]; color = :viridis, k...)\ncontoursol!(x, m, n; np = n, k...) = contour!(reshape(x[1:end-1],m,n)[1:np,:]; color = :viridis, k...)\nplotsol(x,m,n;k...) = (plot();plotsol!(x,m,n;k...))\n\nfunction Laplacian1D(Nx, lx)\n\thx = 2lx/Nx\n\tT = typeof(hx)\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD1x = CenteredDifference(1, 2, hx, Nx)\n\tQx = PeriodicBC(T)\n\n\tΔ = sparse(D2x * Qx)[1] |> sparse\n\tD = sparse(D1x * Qx)[1] |> sparse\n\treturn Δ, D\nend\n\n# add the nonlinearity to f\n@views function NL!(f, u, p)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1 = u[1:n]\n\tu2 = u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1 = f[1:n]\n\tf2 = f[n+1:2n]\n\n\tf1 .+= @. r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1\n\tf2 .+= @. r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\n\treturn f\nend\n\n# full functional\nfunction Fcgl!(f, u, p, t = 0)\n\tmul!(f, p.Δ, u)\n\tNL!(f, u, p)\nend\nFcgl(u, p, t = 0) = Fcgl!(similar(u), u, p)\n\n# analytical expression off the jacobian\n@views function Jcgl(u, p)\n\t@unpack r, μ, ν, c3, c5, Δ = p\n\n\tn = div(length(u), 2)\n\tu1 = u[1:n]\n\tu2 = u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1u = zero(u1)\n\tf2u = zero(u1)\n\tf1v = zero(u1)\n\tf2v = zero(u1)\n\n\t@. f1u = r - 2 * u1 * (c3 * u1 - μ * u2) - c3 * ua - 4 * c5 * ua * u1^2 - c5 * ua^2\n\t@. f1v = -ν - 2 * u2 * (c3 * u1 - μ * u2) + μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2u = ν - 2 * u1 * (c3 * u2 + μ * u1) - μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2v = r - 2 * u2 * (c3 * u2 + μ * u1) - c3 * ua - 4 * c5 * ua * u2 ^2 - c5 * ua^2\n\n\tjacdiag = vcat(f1u, f2v)\n\n\tΔ + spdiagm(0 => jacdiag, n => f1v, -n => f2u)\nend\n\nnothing #hide","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We then define a problem for computing the bifurcations of the trivial state u=0 as function of r.","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"# space discretization\nn = 50\n\nl = pi\nΔ, D = Laplacian1D(n, l)\n\n# model parameters\npar_cgl = (r = 0.0, μ = 0.5, ν = 1.0, c3 = -1.0, c5 = 1.0, Δ = blockdiag(Δ, Δ), Db = blockdiag(D, D), δ = 1.0, N = 2n)\n\n# initial guess\nsol0 = zeros(par_cgl.N)\n\n# bifurcation problem\nprob = BifurcationProblem(Fcgl, sol0, par_cgl, (@lens _.r); J = Jcgl)\n\nopt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.15, ds = 0.001, p_max = 2.5,\n\tdetect_bifurcation = 3, nev = 9, newton_options = (@set opt_newton.verbose = false), max_steps = 100, n_inversion = 8, max_bisection_steps = 20)\nbr = continuation(prob, PALC(), opts_br, verbosity = 0)","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"The first bifurcation point is a regular Hopf bifurcation in the zero mode, i.e. u(x t) = u_0cos(omega t +phi) with no spatial structure. The second bifurcation point, labelled nd is a Hopf bifurcation with O(2) symmetry group generated by the translations T_zcdot u(x) = u(x+y) and the reflection Scdot u(x) = u(-x).","category":"page"},{"location":"tutorials/cgl1dwave/#Computation-of-the-travelling-wave","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"Computation of the travelling wave","text":"","category":"section"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We focus on the O(2)-Hopf (second bifurcation point in br), with frequency omega0, for which no normal form is currently implemented in BifurcationKit.jl. We write zeta_0zeta_1 two eigenvectors associated with the eigenvalue iomega such that","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"T_zcdotzeta_0 = e^im zzeta_0quad T_zcdotzeta_1 = e^-im zzeta_1quad Scdotzeta_0 = zeta_1quad Scdotzeta_1 = zeta_0","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"By the center manifold theory[Haragus], one has","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"u = A(t)zeta_0+B(t)zeta_1+overlineA(t)zeta_0+overlineB(t)zeta_1+textsmall terms","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"Using the normal form, one finds standing waves (A(t)B(t)) = (r_0e^iomega t r_0e^iomega t) with r_0geq 0 and travelling waves (A(t)B(t)) = (r_0e^iomega t 0) at first order in AB. This provides us with a way to compute the initial guess for the travelling waves as written in the following function:","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"function guessFromHopfO2(branch, ind_hopf, eigsolver, M, A, B = 0.; phase = 0, k = 1.)\n\tspecialpoint = branch.specialpoint[ind_hopf]\n\n\t# parameter value at the Hopf point\n\tp_hopf = specialpoint.param\n\n\t# frequency at the Hopf point\n\tωH = imag(branch.eig[specialpoint.idx].eigenvals[specialpoint.ind_ev]) |> abs\n\n\t# eigenvectors for the eigenvalues iω\n\tζ0 = geteigenvector(eigsolver, br.eig[specialpoint.idx][2], specialpoint.ind_ev)\n\tζ0 ./= norm(ζ0)\n\n\tζ1 = geteigenvector(eigsolver, br.eig[specialpoint.idx][2], specialpoint.ind_ev - 2)\n\tζ1 ./= norm(ζ1)\n\n\torbitguess = [real.(specialpoint.x .+\n\t \t\t\tA .* ζ0 .* exp(2pi * complex(0, 1) .* (ii/(M-1) - phase)) .+\n\t\t\t\tB .* ζ1 .* exp(2pi * complex(0, 1) .* (ii/(M-1) - phase))) for ii in 0:M-1]\n\n\treturn (; p = p_hopf, period = 2pi/ωH, guess = orbitguess, x0 = specialpoint.x, ζ0 = ζ0, ζ1 = ζ1)\nend\nnothing #hide","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We can use this function to effectively build a guess for the travelling wave:","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"M = 50 # number of time slices (plotting purposes)\nr_hopf, Th, orbitguess2, hopfpt, eigvec = guessFromHopfO2(br, 2, opt_newton.eigsolver, M, 1. + 0.0im, 1+0.0im; k = 2.) #TW\n\nuold = copy(orbitguess2[1][1:2n])\n\n# we create a TW problem\nprobTW = TWProblem(re_make(prob, params = setproperties(par_cgl; r = r_hopf - 0.01)), par_cgl.Db, uold; jacobian = :FullLU)\n\n# refine the guesss\nwave = newton(probTW, vcat(uold, 0),\n\t\tNewtonPar(verbose = true, max_iterations = 50),\n\t)\nprintln(\"norm wave = \", wave.u[1:end-1] |> norminf)\nplot(wave.u[1:end-1]; linewidth = 5, label = \"solution\")\nplot!(uold, color = :blue, label=\"guess\")","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"Note that in the following code, a generalized eigensolver is automatically created during the call to continuation which properly computes the stability of the wave.","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"amplitude(x) = maximum(x) - minimum(x)\noptn = NewtonPar(tol = 1e-8, verbose = true, max_iterations = 10)\nopt_cont_br = ContinuationPar(p_min = 0.015, p_max = 2.5, newton_options = optn, ds= 0.001, dsmax = 0.1, detect_bifurcation = 3, nev = 10, max_steps = 190, n_inversion = 6)\n\nbr_TW = @time continuation(probTW, wave.u, PALC(), opt_cont_br;\n\trecord_from_solution = (x, p) -> (u∞ = maximum(x[1:n]), s = x[end], amp = amplitude(x[1:n])),\n\tplot_solution = (x, p; k...) -> (plot!(x[1:end-1];k...);plot!(br,subplot=1, legend=false)),\n\tfinalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\tamplitude(z.u[n+1:2n]) > 0.01\nend, bothside = true)\n\nplot(br, br_TW, legend = :bottomright, branchlabel =[\"\",\"TW\"])","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We note that the branch of travelling wave solutions has a Hopf bifurcation point at which point Modulated Travelling waves will emerge. This will be analyzed in the future.","category":"page"},{"location":"tutorials/cgl1dwave/#References","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"References","text":"","category":"section"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"[Haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"tutorials/mittelmannGridap/#2d-Bratu–Gelfand-problem-with-[Gridap.jl](https://github.com/gridap/Gridap.jl)","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"","category":"section"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Pages = [\"mittelmannGridap.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We re-consider the problem of Mittelmann treated in the previous tutorial but using a finite elements method (FEM) implemented in the package Gridap.jl.","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Recall that the problem is defined by solving","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Delta u +NL(lambdau) = 0","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"with Neumann boundary condition on Omega = (01)^2 and where NL(lambdau)equiv-10(u-lambda e^u).","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We start by installing the package GridapBifurcationKit.jl. Then, we can import the different packages:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"using Revise\nusing Plots, Gridap, Setfield\nusing Gridap.FESpaces\nusing GridapBifurcationKit, BifurcationKit\n\n# custom plot function to deal with Gridap\nplotgridap!(x; k...) = (n=isqrt(length(x));heatmap!(reshape(x,n,n); color=:viridis, k...))\nplotgridap(x; k...) =( plot();plotgridap!(x; k...))","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We are now ready to specify the problem using the setting of Gridap.jl: it allows to write the equations very closely to the mathematical formulation:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"# discretisation\nn = 40\ndomain = (0, 1, 0, 1)\ncells = (n,n)\nmodel = CartesianDiscreteModel(domain,cells)\n\n# function spaces\norder = 1\nreffe = ReferenceFE(lagrangian, Float64, order)\nV = TestFESpace(model, reffe, conformity=:H1,)#dirichlet_tags=\"boundary\")\nU = TrialFESpace(V)\n\nΩ = Triangulation(model)\ndegree = 2*order\nconst dΩ = Measure(Ω, degree) # we make it const because it is used in res\n\n# nonlinearity\nNL(u) = exp(u)\n\n# residual\nres(u,p,v) = ∫( -∇(v)⋅∇(u) - v ⋅ (u - p.λ ⋅ (NL ∘ u)) * 10 )*dΩ\n\n# jacobian of the residual\njac(u,p,du,v) = ∫( -∇(v)⋅∇(du) - v ⋅ du ⋅ (1 - p.λ * ( NL ∘ u)) * 10 )*dΩ\n\n# 3rd and 4th derivatives, used for aBS\nd2res(u,p,du1,du2,v) = ∫( v ⋅ du1 ⋅ du2 ⋅ (NL ∘ u) * 10 * p.λ )*dΩ\nd3res(u,p,du1,du2,du3,v) = ∫( v ⋅ du1 ⋅ du2 ⋅ du3 ⋅ (NL ∘ u) * 10 * p.λ )*dΩ\n\n# example of initial guess\nuh = zero(U)\n\n# model parameter\npar_bratu = (λ = 0.01,)\n\n# problem definition\nprob = GridapBifProblem(res, uh, par_bratu, V, U, (@lens _.λ); jac = jac, d2res = d2res, d3res = d3res, plot_solution = (x,p; k...) -> plotgridap!(x; k...))","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We can call then the newton solver:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"optn = NewtonPar(eigsolver = EigArpack())\nsol = newton(prob, NewtonPar(optn; verbose = true))","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"which gives","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 2.4687e-03 │ 0 │\n│ 1 │ 1.2637e-07 │ 1 │\n│ 2 │ 3.3833e-16 │ 1 │\n└─────────────┴──────────────────────┴────────────────┘","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"In the same vein, we can continue this solution as function of lambda:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"opts = ContinuationPar(p_max = 40., p_min = 0.01, ds = 0.01,\n\tmax_steps = 1000, detect_bifurcation = 3, newton_options = optn, nev = 20)\nbr = continuation(prob, PALC(tangent = Bordered()), opts;\n\tplot = true,\n\tverbosity = 0,\n\t)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We obtain:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"julia> br\n ┌─ Number of points: 56\n ├─ Curve of EquilibriumCont\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter λ starts at 0.01, ends at 0.01\n ├─ Algo: PALC\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, bp at λ ≈ +0.36787944 ∈ (+0.36787944, +0.36787944), |δp|=1e-12, [converged], δ = ( 1, 0), step = 13, eigenelements in eig[ 14], ind_ev = 1\n- # 2, nd at λ ≈ +0.27234314 ∈ (+0.27234314, +0.27234328), |δp|=1e-07, [converged], δ = ( 2, 0), step = 21, eigenelements in eig[ 22], ind_ev = 3\n- # 3, bp at λ ≈ +0.15185452 ∈ (+0.15185452, +0.15185495), |δp|=4e-07, [converged], δ = ( 1, 0), step = 29, eigenelements in eig[ 30], ind_ev = 4\n- # 4, nd at λ ≈ +0.03489122 ∈ (+0.03489122, +0.03489170), |δp|=5e-07, [converged], δ = ( 2, 0), step = 44, eigenelements in eig[ 45], ind_ev = 6\n- # 5, nd at λ ≈ +0.01558733 ∈ (+0.01558733, +0.01558744), |δp|=1e-07, [converged], δ = ( 2, 0), step = 51, eigenelements in eig[ 52], ind_ev = 8\n- # 6, endpoint at λ ≈ +0.01000000, step = 55","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannGridap/#Computation-of-the-first-branches","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"Computation of the first branches","text":"","category":"section"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Let us now compute the first branches from the bifurcation points. We start with the one with 1d kernel:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"br1 = continuation(br, 3,\n\tsetproperties(opts; ds = 0.005, dsmax = 0.05, max_steps = 140, detect_bifurcation = 3);\n\tverbosity = 3, plot = true, nev = 10,\n\tusedeflation = true,\n\tcallback_newton = BifurcationKit.cbMaxNorm(100),\n\t)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We also compute the branch from the first bifurcation point on this branch br1:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"br2 = continuation(br1, 3,\n\tsetproperties(opts;ds = 0.005, dsmax = 0.05, max_steps = 140, detect_bifurcation = 3);\n\tverbosity = 0, plot = true, nev = 10,\n\tusedeflation = true,\n\tcallback_newton = BifurcationKit.cbMaxNorm(100),\n\t)\n\nplot(br, br1, br2)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We get:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Finally, we compute the branches from the 2d bifurcation point:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"br3 = continuation(br, 2,\n\tsetproperties(opts; ds = 0.005, dsmax = 0.05, max_steps = 140, detect_bifurcation = 0);\n\tverbosity = 0, plot = true,\n\tusedeflation = true,\n\tverbosedeflation = false,\n\tcallback_newton = BifurcationKit.cbMaxNorm(100),\n\t)\n\nplot(br, br1, br2, br3...)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"(Image: )","category":"page"},{"location":"BifProblem/#Bifurcation-problems","page":"Bifurcation Problem","title":"Bifurcation problems","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"Pages = [\"BifProblem.md\"]\nDepth = 3","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"The idea behind BifurcationKit is to compute bifurcation diagrams in memory limited environments where the device can barely hold the current continuation state. We thus disable by default saving all solutions along the branch and all eigenvectors (see ContinuationPar to change this behaviour). Still, one needs to save a few solution indicators, like for plotting. This is the reason for the function record_from_solution (see below).","category":"page"},{"location":"BifProblem/#Generic-bifurcation-problem","page":"Bifurcation Problem","title":"Generic bifurcation problem","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"BifurcationProblem is the basic / generic structure for encoding a bifurcation problem ; it holds the following fields:","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"the vector field\nan initial guess\na set of parameters\na parameter axis","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"as well as user defined functions for ","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"plotting, plot_solution\nrecording (record_from_solution) indicators about the solution when this one is too large to be saved at every continuation step.","category":"page"},{"location":"BifProblem/#Example","page":"Bifurcation Problem","title":"Example","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"f(x,p) = @. sin(x * p.a)\nu0 = zeros(100_000_000) \nparams = (a = 1.0, b = 2.0)\n\n# record a few components / indicators about x \nmyRecord(x,p) = (x1 = x[1], max = maximum(x), nrm = norm(x, Inf))\n\nprob = BifurcationProblem(f, u0, p, (@lens _.a);\n\trecord_from_solution = myRecord\n\t)","category":"page"},{"location":"BifProblem/#Problem-modification","page":"Bifurcation Problem","title":"Problem modification","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"In case you want to modify an existing problem, you should use the following method","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"re_make(prob::BifurcationKit.AbstractBifurcationProblem;\n\t\tu0 = prob.u0,\n\t\tparams = prob.params,\n\t\tlens::Lens = prob.lens,\n\t\trecord_from_solution = prob.record_from_solution,\n\t\tplot_solution = prob.plot_solution,\n J = missing,\n d2F = missing,\n\t\td3F = missing)","category":"page"},{"location":"BifProblem/#BifurcationKit.re_make-Tuple{BifurcationKit.AbstractBifurcationProblem}","page":"Bifurcation Problem","title":"BifurcationKit.re_make","text":"re_make(\n prob;\n u0,\n params,\n lens,\n record_from_solution,\n plot_solution,\n J,\n Jᵗ,\n d2F,\n d3F\n)\n\n\nThis function changes the fields of a problem ::AbstractBifurcationProblem. For example, you can change the initial condition by doing\n\nre_make(prob; u0 = new_u0)\n\n\n\n\n\n","category":"method"},{"location":"BifProblem/#Example-2","page":"Bifurcation Problem","title":"Example","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"using BifurcationKit, Setfield\nF(x,p) = @. p.a + x^2\n# parameters\npar = (a = 0., b = 2)\nprob = BifurcationProblem(F, zeros(3), par, (@lens _.a))\n# change u0\nprob2 = BifurcationKit.re_make(prob, u0 = rand(3))","category":"page"},{"location":"tutorials/ode/tutorialsODE/#nmepo","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"Pages = [\"tutorialsODE.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"The following model is taken from [Cortes]:","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"leftbeginarrayl\ntau dotE=-E+gleft(J u x E+E_0right) \ndotx=tau_D^-1(1-x)-u E x \ndotu=U E(1-u)-tau_F^-1(u-U)\nendarrayright","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We use this model as a mean to introduce the basics of BifurcationKit.jl, namely the continuation of equilibria and periodic orbits (with the different methods).","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"The model is interesting on its own because the branch of periodic solutions converges to an homoclinic orbit which can be challenging to compute. We provide three different ways to compute these periodic orbits and highlight their pro / cons.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# vector field\nfunction TMvf!(dz, z, p, t = 0)\n\t@unpack J, α, E0, τ, τD, τF, U0 = p\n\tE, x, u = z\n\tSS0 = J * u * x * E + E0\n\tSS1 = α * log(1 + exp(SS0 / α))\n\tdz[1] = (-E + SS1) / τ\n\tdz[2] =\t(1.0 - x) / τD - u * x * E\n\tdz[3] = (U0 - u) / τF + U0 * (1.0 - u) * E\n\tdz\nend\n\n# parameter values\npar_tm = (α = 1.5, τ = 0.013, J = 3.07, E0 = -2.0, τD = 0.200, U0 = 0.3, τF = 1.5, τS = 0.007)\n\n# initial condition\nz0 = [0.238616, 0.982747, 0.367876]\n\n# Bifurcation Problem\nprob = BifurcationProblem(TMvf!, z0, par_tm, (@lens _.E0);\n\trecord_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]),)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We first compute the branch of equilibria","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = -10.0, p_max = -0.9,\n\t# parameters to have a smooth continuation curve\n\tds = 0.04, dsmax = 0.05,)\n\n# continuation of equilibria\nbr = continuation(prob, PALC(tangent=Bordered()), opts_br; normC = norminf)\n\nscene = plot(br, plotfold=false, markersize=3, legend=:topleft)","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"br","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Branch-of-periodic-orbits-with-Trapezoid-method","page":"🟡 Neural mass equation (Hopf aBS)","title":"Branch of periodic orbits with Trapezoid method","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We then compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use finite differences to discretize the problem of finding periodic orbits. Obviously, this will be problematic when the period of the limit cycle grows unbounded close to the homoclinic orbit.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"# newton parameters for the computation of periodic orbits\noptn_po = NewtonPar(tol = 1e-8, max_iterations = 12)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(opts_br, dsmax = 0.1, ds = -0.001, dsmin = 1e-4,\n\tmax_steps = 90, newton_options = optn_po, tol_stability = 1e-8)\n\n# arguments for periodic orbits\n# one function to record information and one\n# function for plotting\nargs_po = (\trecord_from_solution = (x, p) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\t\tmin = minimum(xtt[1,:]),\n\t\t\t\tperiod = getperiod(p.prob, x, p.p))\n\tend,\n\tplot_solution = (x, p; k...) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\targ = (marker = :d, markersize = 1)\n\t\tplot!(xtt.t, xtt[1,:]; label = \"E\", arg..., k...)\n\t\tplot!(xtt.t, xtt[2,:]; label = \"x\", arg..., k...)\n\t\tplot!(xtt.t, xtt[3,:]; label = \"u\", arg..., k...)\n\t\tplot!(br; subplot = 1, putspecialptlegend = false)\n\t\tend,\n\t# we use the supremum norm\n\tnormC = norminf)\n\nMt = 250 # number of time sections\nbr_potrap = continuation(\n\t# we want to branch form the 4th bif. point\n\tbr, 4, opts_po_cont,\n\t# we want to use the Trapeze method to locate PO\n\tPeriodicOrbitTrapProblem(M = Mt);\n\targs_po...,\n\t)\n\nscene = plot(br, br_potrap, markersize = 3)\nplot!(scene, br_potrap.param, br_potrap.min, label = \"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We plot the maximum (resp. minimum) of the limit cycle. We can see that the min converges to the smallest equilibrium indicating a homoclinic orbit.","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Plot-of-some-of-the-periodic-orbits-as-function-of-E_0","page":"🟡 Neural mass equation (Hopf aBS)","title":"Plot of some of the periodic orbits as function of E_0","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We can plot some of the previously computed periodic orbits in the plane (Ex) as function of E_0:","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"plot()\n# fetch the saved solutions\nfor sol in br_potrap.sol[1:2:40]\n\t# periodic orbit\n\tpo = sol.x\n\t# get the mesh and trajectory\n\ttraj = get_periodic_orbit(br_potrap.prob, po, @set par_tm.E0 = sol.p)\n\tplot!(traj[1,:], traj[2,:], xlabel = \"E\", ylabel = \"x\", label = \"\")\nend\ntitle!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Branch-of-periodic-orbits-with-Orthogonal-Collocation","page":"🟡 Neural mass equation (Hopf aBS)","title":"Branch of periodic orbits with Orthogonal Collocation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use Orthogonal Collocation to discretize the problem of finding periodic orbits. This is vastly more precise than the previous method because we use mesh adaptation.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"# continuation parameters\nopts_po_cont = ContinuationPar(opts_br, dsmax = 0.15, ds= -0.001, dsmin = 1e-4,\n\tmax_steps = 100, newton_options = (@set optn_po.tol = 1e-8),\n\ttol_stability = 1e-5)\n\nbr_pocoll = @time continuation(\n\t# we want to branch form the 4th bif. point\n\tbr, 4, opts_po_cont,\n\t# we want to use the Collocation method to locate PO, with polynomial degree 4\n\tPeriodicOrbitOCollProblem(30, 4; meshadapt = true);\n\t# regular continuation options\n\tverbosity = 2, plot = true,\n\t# we reject the newton step if the residual is high\n\tcallback_newton = BK.cbMaxNorm(100.),\n\targs_po...)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Periodic-orbits-with-Parallel-Standard-Shooting","page":"🟡 Neural mass equation (Hopf aBS)","title":"Periodic orbits with Parallel Standard Shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We use a different method to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl. This way of computing periodic orbits should be more precise than the Trapezoid method. We use a particular instance called multiple shooting which is computed in parallel. This is an additional advantage compared to the two previous methods.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"using DifferentialEquations\n\n# this is the ODEProblem used with `DiffEqBase.solve`\nprobsh = ODEProblem(TMvf!, copy(z0), (0., 1.), par_tm; abstol = 1e-12, reltol = 1e-10)\n\nopts_po_cont = ContinuationPar(opts_br, dsmax = 0.1, ds= -0.0001, dsmin = 1e-4, max_steps = 100, tol_stability = 1e-4)\n\nbr_posh = @time continuation(\n\tbr, 4, opts_po_cont,\n\t# this is where we tell that we want Standard Shooting\n\t# with 15 time sections\n\tShootingProblem(15, probsh, Rodas5(), parallel = true);\n\t# this to help branching: \n\t# specify guess for parameter value\n\tδp = 0.0005,\n\t# regular continuation parameters\n\tverbosity = 2, plot = true,\n\targs_po...,\n\t# we reject the step when the residual is high\n\tcallback_newton = BK.cbMaxNorm(10)\n\t)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/#References","page":"🟡 Neural mass equation (Hopf aBS)","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"[Cortes]: Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.","category":"page"},{"location":"periodicOrbitCollocation/#Periodic-orbits-based-on-orthogonal-collocation","page":"Collocation","title":"Periodic orbits based on orthogonal collocation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We compute Ntst time slices of a periodic orbit using orthogonal collocation. This is implemented in the structure PeriodicOrbitOCollProblem.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"tip: Large scale\nThe current implementation is optimized for ODE and for large scale problems for which the jacobian is sparse. ","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The general method is very well exposed in [Dankowicz],[Doedel] and we adopt the notations of [Dankowicz]. However our implementation is based on [Doedel] because it is more economical (less equations) when it enforces the continuity of the solution.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We look for periodic orbits as solutions (x(0) T) of","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"dot x = Tcdot F(x) x(0)=x(1)inmathbb R^n","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We focus on the differential equality and consider a partition of the time domain","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"0=tau_1cdotstau_jcdotstau_N_tst+1=1","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"where the points are referred to as mesh points. On each mesh interval tau_jtau_j+1 for j=1cdotsN_tst, we define the affine transformation","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"tau=tau^(j)(sigma)=tau_j+frac(1+sigma)2left(tau_j+1-tau_jright) sigma in-11","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The functions x^(j) defined on -11 by x^(j)(sigma) equiv x(tau_j(sigma)) satisfies the following equation on -11:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"dot x^(j) = Tfractau_j+1-tau_j2cdot F(x^(j))tagE_j","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"with the continuity equation x^(j+1)(-1) = x^(j)(1).","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We now aim at solving (E_j) by using an approximation with a polynomial of degree m. Following [Dankowicz], we define a (uniform) partition:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"-1=sigma_1cdotssigma_icdotssigma_m+1=1","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The points tau_ij = tau^(i)(sigma_j) are called the base points: they serve as collocation points.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The associated m+1 Lagrange polynomials of degree m are:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"mathcalL_i(sigma)=prod_k=1 k neq i^m+1 fracsigma-sigma_ksigma_i-sigma_k i=1 ldots m+1","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We then introduce the approximation p_j of x^(j):","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"mathcal p_j(sigma)equiv sumlimits_k=1^m+1mathcal L_k(sigma)x_jk","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"and the problem to be solved at the nodes z_l, l=1cdotsm:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"forall 1leq lleq mquad 1leq jleq N_tstquad dot p_j(z_l) = Tfractau_j+1-tau_j2cdot F(p_j(z_l))tagE_j^2","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The nodes (z_l) are associated with a Gauss–Legendre quadrature.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"In order to have a unique solution, we need to remove the phase freedom. This is done by imposing a phase condition.","category":"page"},{"location":"periodicOrbitCollocation/#Number-of-unknowns","page":"Collocation","title":"Number of unknowns","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"Putting the period unknown aside, we have to find the x_jk which gives ntimes N_tsttimes (m+1) unknowns. ","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The equations E_j^2 provides ntimes N_tsttimes m plus the (N_tst-1)times n equations for the continuity equations. This makes a total of (N_tst-1)times mtimes n+ntimes N_tsttimes m = nN_tst(m+1)-1 equations to which we add the n equations for the periodic boundary condition. In total, we have","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"ntimes N_tsttimes (m+1)","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"equations which matches the number of unknowns.","category":"page"},{"location":"periodicOrbitCollocation/#Phase-condition","page":"Collocation","title":"Phase condition","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"To ensure uniqueness of the solution to the functional, we add the following phase condition","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"frac1T int_0^Tleftlangle x(s) dot x_0(s)rightrangle d s =0","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"During continuation at step k, we use frac1T int_0^Tleftlangle x(s) dot x_k-1(s)rightrangle d s","category":"page"},{"location":"periodicOrbitCollocation/#Interpolation","page":"Collocation","title":"Interpolation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"BifurcationKit.POSolution","category":"page"},{"location":"periodicOrbitCollocation/#BifurcationKit.POSolution","page":"Collocation","title":"BifurcationKit.POSolution","text":"Structure to encode the solution associated to a functional like ::PeriodicOrbitOCollProblem or ::ShootingProblem. In the particular case of ::PeriodicOrbitOCollProblem, this allows to use the collocation polynomials to interpolate the solution. Hence, if sol::POSolution, one can call\n\nsol = BifurcationKit.POSolution(prob_coll, x)\nsol(t)\n\non any time t.\n\n\n\n\n\n","category":"type"},{"location":"periodicOrbitCollocation/#Mesh-adaptation","page":"Collocation","title":"Mesh adaptation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The goal of this method[Russell] is to adapt the mesh tau_i in order to minimize the error. It is particularly helpful near homoclinic solutions where the period diverge. It can also be useful in order to use a smaller N_tst.","category":"page"},{"location":"periodicOrbitCollocation/#Encoding-of-the-functional","page":"Collocation","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The functional is encoded in the composite type PeriodicOrbitOCollProblem. See the link for more information, in particular on how to access the underlying functional, its jacobian...","category":"page"},{"location":"periodicOrbitCollocation/#Jacobian-and-linear-solvers","page":"Collocation","title":"Jacobian and linear solvers","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We provide many different linear solvers to take advantage of the formulations or the dimensionality. These solvers are available through the argument jacobian in the constructor of PeriodicOrbitOCollProblem. For example, you can pass jacobian = FullSparse(). Note that all the internal solvers and jacobian are set up automatically, you don't need to do anything. However, for the sake of explanation, we detail how this works.\t","category":"page"},{"location":"periodicOrbitCollocation/#.-AutoDiffDenseAnalytical()","page":"Collocation","title":"1. AutoDiffDenseAnalytical()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed with an analytical formula, works for dense matrices. This is the default algorithm.","category":"page"},{"location":"periodicOrbitCollocation/#.-AutoDiffDense()","page":"Collocation","title":"2. AutoDiffDense()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed with automatic differentiation, works for dense matrices. Can be used for debugging.","category":"page"},{"location":"periodicOrbitCollocation/#.-FullSparse()","page":"Collocation","title":"3. FullSparse()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed with an analytical formula, works for sparse matrices.","category":"page"},{"location":"periodicOrbitCollocation/#.-FullSparseInplace()","page":"Collocation","title":"3. FullSparseInplace()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed in place, limiting memory allocations, with an analytical formula when the sparsity of the jacobian of the vector field is constant. This is much faster than FulSparse().","category":"page"},{"location":"periodicOrbitCollocation/#Floquet-multipliers-computation","page":"Collocation","title":"Floquet multipliers computation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We provide three methods to compute the Floquet coefficients.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The algorithm (Default) FloquetColl is based on the condensation of parameters described in [Doedel]. It is the fastest method.\nThe algorithm FloquetCollGEV is a simplified version of the procedure described in [Fairgrieve]. It boils down to solving a large generalized eigenvalue problem. There is clearly room for improvements here but this can be used to check the results of the previous method.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"These methods allow to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. However they may be imprecise[Lust].","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbitCollocation/#Computation-with-newton","page":"Collocation","title":"Computation with newton","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"newton(prob::PeriodicOrbitOCollProblem, orbitguess, options::NewtonPar; kwargs...)","category":"page"},{"location":"periodicOrbitCollocation/#BifurcationKit.newton-Tuple{PeriodicOrbitOCollProblem, Any, NewtonPar}","page":"Collocation","title":"BifurcationKit.newton","text":"newton(probPO, orbitguess, options; kwargs...)\n\n\nThis is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is a PeriodicOrbitOCollProblem.\n\nprob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit.\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG\nFor AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.\nFor AutoDiffDenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We provide a simplified call to newton to locate the periodic orbits. newton will look for prob.jacobian in order to select the requested way to compute the jacobian.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The docs for this specific newton are located at newton.","category":"page"},{"location":"periodicOrbitCollocation/#Continuation","page":"Collocation","title":"Continuation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We refer to continuation for more information regarding the arguments. continuation will look for prob.jacobian in order to select the requested way to compute the jacobian.","category":"page"},{"location":"periodicOrbitCollocation/#References","page":"Collocation","title":"References","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Dankowicz]: Dankowicz, Harry, and Frank Schilder. Recipes for Continuation. Computational Science and Engineering Series. Philadelphia: Society for Industrial and Applied Mathematics, 2013.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Doedel]: Doedel, Eusebius, Herbert B. Keller, and Jean Pierre Kernevez. “NUMERICAL ANALYSIS AND CONTROL OF BIFURCATION PROBLEMS (II): BIFURCATION IN INFINITE DIMENSIONS.” International Journal of Bifurcation and Chaos 01, no. 04 (December 1991): 745–72.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Fairgrieve]: Fairgrieve, Thomas F., and Allan D. Jepson. “O. K. Floquet Multipliers.” SIAM Journal on Numerical Analysis 28, no. 5 (October 1991): 1446–62. https://doi.org/10.1137/0728075.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Russell]: Russell, R. D., and J. Christiansen. “Adaptive Mesh Selection Strategies for Solving Boundary Value Problems.” SIAM Journal on Numerical Analysis 15, no. 1 (February 1978): 59–80. https://doi.org/10.1137/0715004.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Lust]: Lust, Kurt. “Improved Numerical Floquet Multipliers.” International Journal of Bifurcation and Chaos 11, no. 09 (September 2001): 2389–2410. https://doi.org/10.1142/S0218127401003486.","category":"page"},{"location":"codim3Continuation/#Bogdanov-Takens-refinement","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"In this page, we explain how to perform precise localisation of Bogdanov-Takens (BT) points. This is an unusual feature of numerical continuation libraries. We chose to implement it because the localisation of the BT points on the Hopf bifurcation curves is rather imprecise.","category":"page"},{"location":"codim3Continuation/#Method","page":"Bogdanov-Takens refinement (3 params)","title":"Method","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"The continuation of BT bifurcation points is based on a Minimally Augmented[Govaerts],[Blank],[Bindel] formulation which is an efficient way to detect singularities. The continuation of BT points is based on the formulation","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"G(up) = (F(up) g_1(up) g_2(up))inmathbb R^n+2quadquad (F_bt)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"where the test functions g_1g_2 are solutions of","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"leftbeginarraycc\ndF(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nv_1 \ng_1(up)\nendarrayright=leftbeginarrayc0_n 1endarrayrightquadquad (M_bt)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"and","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"leftbeginarraycc\ndF(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nv_2 \ng_2(up)\nendarrayright=leftbeginarraycv_1 0endarrayrightquadquad (M_bt)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"and where wv are chosen in order to have a non-singular matrix (M_bt). More precisely, v (resp. w) should be close to a null vector of dF(u,p) (resp. dF(u,p)').","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"note that there are very simplified calls for this, see Newton refinement below. In particular, you don't need to set up the Minimally Augmented problem yourself. This is done in the background.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"warning: Linear Method\nYou can pass the bordered linear solver to solve (M_bt) using the option bdlinsolver (see below). Note that the choice bdlinsolver = BorderingBLS() can lead to singular systems. Indeed, in this case, (M_bt) is solved by inverting dF(u,p) which is singular at Fold points.","category":"page"},{"location":"codim3Continuation/#Setting-the-jacobian","page":"Bogdanov-Takens refinement (3 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"In order to apply the newton algorithm to F_bt, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to F_bt and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian F_bt and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"codim3Continuation/#Example","page":"Bogdanov-Takens refinement (3 params)","title":"Example","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"using BifurcationKit, LinearAlgebra, Setfield, SparseArrays, ForwardDiff, Parameters\nFbt(x, p) = [x[2], p.β1 + p.β2 * x[2] + p.a * x[1]^2 + p.b * x[1] * x[2]]\npar = (β1 = 0.01, β2 = -0.3, a = -1., b = 1.)\nprob = BifurcationProblem(Fbt, [0.01, 0.01], par, (@lens _.β1))\nopts_br = ContinuationPar(p_max = 0.5, p_min = -0.5, detect_bifurcation = 3, nev = 2)\n\nbr = continuation(prob, PALC(), opts_br; bothside = true)\n\n# compute branch of Hopf points\nhopf_codim2 = continuation(br, 3, (@lens _.β2), ContinuationPar(opts_br, detect_bifurcation = 1, max_steps = 40, max_bisection_steps = 25) ;\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tbothside = true,\n\t)\n\n# refine BT point\nsolbt = BifurcationKit.newton_bt(hopf_codim2, 2; start_with_eigen = true)\nsolbt.u","category":"page"},{"location":"codim3Continuation/#Newton-refinement","page":"Bogdanov-Takens refinement (3 params)","title":"Newton refinement","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"Once a Bogdanov-Takens point has been detected after a call to br = continuation(...), it can be refined using newton iterations. Let us say that ind_bif is the index in br.specialpoint of a Bogdanov-Takens point. This guess can be refined as follows:","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"outfold = newton(br::AbstractBranchResult, ind_bif::Int; \n\tnormN = norm,\n\toptions = br.contparams.newton_options,\n\tbdlinsolver = BorderingBLS(options.linsolver),\n\tjacobian_ma = :autodiff,\n\tstart_with_eigen = false, kwargs...)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"For the options parameters, we refer to Newton.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"It is important to note that for improved performances, a function implementing the expression of the hessian should be provided. This is by far the fastest. BifurcationProblem provides it by default using AD though.","category":"page"},{"location":"codim3Continuation/#Advanced-use","page":"Bogdanov-Takens refinement (3 params)","title":"Advanced use","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"Here, we expose the solvers that are used to perform newton refinement. This is useful in case it is too involved to expose the linear solver options.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"BifurcationKit.newton_bt","category":"page"},{"location":"codim3Continuation/#BifurcationKit.newton_bt","page":"Bogdanov-Takens refinement (3 params)","title":"BifurcationKit.newton_bt","text":"newton_bt(\n prob,\n btpointguess,\n par,\n lens2,\n eigenvec,\n eigenvec_ad,\n options;\n normN,\n jacobian_ma,\n usehessian,\n bdlinsolver,\n kwargs...\n)\n\n\nThis function turns an initial guess for a BT point into a solution to the BT problem based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationFunction\nbtpointguess initial guess (x0, p0) for the BT point. It should be a BorderedArray as returned by the function BTPoint\npar parameters used for the vector field\neigenvec guess for the 0 eigenvector\neigenvec_ad guess for the 0 adjoint eigenvector\noptions::NewtonPar options for the Newton-Krylov algorithm, see NewtonPar.\n\nOptional arguments:\n\nnormN = norm\nbdlinsolver bordered linear solver for the constraint equation\njacobian_ma::Symbol = true specify the way the (newton) linear system is solved. Can be (:autodiff, :finitedifferences, :minaug)\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\nSimplified call\n\nSimplified call to refine an initial guess for a BT point. More precisely, the call is as follows\n\nnewton(br::AbstractBranchResult, ind_bt::Int; options = br.contparams.newton_options, kwargs...)\n\nThe parameters / options are as usual except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of bifurcation point in br you want to refine. You can pass newton parameters different from the ones stored in br by using the argument options.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian will be computed twice!\n\ntip: ODE problems\nFor ODE problems, it is more efficient to pass the option jacobian_ma = :autodiff\n\n\n\n\n\nnewton_bt(\n br,\n ind_bt;\n probvf,\n normN,\n options,\n nev,\n start_with_eigen,\n bdlinsolver,\n kwargs...\n)\n\n\nThis function turns an initial guess for a Bogdanov-Takens point into a solution to the Bogdanov-Takens problem based on a Minimally Augmented formulation.\n\nArguments\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\n\nOptional arguments:\n\noptions::NewtonPar, default value br.contparams.newton_options\nnormN = norm\noptions You can pass newton parameters different from the ones stored in br by using this argument options.\njacobian_ma::Symbol = true specify the way the (newton) linear system is solved. Can be (:autodiff, :finitedifferences, :minaug)\nbdlinsolver bordered linear solver for the constraint equation\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements.\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\ntip: ODE problems\nFor ODE problems, it is more efficient to pass the option jacobian = :autodiff\n\ntip: start_with_eigen\nFor ODE problems, it is more efficient to pass the option start_with_eigen = true\n\n\n\n\n\n","category":"function"},{"location":"codim3Continuation/#References","page":"Bogdanov-Takens refinement (3 params)","title":"References","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Blank]: Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Bindel]: Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.","category":"page"},{"location":"tutorials/ode/NME-MTK/#Neural-mass-equation-MTK","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"Pages = [\"NME-MTK.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"In this tutorial, we study the following model taken from [Cortes]. It is essentially the same tutorial as in Neural mass equation but treated with ModelingToolkit.jl.","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"leftbeginarrayl\ntau dotE=-E+gleft(J u x E+E_0right) \ndotx=tau_D^-1(1-x)-u E x \ndotu=U E(1-u)-tau_F^-1(u-U)\nendarrayright","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"The model is interesting because the branch of periodic solutions converges to an homoclinic orbit which is challenging to compute with our methods.","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"using Revise, ModelingToolkit, LinearAlgebra\nusing DifferentialEquations, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nindexof(sym, syms) = findfirst(isequal(sym),syms)\n\n@variables t E(t) x(t) u(t) SS0(t) SS1(t) \t# independent and dependent variables\n@parameters U0 τ J E0 τD U0 τF τS α \t\t# parameters\nD = Differential(t) \t\t\t\t# define an operator for the differentiation w.r.t. time\n\n# define the model\n@named NMmodel = ODESystem([SS0 ~ J * u * x * E + E0,\n\tSS1 ~ α * log(1 + exp(SS0 / α)),\n\tD(E) ~ (-E + SS1) / τ,\n\tD(x) ~ (1.0 - x) / τD - u * x * E,\n\tD(u) ~ (U0 - u) / τF + U0 * (1 - u) * E],\n\tdefaults = Dict(E => 0.238616, x => 0.982747, u => 0.367876,\n\tα => 1.5, τ => 0.013, J => 3.07, E0 => -2.0, τD => 0.200, U0 => 0.3, τF => 1.5, τS => 0.007))\n\n# get the vector field and jacobian\nodeprob = ODEProblem(structural_simplify(NMmodel), [], (0.,10.), [], jac = true)\nodefun = odeprob.f\nF = (u,p) -> odefun(u,p,0)\nJ = (u,p) -> odefun.jac(u,p,0)\n\nid_E0 = indexof(E0, parameters(NMmodel))\npar_tm = odeprob.p\n\n# we collect the differentials together in a problem\nprob = BifurcationProblem(F, odeprob.u0, par_tm, (@lens _[id_E0]); J = J,\n record_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]))\nnothing #hide","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We first compute the branch of equilibria","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"# continuation options\nopts_br = ContinuationPar(p_min = -10.0, p_max = -0.9,\n\t# parameters to have a smooth result\n\tds = 0.04, dsmax = 0.05,\n\t# this is to detect bifurcation points precisely with bisection\n\tdetect_bifurcation = 3,\n\t# Optional: bisection options for locating bifurcations\n\tn_inversion = 8, max_bisection_steps = 25, nev = 3)\n\n# continuation of equilibria\nbr = continuation(prob, PALC(tangent = Bordered()), opts_br; normC = norminf)\n\nscene = plot(br, plotfold=false, markersize=3, legend=:topleft)","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"br","category":"page"},{"location":"tutorials/ode/NME-MTK/#Branch-of-periodic-orbits-with-Collocation-method","page":"🟢 Neural mass equation - MTK","title":"Branch of periodic orbits with Collocation method","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We then compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use finite differences to discretize the problem of finding periodic orbits. Obviously, this will be problematic when the period of the limit cycle grows unbounded close to the homoclinic orbit.","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"# newton parameters\noptn_po = NewtonPar(tol = 1e-8, max_iterations = 10)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.15, ds= -0.0001, dsmin = 1e-4, p_max = 0., p_min=-5.,\n\tmax_steps = 150, newton_options = optn_po,\n\tnev = 3, plot_every_step = 10, detect_bifurcation = 0)\n\n# arguments for periodic orbits\n# this is mainly for printing purposes\nargs_po = (\trecord_from_solution = (x, p) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\t\tmin = minimum(xtt[1,:]),\n\t\t\t\tperiod = getperiod(p.prob, x, p.p))\n\tend,\n\tplot_solution = (x, p; k...) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\tplot!(xtt.t, xtt[1,:]; label = \"E\", k...)\n\t\tplot!(xtt.t, xtt[2,:]; label = \"x\", k...)\n\t\tplot!(xtt.t, xtt[3,:]; label = \"u\", k...)\n\t\tplot!(br; subplot = 1, putspecialptlegend = false)\n\t\tend,\n\tnormC = norminf)\n\n\nMt = 30 # number of time sections\n\tbr_pocoll = @time continuation(\n\t# we want to branch form the 4th bif. point\n\tbr, 4, opts_po_cont,\n\t# we want to use the Collocation method to locate PO, with polynomial degree 5\n\tPeriodicOrbitOCollProblem(Mt, 5; meshadapt = true);\n\t# regular continuation options\n\targs_po..., callback_newton = BK.cbMaxNorm(10))\n\nscene = plot(br, br_pocoll, markersize = 3)\nplot!(scene, br_pocoll.param, br_pocoll.min, label = \"\")","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We plot the maximum (resp. minimum) of the limit cycle. We can see that the min converges to the smallest equilibrium indicating a homoclinic orbit.","category":"page"},{"location":"tutorials/ode/NME-MTK/#Plot-of-some-of-the-periodic-orbits-as-function-of-E_0","page":"🟢 Neural mass equation - MTK","title":"Plot of some of the periodic orbits as function of E_0","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We can plot some of the previously computed periodic orbits in the plane (Ex) as function of E_0:","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"plot()\n# fetch the saved solutions\nfor sol in br_pocoll.sol[1:2:40]\n\t# periodic orbit\n\tpo = sol.x\n\t# get the mesh and trajectory\n\ttraj = BK.get_periodic_orbit(br_pocoll.prob, po, @set par_tm[id_E0] = sol.p)\n\tplot!(traj[1,:], traj[2,:], xlabel = \"E\", ylabel = \"x\", label = \"\")\nend\ntitle!(\"\")","category":"page"},{"location":"tutorials/ode/NME-MTK/#References","page":"🟢 Neural mass equation - MTK","title":"References","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"[Cortes]: Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.","category":"page"},{"location":"tutorials/ode/tutorials1/#Temperature-model","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"","category":"section"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"This is a classical example from the Trilinos library.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"This is a simple example in which we aim at solving Delta T+alpha N(Tbeta)=0 with boundary conditions T(0) = T(1)=beta. This example is coded in examples/chan.jl. We start with some imports:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"using BifurcationKit, LinearAlgebra, Plots, Parameters\nconst BK = BifurcationKit\n\nN(x; a = 0.5, b = 0.01) = 1 + (x + a*x^2)/(1 + b*x^2)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We then write our functional:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"function F_chan(x, p)\n\t@unpack α, β = p\n\tf = similar(x)\n\tn = length(x)\n\tf[1] = x[1] - β\n\tf[n] = x[n] - β\n\tfor i=2:n-1\n\t\tf[i] = (x[i-1] - 2 * x[i] + x[i+1]) * (n-1)^2 + α * N(x[i], b = β)\n\tend\n\treturn f\nend\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We want to call a Newton solver. We first need an initial guess:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"n = 101\nsol0 = [(i-1)*(n-i)/n^2+0.1 for i=1:n]\n\n# set of parameters\npar = (α = 3.3, β = 0.01)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"Finally, we need to provide some parameters for the Newton iterations. This is done by calling","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"optnewton = NewtonPar(tol = 1e-9, max_iterations = 10)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We call the Newton solver:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"prob = BifurcationProblem(F_chan, sol0, par, (@lens _.α),\n\t# function to plot the solution\n\tplot_solution = (x, p; k...) -> plot!(x; ylabel=\"solution\", label=\"\", k...))\nsol = newton(prob, optnewton) # hide\n# we set verbose to true to see the newton iterations\nsol = @time newton( prob, @set optnewton.verbose = true)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We can perform numerical continuation w.r.t. the parameter alpha. This time, we need to provide additional parameters, but now for the continuation method:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"optcont = ContinuationPar(max_steps = 150,\n\tp_min = 0., p_max = 4.2,\n\tnewton_options =optnewton)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"Next, we call the continuation routine as follows.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"br = continuation(prob, PALC(), optcont; plot = true)\nnothing #hide\t\t","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"The parameter axis lens = @lens _.α is used to extract the component of par corresponding to α. Internally, it is used as get(par, lens) which returns 3.3.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"You should see","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"scene = title!(\"\") #hide\t\t","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"The left figure is the norm of the solution as function of the parameter p=alpha, the y-axis can be changed by passing a different recordFromSolution to BifurcationProblem. The top right figure is the value of alpha as function of the iteration number. The bottom right is the solution for the current value of the parameter. This last plot can be modified by changing the argument plotSolution to BifurcationProblem.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"note: Bif. point detection\nTwo Fold points were detected. This can be seen by looking at br.specialpoint, by the black\tdots on the continuation plots when doing plot(br, plotfold=true) or by typing br in the REPL. Note that the bifurcation points are located in br.specialpoint.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"What if we want to compute to continue both ways in one call?","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"br = continuation(prob, PALC(), optcont; bothside = true)\nplot(br)","category":"page"},{"location":"guidelines/#Guidelines","page":"Guidelines","title":"Guidelines","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The goal of this package is to find solutions x to nonlinear equations ","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"F(xp) = 0 quadtagE","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"in large dimensions as function of a real parameter p. We want to be able to do so on GPU, distributed systems...","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The core of the package is built around a Newton-Krylov solver (see newton) which allows to solve equations of the form F(x)=0, or find a solution x_0 to (E) for a particular p_0.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"Once such a solution (or several) (x_0p_0) is known, we can continue it by computing a 1d curve of solutions gamma = (x(s)p(s))_sin I passing through (x_0p_0) (see continuation and Deflated Continuation).","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"In practice, you don't need to know exactly (x_0p_0) to compute gamma. Indeed, continuation will call newton to refine any initial guess that you pass.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Textbook\nOnly the basics of bifurcation theory is underlined here. We refer to [Kuznetsov],[haragus] for a more thorough description.","category":"page"},{"location":"guidelines/#Bifurcation-analysis-of-Equilibria","page":"Guidelines","title":"Bifurcation analysis of Equilibria","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We can detect if the curve of solutions gamma crosses another curve of solutions gamma^bif without knowing gamma^bif! The intersection point (x^bp^b)ingamma is called a bifurcation point and is such that partial_xF(x^bp^b) is non invertible. When calling γ = continuation(...) with the option detect_bifurcation > 1 inside ContinuationPar, the bifurcation points are automatically detected and stored in γ.specialpoints.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"warning: Eigenvalues\nThe rightmost eigenvalues are computed by default to detect bifurcations. Hence, the number of eigenvalues with positive real parts must be finite (e.g. small). This might require to consider -F(xp)=0 instead of (E).","category":"page"},{"location":"guidelines/#Branch-switching","page":"Guidelines","title":"Branch switching","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"In the simple case where dimker partial_xF(x^bp^b) = 1, we can compute automatically the bifurcated branch gamma^bif by calling continuation and passing gamma. This is explained in Branch switching from simple branch point to equilibria. Recursively, we can compute the curves of solutions which are connected to (x_0p_0), this is called a bifurcation diagram. This bifurcation diagram can be automatically computed using the function bifurcationdiagram with minimum input from the user. More information is provided in Automatic Bifurcation diagram computation and examples of use are 1d Swift-Hohenberg equation and Bratu–Gelfand problem.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"When dequiv dimker partial_xF(x^bp^b) 1, you can still compute automatically the bifurcated branches gamma^bifs by calling continuation. It is based on a reduction of (E) to a small system of d dimensional multivariate polynomial equations in d unknowns whose solutions give the local topology of branches in the neighborhood of the bifurcation point (x^b p^b). The solutions of this reduced equation are then used as initial guesses for the call to Krylov-Newton. This is explained in From simple branch point to equilibria and examples of use are shown in 2d Bratu–Gelfand problem and Automatic 2d Bratu–Gelfand problem (Intermediate).\t","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"In the case d=1, the reduced equation can be further simplified into a normal form. This is also automatically computed by the package.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Branch switching\nMany more branch switching procedures are available. They are all listed in Branch switching","category":"page"},{"location":"guidelines/#Bifurcation-analysis-of-Cauchy-problems","page":"Guidelines","title":"Bifurcation analysis of Cauchy problems","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The goal of this section is to study the dynamics of the Cauchy problem","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"fracddtx - F(xp) = 0 quadtagC","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The equilibria are time independent solutions of (C) hence satisfying (E). The previous section can be applied to compute curves of equilibria. However, we can do more. By discretizing time, we can recast (C) in the general form (E) and look for time dependent solutions as well. ","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We can detect the existence of periodic solutions close to gamma. This is done automatically and those bifurcation points are stored in γ.specialpoint as well with the name of Hopf bifurcation points. ","category":"page"},{"location":"guidelines/#Branch-switching-at-Hopf-points","page":"Guidelines","title":"Branch switching at Hopf points","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We focus on computing the branch of periodic solutions branching from a Hopf point. This is done automatically by calling continuation, passing gamma and choosing a time discretization algorithm (see Periodic orbits computation). Some details about this branch switching are given in From Hopf point to periodic orbits.","category":"page"},{"location":"guidelines/#Branch-switching-at-bifurcation-points-of-periodic-orbits","page":"Guidelines","title":"Branch switching at bifurcation points of periodic orbits","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"Let us consider the case where a branch of periodic orbits gamma^po have been computed (see for example previous section) and several bifurcation points have been detected (branch point, period doubling and Neimark Sacker). Can we compute bifurcated branches from gamma^po? Automatically?","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We do not provide an automatic branch switching for those points and for all methods (Shooting, Finite differences). However, for branch points of periodic orbits, you can call continuation by passing gamma^po and some simple arguments (amplitude of the periodic orbits) to perform branch switching in a semi-automatic way. For the case of Periodic orbits based on Trapezoidal rule, see From Branch / Period-doubling point of curve of periodic orbits.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Branch switching\nMany more branch switching procedures are available. They are all listed in Branch switching","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Manual Branch switching\nYou can perform manual branch switching by computing the nearby solutions close to a bifurcation point using a deflated newton (see Deflated problems), which provides a way to compute solutions other than a set of already known solutions. You can then use these solutions to compute branches by calling continuation. Many, if not all tutorials give example of doing so like 2d Bratu–Gelfand problem or 1d Brusselator.","category":"page"},{"location":"guidelines/#References","page":"Guidelines","title":"References","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"[Kuznetsov]: Kuznetsov, Yuri A. Elements of Applied Bifurcation Theory. Vol. 112. Applied Mathematical Sciences. Cham: Springer International Publishing, 2023. https://doi.org/10.1007/978-3-031-22007-4.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"[haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"tutorials/mittelmann/#gelfand","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Pages = [\"mittelmann.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"unknown: References\nThe following example is exposed in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. The Computation of Disconnected Bifurcation Diagrams. ArXiv:1603.00809 [Math], March 2, 2016. It is also treated in Michiel Wouters. Automatic Exploration Techniques for the Numerical Continuation of Large–Scale Nonlinear Systems, 2019.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We consider the problem of Mittelmann:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Delta u + NL(lambdau) = 0","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"with Neumann boundary condition on Omega = (01)^2 and where NL(lambdau)equiv-10(u-lambda e^u). This is a good example to show how automatic branch switching works and also nonlinear deflation.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We start with some imports:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\n\n# define the sup norm and a L2 norm\nnormbratu(x) = norm(x .* w) / sqrt(length(x)) # the weight w is defined below\n\n# some plotting functions to simplify our life\nplotsol!(x, nx = Nx, ny = Ny; kwargs...) = heatmap!(reshape(x, nx, ny); color = :viridis, kwargs...)\nplotsol(x, nx = Nx, ny = Ny; kwargs...) = (plot();plotsol!(x, nx, ny; kwargs...))\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"and with the discretization of the problem","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"function Laplacian2D(Nx, Ny, lx, ly, bc = :Neumann)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Neumann0BC(hx)\n\tQy = Neumann0BC(hy)\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A\nend\n\nϕ(u, λ) = -10(u-λ*exp(u))\ndϕ(u, λ) = -10(1-λ*exp(u))\n\nfunction NL!(dest, u, p)\n\t@unpack λ = p\n\tdest .= ϕ.(u, λ)\n\treturn dest\nend\n\nNL(u, p) = NL!(similar(u), u, p)\n\nfunction Fmit!(f, u, p)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\n\treturn f\nend\n\nFmit(u, p) = Fmit!(similar(u), u, p)\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"It will also prove useful to have the derivatives of our functional:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"function JFmit(x,p)\n\tJ = p.Δ\n\tdg = dϕ.(x, p.λ)\n\treturn J + spdiagm(0 => dg)\nend\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We need to define the parameters associated to this problem:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Nx = 30; Ny = 30\nlx = 0.5; ly = 0.5\n# weight for the weighted norm\nconst w = (lx .+ LinRange(-lx,lx,Nx)) * (LinRange(-ly,ly,Ny))' |> vec\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)\npar_mit = (λ = .05, Δ = Δ)\n\n# initial guess f for newton\nsol0 = zeros(Nx, Ny) |> vec\n\n# Bifurcation Problem\nprob = BifurcationProblem(Fmit, sol0, par_mit, (@lens _.λ),; J = JFmit,\n record_from_solution = (x, p) -> (x = normbratu(x), n2 = norm(x), n∞ = norminf(x)),\n plot_solution = (x, p; k...) -> plotsol!(x ; k...))\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"To compute the eigenvalues, we opt for the shift-invert strategy with shift =0.5","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"# eigensolver\neigls = EigKrylovKit(dim = 70)\n\n# options for Newton solver, we pass the eigensolverr\nopt_newton = BK.NewtonPar(tol = 1e-8, verbose = false, eigsolver = eigls, max_iterations = 20)\n\n# options for continuation\nopts_br = ContinuationPar(p_max = 3.5, p_min = 0.025,\n\t# for a good looking curve\n\tdsmin = 0.001, dsmax = 0.05, ds = 0.01,\n\t# number of eigenvalues to compute\n\tnev = 30,\n\tplot_every_step = 10, newton_options = (@set opt_newton.verbose = false),\n\tmax_steps = 100, tol_stability = 1e-6,\n\t# detect codim 1 bifurcations\n\tdetect_bifurcation = 3,\n\t# Optional: bisection options for locating bifurcations\n\tn_inversion = 4, dsmin_bisection = 1e-7, max_bisection_steps = 25)\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Note that we put the option detect_bifurcation = 3 to detect bifurcations precisely with a bisection method. Indeed, we need to locate these branch points precisely to be able to call automatic branch switching.","category":"page"},{"location":"tutorials/mittelmann/#Branch-of-homogeneous-solutions","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Branch of homogeneous solutions","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"At this stage, we note that the problem has a curve of homogeneous (constant in space) solutions u_h solving N(lambda u_h)=0. We shall compute this branch now.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Given that we will use these arguments for continuation many times, it is wise to collect them:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"# optional arguments for continuation\nkwargsC = (verbosity = 0, plot = true, normC = norminf)\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We call continuation with the initial guess sol0 which is homogeneous, thereby generating homogeneous solutions:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"br = continuation(prob, PALC(), opts_br; kwargsC...)\nshow(br)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You should see the following result:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"title!(\"\")","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We note several simple bifurcation points for which the dimension of the kernel of the jacobian is one dimensional. In the above box, δ = ( 1, 0) gives the change in the stability. In this case, there is one vector in the kernel which is real. The bifurcation point 2 has a 2d kernel and is thus not amenable to automatic branch switching.","category":"page"},{"location":"tutorials/mittelmann/#Automatic-branch-switching-at-simple-branch-points","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Automatic branch switching at simple branch points","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can compute the branch off the third bifurcation point:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"br1 = continuation(br, 3, setproperties(opts_br;ds = 0.001, max_steps = 40); kwargsC...)\ntitle!(\"\")","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You can also plot the two branches together plot(br, br1, plotfold=false) and get","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"scene = plot(br,br1,plotfold=false)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We continue our journey and compute the branch bifurcating of the first bifurcation point from the last branch we computed:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"br2 = continuation(br1, 1, setproperties(opts_br;ds = 0.001, max_steps = 40); kwargsC...)\nscene = plot(br,br1,br2)","category":"page"},{"location":"tutorials/mittelmann/#Automatic-branch-switching-at-the-2d-branch-points","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Automatic branch switching at the 2d-branch points","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We now show how to perform automatic branch switching at the nonsimple branch points. However, we think it is important that the user is able to use the previous tools in case automatic branch switching fails. This is explained in the next sections.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"The call for automatic branch switching is the same as in the case of simple branch points (see above) except that many branches are returned.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"branches = continuation(br, 2,\n\tsetproperties(opts_br; detect_bifurcation = 3, ds = 0.001, p_min = 0.01, max_steps = 32 ) ;\n alg = PALC(tangent = Bordered()),\n\tkwargsC...,\n\tnev = 30,\n\t)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You can plot the branches using","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"scene = plot(br, branches...)","category":"page"},{"location":"tutorials/mittelmann/#Analysis-at-the-2d-branch-points-(manual)","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Analysis at the 2d-branch points (manual)","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"The second bifurcation point on the branch br of homogeneous solutions has a 2d kernel. we provide two methods to deal with such case","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"automatic local bifurcation diagram (see below)\nbranch switching with deflation (see next section)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We provide a generic way to study branch points of arbitrary dimensions by computing a reduced equation. The general method is based on a Lyapunov-Schmidt reduction. We can compute the information about the branch point using the generic function (valid for simple branch points, Hopf bifurcation points,...)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"bp2d = get_normal_form(br, 2; verbose=true, nev = 50)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Note that this is a multivariate polynomials. For more information, see Non-simple branch point.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You can evaluate this polynomial as follows bp2d(Val(:reducedForm),[0.1,0.2], 0.01) which returns a 2d vector or bp2d([0.1,0.2], 0.01). This last expression actually returns a vector corresponding to the PDE problem.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You need to solve these equations to compute the bifurcation diagram in the neighborhood of the bifurcation point. In the present case, we do it using brute force. We suggest to use IntervalConstraintProgramming.jl for a more precise way.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"using ProgressMeter\nNd = 200; L = 0.9\n# sampling grid\nX = LinRange(-L,L, Nd); Y = LinRange(-L,L, Nd); P = LinRange(-0.0001,0.0001, Nd+1)\n\n# sample reduced equation on the grid for the first component\nV1a = @showprogress [bp2d(Val(:reducedForm),[x1,y1], p1)[1] for p1 in P, x1 in X, y1 in Y]\nInd1 = findall( abs.(V1a) .<= 9e-4 * maximum(abs.(V1a)))\n# intersect with second component\nV2a = @showprogress [bp2d(Val(:reducedForm),[X[ii[2]],Y[ii[3]]], P[ii[1]])[2] for ii in Ind1]\nInd2 = findall( abs.(V2a) .<= 3e-3 * maximum(abs.(V2a)))\n\n# get solutions\nresp = Float64[]; resx = Vector{Float64}[]; resnrm = Float64[]\n\t@showprogress for k in Ind2\n\t\tii = Ind1[k]\n\t\tpush!(resp, P[ii[1]])\n\t\tpush!(resnrm, sqrt(X[ii[2]]^2+Y[ii[3]]^2))\n\t\tpush!(resx, [X[ii[2]], Y[ii[3]]])\n\tend","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can now plot the local bifurcation diagram as follows","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"using LaTeXStrings\nplot(\n\tscatter(1e4resp, map(x->x[1], resx), map(x->x[2], resx); label = \"\", markerstrokewidth=0, xlabel = L\"10^4 \\cdot \\lambda\", ylabel = L\"x_1\", zlabel = L\"x_2\", zcolor = resnrm, color = :viridis,colorbar=false),\n\tscatter(1e4resp, resnrm; label = \"\", markersize =2, markerstrokewidth=0, xlabel = L\"10^4 \\cdot \\lambda\", ylabel = L\"\\|x\\|\"))","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"This looks like a Pitchfork bifurcation with D4 symmetry","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can see that there are two types of solutions. After the bifurcation point, the solutions are of the form (x_1x_2) = (pm xpm x) for some real x. Before the bifurcation point, the solutions are of the form (x_1x_2) = (pm x0) (0 pm x) for some real x. Here is an example plotsol(bp2d(resx[10], resp[10]))","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We could use the solutions saved in resp, resx as initial guesses for a call to continuation but we turn to a different method.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"tip: Solutions\nThe brute force method provided all solutions in a neighborhood of the bifurcation point.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"info: Advanced computation\nInstead of using brute force and computing the vector field on a grid. One can rely on IntervalConstraintProgramming.jl to do better using bisection. See also this discourse post where the same example is treated by D. P. Sanders. ","category":"page"},{"location":"tutorials/mittelmann/#Branch-switching-with-deflated-newton-(manual)","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Branch switching with deflated newton (manual)","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"At this stage, we know what happens at the 2d bifurcation point of the curve of homogeneous solutions. We chose another method based on Deflated problems. We want to find all nearby solutions of the problem close to this bifurcation point. This is readily done by trying several initial guesses in a brute force manner:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"out = zeros(Nx*Ny)\n# deflation operator to\ndeflationOp = DeflationOperator(2, 1.0, [zeros(Nx*Ny)])\n\n# options for the newton solver\noptdef = setproperties(opt_newton; tol = 1e-8, max_iterations = 100)\n\n# eigen-elements close to the second bifurcation point on the branch\n# of homogeneous solutions\nvp, ve, _, _= eigls(JFmit(out, @set par_mit.λ = br.specialpoint[2].param), 5)\n\nfor ii=1:length(ve)\n\toutdef1 = newton(\n\t\tre_make(prob,\n\t\t # initial guess for newton\n\t\t u0 = br.specialpoint[2].x .+ 0.01 .* real.(ve[ii]) .* (1 .+ 0.01 .* rand(Nx*Ny)),\n\t\t params = (@set par_mit.λ = br.specialpoint[2].param + 0.005)),\n deflationOp,\n\t\toptdef)\n\t\tBK.converged(outdef1) && push!(deflationOp, outdef1.u)\nend","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"This provides length(deflationOp) = 5 solutions as there are some symmetries in the problem. For example plotsol(deflationOp[5]) gives","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can continue this solution as follows in one direction","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"brdef1 = continuation(\n\tre_make(prob,\n\t u0 = deflationOp[3],\n params = (@set par_mit.λ = br.specialpoint[2].param + 0.005)),\n PALC(),\n\tsetproperties(opts_br;ds = -0.001, detect_bifurcation = 3, dsmax = 0.01, max_steps = 500);\n\tkwargsC...)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"If we repeat the above loop but before the branch point by using @set par_mit.λ = br.specialpoint[2].param + 0.005, we get 3 new solutions that we can continue","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"brdef2 = continuation(\n re_make(prob,\n u0 = deflationOp[5],\n params = (@set par_mit.λ = br.specialpoint[2].param + 0.005)),\n PALC(),\n\tsetproperties(opts_br;ds = 0.001, detect_bifurcation = 3, dsmax = 0.01);\n\tkwargsC...)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"thereby providing the following bifurcation diagram with plot(br,br1,br2,brdef1, brdef2,plotfold=false, putbifptlegend = false)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/#sh3d","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Pages = [\"tutorialsSH3d.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"info: Why this example?\nThis example is challenging because we cannot employ the easy to use \\ sparse linear solver which takes too much time/memory to do the LU decomposition. Hence, one has to be tricky to devise a preconditioned linear solver that does not explode the memory budget. But then, one has to also devise a specific eigensolver. This is done in this tutorial. It also shows how this can be used for automatic branch switching. Hence, if you are not happy with the linear / eigen solvers in BifurcationKit.jl, this is perhaps the example you are looking for.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We look at the following PDE on a 3d domain, e.g. a cube:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"-(I+Delta)^2 u+lcdot u +nu u^2-u^3 = 0tagE","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"with Neumann boundary conditions. We use a Sparse Matrix to express the operator L_1equiv(I+Delta)^2. However, compared to the 2d case (see 2d Swift-Hohenberg equation: snaking), we cannot use directly \\ to solve linear systems because the LU décomposition is a bit slow, it uses a lot of memory.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We start by defining the associated functional to encode (E).","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"using Revise, Parameters, KrylovKit\nusing GLMakie # must be imported before BifurcationKit to trigger some imports\nusing BifurcationKit\nusing LinearAlgebra, SparseArrays, LinearMaps, DiffEqOperators, Setfield\nconst BK = BifurcationKit\n\nfunction Laplacian3D(Nx, Ny, Nz, lx, ly, lz, bc = :Neumann)\n\tspeye(n) = sparse(I, n, n)\n\thx = 2lx/Nx; hy = 2ly/Ny; hz = 2lz/Nz\n\tD2x = CenteredDifference{1}(2, 2, hx, Nx)\n\tD2y = CenteredDifference{1}(2, 2, hy, Ny)\n\tD2z = CenteredDifference{1}(2, 2, hz, Nz)\n\tQx = Neumann0BC(hx); Qy = Neumann0BC(hy); Qz = Neumann0BC(hz)\n\n\t_A = kron(speye(Ny), sparse(D2x * Qx)[1]) + kron(sparse(D2y * Qy)[1], speye(Nx))\n\tA = kron(speye(Nz), _A) + kron(kron(sparse(D2z * Qz)[1], speye(Ny)), speye(Nx))\n\treturn sparse(A), D2x\nend\n\n# main functional\nfunction F_sh(u, p)\n\t@unpack l, ν, L1 = p\n\treturn -(L1 * u) .+ (l .* u .+ ν .* u.^2 .- u.^3)\nend\n\n# differential of the functional\nfunction dF_sh(u, p, du)\n\t@unpack l, ν, L1 = p\n\treturn -(L1 * du) .+ (l .+ 2 .* ν .* u .- 3 .* u.^2) .* du\nend\n\n# various differentials\nd2F_sh(u, p, dx1, dx2) = (2 .* p.ν .* dx2 .- 6 .* dx2 .* u) .* dx1\nd3F_sh(u, p, dx1, dx2, dx3) = (-6 .* dx2 .* dx3) .* dx1\n\n# these types are useful to switch to GPU\nTY = Float64\nAF = Array{TY}","category":"page"},{"location":"tutorials/tutorialsSH3d/#Plotting-with-Makie","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Plotting with Makie","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"In most tutorials, we have used Plots.jl for the figures. However, it appears that Makie.jl is more convenient for 3d plots. We thus define the following convenience functions to display the solutions of (E).","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"contour3dMakie(x; k...) = GLMakie.contour(x; k...)\ncontour3dMakie(x::AbstractVector; k...) = contour3dMakie(reshape(x,Nx,Ny,Nz); k...)\n\ncontour3dMakie(ax, x; k...) = (GLMakie.contour(ax, x; k...))\ncontour3dMakie(ax, x::AbstractVector; k...) = contour3dMakie(ax, reshape(x,Nx,Ny,Nz); k...)\n\ncontour3dMakie!(ax, x; k...) = (GLMakie.contour!(ax, x; k...))\ncontour3dMakie!(ax, x::AbstractVector; k...) = contour3dMakie!(ax, reshape(x,Nx,Ny,Nz); k...)","category":"page"},{"location":"tutorials/tutorialsSH3d/#Setting-up-the-problem","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Setting up the problem","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We provide the parameters defining the PDE:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Nx = Ny = Nz = 22; N = Nx*Ny*Nz\nlx = ly = lz = pi\n\nX = -lx .+ 2lx/(Nx) * collect(0:Nx-1)\nY = -ly .+ 2ly/(Ny) * collect(0:Ny-1)\nZ = -lz .+ 2lz/(Nz) * collect(0:Nz-1)\n\n# initial guess for newton\nsol0 = [(cos(x) .* cos(y )) for x in X, y in Y, z in Z]\n\tsol0 .= sol0 .- minimum(vec(sol0))\n\tsol0 ./= maximum(vec(sol0))\n\tsol0 .*= 1.7\n\n# parameters for PDE\nΔ, D2x = Laplacian3D(Nx, Ny, Nz, lx, ly, lz, :Neumann);\nL1 = (I + Δ)^2;\npar = (l = 0.1, ν = 1.2, L1 = L1);","category":"page"},{"location":"tutorials/tutorialsSH3d/#Choice-of-linear-solver","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Choice of linear solver","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Let us run a quick benchmark to evaluate the direct linear solvers:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"julia> @time cholesky(L1) \\ sol_hexa;\n 0.152849 seconds (54 allocations: 87.273 MiB)\n\njulia> @time lu(L1) \\ sol_hexa;\n 0.556157 seconds (87 allocations: 226.210 MiB, 0.49% compilation time)\n\njulia> @time qr(L1) \\ sol_hexa;\n 1.609175 seconds (8.96 k allocations: 989.285 MiB, 2.67% gc time, 0.67% compilation time)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Hence, cholesky is the big winner but it requires a positive matrix so let's see how to do that.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"As said in the introduction, the LU linear solver does not scale well with dimension N. Hence, we do something else. We note that the matrix L_1 is hermitian positive and use it as a preconditioner. Thus, we pre-factorize it using a Cholesky decomposition:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Pr = cholesky(L1);\nusing SuiteSparse\n# we need this \"hack\" to be able to use Pr as a preconditioner.\nLinearAlgebra.ldiv!(o::Vector, P::SuiteSparse.CHOLMOD.Factor{Float64}, v::Vector) = o .= -(P \\ v)\n\n# rtol must be small enough to pass the Fold points and to get precise eigenvalues\n# we know that the jacobian is symmetric so we tell the solver\nls = GMRESKrylovKit(verbose = 0, rtol = 1e-9, maxiter = 150, ishermitian = true, Pl = Pr)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Let's try this on a Krylov-Newton computation to refine the guess sol0:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"prob = BifurcationProblem(F_sh, AF(vec(sol0)), par, (@lens _.l),\n\tJ = (x, p) -> (dx -> dF_sh(x, p, dx)),\n\tplot_solution = (ax, x, p) -> contour3dMakie(ax, x),\n\trecord_from_solution = (x, p) -> (n2 = norm(x), n8 = norm(x, 8)))\n\noptnew = NewtonPar(verbose = true, tol = 1e-8, max_iterations = 20, linsolver = ls)\nsol_hexa = @time newton(prob, optnew)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"which gives","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 2.6003e+02 │ 0 │\n│ 1 │ 1.5414e+02 │ 25 │\n│ 2 │ 2.6040e+02 │ 21 │\n│ 3 │ 7.3531e+01 │ 21 │\n│ 4 │ 2.0513e+01 │ 23 │\n│ 5 │ 6.4608e+00 │ 18 │\n│ 6 │ 1.3743e+00 │ 18 │\n│ 7 │ 1.7447e-01 │ 17 │\n│ 8 │ 4.0924e-03 │ 17 │\n│ 9 │ 2.4048e-06 │ 17 │\n│ 10 │ 1.8389e-10 │ 17 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.405419 seconds (1.22 M allocations: 205.788 MiB, 2.16% gc time, 18.84% compilation time)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"and contour3dMakie(sol_hexa) produces","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/#Continuation-and-bifurcation-points","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Continuation and bifurcation points","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We now switch gears and compute the stability of the trivial solution u=0. We will then branch from the detected bifurcation points. However, we wish to show an example of computation of eigenvalues based on a custom preconditioned Shift-Invert strategy.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We thus define our eigensolver based on the previously defined pre-conditioned linear solver ls:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"# structure to hold eigensolver\nstruct SH3dEig{Ts, Tσ} <: BK.AbstractEigenSolver\n\t# linear solver used for Shift-Invert strategy\n\tls::Ts\n\t# shift of the linear operator\n\tσ::Tσ\nend\n\n# function to extract eigenvectors, used for automatic branch switching\nBifurcationKit.geteigenvector(eigsolve::SH3dEig, vecs, n::Union{Int, Array{Int64,1}}) = vecs[n]\n\n# implementation of Shift-invert strategy\nfunction (sheig::SH3dEig)(J, nev::Int; verbosity = 0, kwargs...)\n\tσ = sheig.σ\n\tnv = 30\n\tJshift = du -> J(du) .- σ .* du\n\tA = du -> sheig.ls(Jshift, du)[1]\n\t# we adapt the krylov dimension as function of the requested eigenvalue number\n\tvals, vec, info = KrylovKit.eigsolve(A, AF(rand(Nx*Ny*Nz)), nev, :LM;\n\t\t tol = 1e-12, maxiter = 20, verbosity = verbosity, ishermitian = true,\n\t\t krylovdim = max(nv, nev + nv))\n\tvals2 = 1 ./vals .+ σ\n\tInd = sortperm(vals2, by = real, rev = true)\n\treturn vals2[Ind], vec[Ind], true, info.numops\nend","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We can then declare our eigensolver and pass it to the newton parameters","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"eigSH3d = SH3dEig((@set ls.rtol = 1e-9), 0.1)\n@set! optnew.eigsolver = eigSH3d","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We are now ready to perform continuation and detection of bifurcation points:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"optcont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= -0.001, p_max = 0.15,\n\tp_min = -.1, newton_options = setproperties(optnew; tol = 1e-9, maxIter = 15),\n\tmax_steps = 146, detect_bifurcation = 3, nev = 15, n_inversion = 4, plot_every_step = 1)\n\nbr = continuation( re_make(prob, u0 = zeros(N)),\n # we use a particular bordered linear solver to\n # take advantage of our specific linear solver\n PALC(bls = BorderingBLS(solver = optnew.linsolver, check_precision = false)),\n optcont;\n normC = x -> norm(x, Inf),\n\tplot = true, verbosity = 3)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"The following result shows the detected bifurcation points (its takes ~300s)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"julia> br\nBranch number of points: 34\nBranch of Equilibrium\nParameters l from 0.1 to -0.1\nBifurcation points:\n (ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`)\n- # 1, bp at l ≈ +0.06243495 ∈ (+0.06243495, +0.06287689), |δp|=4e-04, [converged], δ = (-1, 0), step = 8, eigenelements in eig[ 9], ind_ev = 10\n- # 2, nd at l ≈ +0.06069653 ∈ (+0.06069653, +0.06069826), |δp|=2e-06, [converged], δ = (-6, 0), step = 9, eigenelements in eig[ 10], ind_ev = 9\n- # 3, nd at l ≈ -0.00007046 ∈ (-0.00007046, +0.00015051), |δp|=2e-04, [converged], δ = (-3, 0), step = 18, eigenelements in eig[ 19], ind_ev = 3","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We get the following plot during computation:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorialsSH3d/#Automatic-branch-switching","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Automatic branch switching","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"warning: Computation time\nThe following computation takes ~1.5h","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We can use Branch switching to compute the different branches emanating from the bifurcation points. For example, the following code will perform automatic branch switching from the last bifurcation point of br. Note that this bifurcation point is 3d.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"br1 = @time continuation(br, 3, setproperties(optcont; save_sol_every_step = 10,\n\tdetect_bifurcation = 0, p_max = 0.1, plot_every_step = 5, dsmax = 0.02);\n\tplot = true, verbosity = 3,\n\t# to set initial point on the branch\n\tδp = 0.01,\n\t# remove display of deflated newton iterations\n\tverbosedeflation = false,\n\talg = PALC(tangent = Bordered()),\n\tlinear_algo = BorderingBLS(solver = optnew.linsolver, check_precision = false),\n\t# to compute the normal form, so we don't have to\n\t# compute the left eigenvectors\n\tissymmetric = true,\n\tplot_solution = (ax, x, p) -> contour3dMakie(ax, x),\n\trecord_from_solution = (x, p) -> (n2 = norm(x), n8 = norm(x, 8)),\n\tnormC = x -> norm(x, Inf))","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We can then plot the branches using BK.plotBranch(br, branches...) where green (resp. red) means stable (resp. unstable) solution.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"There are 19 banches that were discovered. You can plot the solutions on the branches using","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"fig = Figure(resolution = (1200, 900))\n\tfor i=1:length(br1)\n\t\tix = div(i,5)+1; iy = i%5+1\n\t\t@show i, ix, iy\n\t\tax = Axis3(fig[ix, iy], title = \"$i\", aspect = (1, 1, 1))\n\t\thidedecorations!(ax, grid=false)\n\t\tcontour3dMakie!(ax, br1[i].sol[2].x)\n\t\tax.protrusions = (0, 0, 0, 10)\n\tend\n\tdisplay(fig)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"periodicOrbit/#Periodic-orbits-computation","page":"Introduction","title":"Periodic orbits computation","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"Consider the Cauchy problem","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"fracdudt=F(up)","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"A periodic solution with period T satisfies","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"beginalign\nfracdudt=F(up)\nu(0)=u(T)\nendalign","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"We provide 4 methods for computing periodic orbits (PO):","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"one (Trapezoid) based on finite differences to discretize a Cauchy problem,\none (Collocation) based on orthogonal collocation to discretize a Cauchy problem,\ntwo (Shooting) based on the flow associated to a Cauchy problem.","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"It is important to understand the pro and cons of each method to compute PO in large dimensions.","category":"page"},{"location":"periodicOrbit/#Trapezoid-method","page":"Introduction","title":"Trapezoid method","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The Trapezoid method (or the Collocation one) is usually faster than the ones based on Shooting but it requires more memory as it saves the whole orbit. However the main drawback of this method is that the associated linear solver is not \"nice\", being composed of a cyclic matrix for which no generic Matrix-free preconditioner is known. Hence, the Trapezoid method is often used with an ILU preconditioner which is severely constrained by memory. Also, when the period of the cycle is large, finer time discretization (or mesh adaptation which is not yet implemented) must be employed which is also a limiting factor both in term of memory and preconditioning.","category":"page"},{"location":"periodicOrbit/#Collocation-method","page":"Introduction","title":"Collocation method","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The Collocation method is (for now) the slowest of the three methods implemented for computing periodic orbits. However, it is by far the most precise one. Additionally, the mesh can be automatically adapted during the continuation. The implementation will be improved for large dimensional systems like the Trapezoid method one.","category":"page"},{"location":"periodicOrbit/#Shooting-method","page":"Introduction","title":"Shooting method","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The methods based on Shooting do not share the same drawbacks because the associated linear system is usually well conditioned, at least in the simple shooting case. There are thus often used without preconditioner at all. Even in the case of multiple shooting, this can be alleviated by a simple generic preconditioner based on deflation of eigenvalues (see Linear solvers (LS)). Also, the time stepper will automatically adapt to the stiffness of the problem, putting more time points where needed unlike the method based on finite differences which requires an adaptive (time) meshing to provide a similar property. Finally, we can use parallel Shooting to greatly increase the speed of computation.","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The main drawback of the method is to find a fast time stepper, at least to compete with the method based on finite differences. The other drawback is the precision of the method which cannot compete with the collocation method.","category":"page"},{"location":"periodicOrbit/#Important-notes","page":"Introduction","title":"Important notes","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"We regroup here some important notes which are valid for all methods above. ","category":"page"},{"location":"periodicOrbit/#.-Accessing-the-periodic-orbit","page":"Introduction","title":"1. Accessing the periodic orbit","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"In record_from_solution, plot_solution or after the computation of a branch of periodic orbits, how do I obtain the periodic orbit, for plotting purposes for example? If x is the solution from newton for the parameter p, you can obtain the periodic orbit as follows","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"xtt = get_periodic_orbit(x, p)","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"where xtt.t contains the time mesh and xtt[:,:] contains the different components. Note that for Trapezoid and collocation methods, calling get_periodic_orbit is essentially free as it is a reshape of x. However, in the case of Shooting methods, this requires recomputing the periodic orbit which can be costly for large scale problems.","category":"page"},{"location":"periodicOrbit/#.-Finaliser","page":"Introduction","title":"2. Finaliser","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"If you pass a finalise_solution function to continuation, the following occurs:","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"If the newton solve was successful, we update the phase condition every update_section_every_step\nwe call the user defined finalizer finalise_solution","category":"page"},{"location":"periodicOrbit/#.-Record-from-solution","page":"Introduction","title":"3. Record from solution","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"You can pass your own function to continuation. In the particular case of periodic orbits, the method is called like record_from_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem. You can then obtain the current periodic orbit using (see above)","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"xtt = get_periodic_orbit(x, opt.p)","category":"page"},{"location":"periodicOrbit/#.-Plot-solution","page":"Introduction","title":"4. Plot solution","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"Similarly to record_from_solution, the method is called like plot_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem.","category":"page"},{"location":"periodicOrbit/#.-Most-precise-method-for-Floquet-coefficients","page":"Introduction","title":"5. Most precise method for Floquet coefficients","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbit/#.-Misc","page":"Introduction","title":"6. Misc","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"set_params_po generate_ci_problem generate_solution","category":"page"},{"location":"nonsimplebp/#Non-simple-branch-point","page":"Non-simple branch point","title":"Non-simple branch point","text":"","category":"section"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"unknown: References\nThe general method is exposed in Golubitsky, Martin, David G Schaeffer, and Ian Stewart. Singularities and Groups in Bifurcation Theory. New York: Springer-Verlag, 1985, VI.1.d page 295","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"tip: Example\nAn example of use of the methods presented here is provided in 2d generalized Bratu–Gelfand problem. ","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"We expose our method to study non-simple branch points. Such branch point (x_0p_0) for the problem F(xp)=0 satisfies d=dim ker dF(x_0p_0) 1 and the eigenvalues have zero imaginary part. At such point, we can apply Lyapunov-Schmidt reduction to transform the initial problem in large dimensions to a d-dimensional polynomial equation, called the reduced equation.","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"More precisely, it is possible to write x = u + v where uin ker dF(x_0p_0) and vapprox 0 belongs to a vector space complement of ker dF(x_0p_0). It can be shown that u solves Phi(udelta p)=0 with Phi(udelta p) = (I-Pi)F(u+psi(udelta p)p_0+delta p) where psi is known implicitly and Pi is the spectral projector on ker dF(x_0p_0). Fortunately, one can compute the Taylor expansion of Phi up to order 3. Computing the bifurcation diagram of this d-dimensional multivariate polynomials can be done using brute force methods.","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"Once the zeros of Phi have been located, we can use them as initial guess for continuation but for the original F !!","category":"page"},{"location":"nonsimplebp/#Reduced-equation-computation","page":"Non-simple branch point","title":"Reduced equation computation","text":"","category":"section"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"The reduced equation (E) can be automatically computed as follows","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. It returns a point with all requested information:","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"mutable struct NdBranchPoint{Tv, T, Tevl, Tevr, Tnf} <: BranchPoint\n\t\"bifurcation point\"\n\tx0::Tv\n\n\t\"Parameter value at the bifurcation point\"\n\tp::T\n\n\t\"Right eigenvectors\"\n\tζ::Tevr\n\n\t\"Left eigenvectors\"\n\tζstar::Tevl\n\n\t\"Normal form coefficients\"\n\tnf::Tnf\n\n\t\"Type of bifurcation point\"\n\ttype::Symbol\nend","category":"page"},{"location":"nonsimplebp/#Using-the-reduced-equation","page":"Non-simple branch point","title":"Using the reduced equation","text":"","category":"section"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"Once a branch point has been computed bp = get_normal_form(...), you can do all sort of things. ","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"For example, quoted from the file test/testNF.jl, you can print the 2d reduced equation as follows:","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"julia> BifurcationKit.nf(bp2d)\n2-element Array{String,1}:\n \" + (3.23 + 0.0im) * x1 * p + (-0.123 + 0.0im) * x1^3 + (-0.234 + 0.0im) * x1 * x2^2\"\n \" + (-0.456 + 0.0im) * x1^2 * x2 + (3.23 + 0.0im) * x2 * p + (-0.123 + 0.0im) * x2^3\"","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"You can evaluate the reduced equation as bp2d(Val(:reducedForm), rand(2), 0.2). This can be used to find all the zeros of the reduced equation by sampling on a grid or using a general solver like Roots.jl. \nFinally, given a d-dimensional vector x and a parameter delta p, you can have access to an initial guess u (see above) by calling bp2d(rand(2), 0.1)","category":"page"},{"location":"nonsimplebp/#Branching-from-bifurcation-point","page":"Non-simple branch point","title":"Branching from bifurcation point","text":"","category":"section"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"It may happen that the general procedure fails. We thus expose the procedure multicontinuation in order to let the user tune it to its need.","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"The first step is to compute the reduced equation, say of the first bifurcation point in br.","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"bp = get_normal_form(br, 1)","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"Next, we want to find the zeros of the reduced equation. This is usually achieved by calling the predictor","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"pred = predictor(bp, δp)","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"which returns zeros of bp before and after the bifurcation point. You could also use your prefered procedure from Roots.jl (or other) to find the zeros of the polynomials bp(Val(:reducedForm), z, p).","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"We can use these zeros to form guesses to apply Newton for the full functional:","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"pts = BifurcationKit.getFirstPointsOnBranch(br, bp, pred, opts; δp = δp)","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"We can then use this to continue the different branches","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"brbp = BifurcationKit.multicontinuation(br, bp, pts.before, pts.after, opts)","category":"page"},{"location":"tutorials/tutorials1b/#Temperature-model-with-ApproxFun,-no-AbstractArray","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"Pages = [\"tutorials1b.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We reconsider the example Temperature model by relying on the package ApproxFun.jl which allows very precise function approximation. This is an interesting example because we have to change the scalar product of PALC for the method to work well.","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"This is one example where the state space, the space of solutions to the nonlinear equation, is not a subtype of AbstractArray. See Requested methods for Custom State for more informations.","category":"page"},{"location":"tutorials/tutorials1b/#Code-for-custom-state","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"Code for custom state","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We start with some imports:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"using ApproxFun, LinearAlgebra, Parameters, Setfield\n\nusing BifurcationKit, Plots\nconst BK = BifurcationKit","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We then need to add some methods not available in ApproxFun because the state space is not a subtype of AbstractArray:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"# specific methods for ApproxFun\nimport Base: eltype, similar, copyto!, length\nimport LinearAlgebra: mul!, rmul!, axpy!, axpby!, dot, norm\n\nsimilar(x::ApproxFun.Fun, T) = (copy(x))\nsimilar(x::ApproxFun.Fun) = copy(x)\nmul!(w::ApproxFun.Fun, v::ApproxFun.Fun, α) = (w .= α * v)\n\neltype(x::ApproxFun.Fun) = eltype(x.coefficients)\nlength(x::ApproxFun.Fun) = length(x.coefficients)\n\ndot(x::ApproxFun.Fun, y::ApproxFun.Fun) = sum(x * y)\n\naxpy!(a, x::ApproxFun.Fun, y::ApproxFun.Fun) = (y .= a * x + y)\naxpby!(a::Float64, x::ApproxFun.Fun, b::Float64, y::ApproxFun.Fun) = (y .= a * x + b * y)\nrmul!(y::ApproxFun.Fun, b::Float64) = (y.coefficients .*= b; y)\nrmul!(y::ApproxFun.Fun, b::Bool) = b == true ? y : (y.coefficients .*= 0; y)\n\ncopyto!(x::ApproxFun.Fun, y::ApproxFun.Fun) = ( (x.coefficients = copy(y.coefficients);x))","category":"page"},{"location":"tutorials/tutorials1b/#Problem-formulation","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"Problem formulation","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We can easily write our functional with boundary conditions in a convenient manner using ApproxFun:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"N(x; a = 0.5, b = 0.01) = 1 + (x + a*x^2)/(1 + b*x^2)\ndN(x; a = 0.5, b = 0.01) = (1-b*x^2+2*a*x)/(1+b*x^2)^2\n\nfunction F_chan(u, p)\n\t@unpack α, β, Δ = p\n\treturn [Fun(u(0.), domain(u)) - β,\n\t\tFun(u(1.), domain(u)) - β,\n\t\tΔ * u + α * N(u, b = β)]\nend\n\nfunction Jac_chan(u, p)\n\t@unpack α, β, Δ = p\n\treturn [Evaluation(u.space, 0.),\n\t\tEvaluation(u.space, 1.),\n\t\tΔ + α * dN(u, b = β)]\nend","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We want to call a Newton solver. We first need an initial guess and the Laplacian operator:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"sol = Fun(x -> x * (1-x), Interval(0.0, 1.0))\nΔ = Derivative(sol.space, 2)\n# set of parameters\npar_af = (α = 3., β = 0.01, Δ = Δ)\n\nprob = BifurcationProblem(F_chan, sol, par_af, (@lens _.α); J = Jac_chan, plot_solution = (x, p; kwargs...) -> plot!(x; label = \"l = $(length(x))\", kwargs...))","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"Finally, we need to provide some parameters for the Newton iterations. This is done by calling","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"optnewton = NewtonPar(tol = 1e-12, verbose = true)","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We call the Newton solver:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"out = @time BK.newton(prob, optnewton, normN = x -> norm(x, Inf64))","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"and you should see","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.5707e+00 │ 0 │\n│ 1 │ 1.1546e-01 │ 1 │\n│ 2 │ 8.0149e-04 │ 1 │\n│ 3 │ 3.9038e-08 │ 1 │\n│ 4 │ 7.9049e-13 │ 1 │\n└─────────────┴──────-───────────────┴────────────────┘\n 0.103869 seconds (362.15 k allocations: 14.606 MiB)","category":"page"},{"location":"tutorials/tutorials1b/#Continuation","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"Continuation","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We can also perform numerical continuation with respect to the parameter alpha. Again, we need to provide some parameters for the continuation:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"optcont = ContinuationPar(dsmin = 0.0001, dsmax = 0.05, ds= 0.005, p_max = 4.1, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, max_iterations = 20, verbose = true), detect_bifurcation = 0, max_steps = 200)","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"Then, we can call the continuation routine.","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"# we need a specific bordered linear solver\n# we use the BorderingBLS one to rely on ApproxFun.\\\nbr = continuation(prob, PALC(bls = BorderingBLS(solver = optnewton.linsolver, check_precision = false)), optcont,\n\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> plot!(x; label = \"l = $(length(x))\", kwargs...),\n\tverbosity = 2,\n\tnormC = x -> norm(x, Inf64))","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"and you should see","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"However, if we do that, we'll see that it does not converge very well. The reason is that the default arc-length constraint (see Pseudo arclength continuation) is","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"N(x p)=fracthetatext length(x)leftlangle x-x_0 d x_0rightrangle+(1-theta) cdotleft(p-p_0right) cdot d p_0-d s=0","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"is tailored for vectors of fixed length. The frac1length(x) is added to properly balance the terms in the constraint. Thus, in BifurcationKit, the dot product is in fact (x,y) -> dot(x,y) / length(y).","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"But here, the vector space is provided with a custom dot product (see above) which depends on the domain, here Interval(0.0, 1.0). Hence, we want to change this constraint N for the following:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"N(x p)=thetaleftlangle x-x_0 d x_0rightrangle+(1-theta) cdotleft(p-p_0right) cdot d p_0-d s=0","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"This can be done as follows:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"optcont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 4.1, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, maxIter = 20, verbose = true), max_steps = 300, θ = 0.2, detect_bifurcation = 0)\n\nbr = continuation(prob, PALC(bls=BorderingBLS(solver = optnewton.linsolver, check_precision = false)), optcont,\n\tplot = true,\n\t# specify the dot product used in PALC\n\tdotPALC = BK.DotTheta(dot),\n\t# we need a specific bordered linear solver\n\t# we use the BorderingBLS one to rely on ApproxFun.\\\n\tlinear_algo = BorderingBLS(solver = DefaultLS(), check_precision = false),\n\tplot_solution = (x, p; kwargs...) -> plot!(x; label = \"l = $(length(x))\", kwargs...),\n\tverbosity = 2,\n\tnormC = x -> norm(x, Inf64))","category":"page"},{"location":"DeflatedContinuation/#Deflated-Continuation","page":"Deflated continuation","title":"Deflated Continuation","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"unknown: References\nFarrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. The Computation of Disconnected Bifurcation Diagrams. ArXiv:1603.00809 [Math], March 2, 2016. http://arxiv.org/abs/1603.00809.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"Deflated continuation allows to compute branches of solutions to the equation F(xp)=0. It is based on the Deflated Newton (see Deflated problems) algorithm.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"See DefCont for more information.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"However, unlike the regular continuation method, deflated continuation allows to compute disconnected bifurcation diagrams, something that is impossible for our Automatic Bifurcation diagram computation which is limited to the connected component of the initial point.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"You can find an example of use of the method in Carrier Problem. We reproduce below the result of the computation which shows various disconnected components arising form Fold bifurcations that are found seemingly by the method.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"(Image: )","category":"page"},{"location":"DeflatedContinuation/#Algorithm","page":"Deflated continuation","title":"Algorithm","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"Input: Initial parameter value λmin.\nInput: Final parameter value λmax > λmin. Input: Step size ∆λ > 0.\nInput: Nonlinear residual f(u,λ).\nInput: Deflation operator M(u; u∗).\nInput: Initial solutions S(λmin) to f(·,λmin).\nλ ← λmin\nwhile λ < λmax do\n\tF(·) ← f(·,λ+∆λ) \t\t\t\t\t\t# Fix the value of λ to solve for.\n\tS(λ+∆λ) ← ∅\n\tfor u0 ∈ S(λ) do \t\t\t\t\t\t# Continue known branches.\n\t\tapply Newton’s method to F from initial guess u0.\n\t\tif solution u∗ found then\n\t\t\tS(λ + ∆λ) ← S(λ + ∆λ) ∪ {u∗} # Record success\n\t\t\tF(·) ← M(·;u∗)F(·)\t\t\t # Deflate solution\n\n\tfor u0 ∈ S(λ) do \t\t\t\t\t # Seek new branches.\n\t\tsuccess ← true\n\t\twhile success do\n\t\t\tapply Newton’s method to F from initial guess u0.\n\t\t\tif solution u∗ found then\t\t # New branch found\n\t\t\t\tS(λ + ∆λ) ← S(λ + ∆λ) ∪ {u∗} # Record success\n\t\t\t\tF(·) ← M(·;u∗)F(·)\t\t # Deflate solution\n\t\telse\n\t\t\tsuccess ← false\n\tλ←λ+∆λ\nreturn S","category":"page"},{"location":"DeflatedContinuation/#Tips","page":"Deflated continuation","title":"Tips","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"The following piece of information is valuable in order to get the algorithm working in various conditions (see also here) especially for small systems (e.g. dim<20):","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"newton is quite good and it is convenient to limit it otherwise it will be able to bypass the deflation. For example, you can use maxIter = 10 in NewtonPar\ntry to limit the newton residual by using the argument callback_newton = BifurcationKit.cbMaxNorm(1e7). This will likely remove the occurrence of ┌ Error: Same solution found for identical parameter value!!\nfinally, you can try some aggressive shift (here 0.01 in the deflation operator, like DeflationOperator(2, dot, 0.01, [sol]) but use it wisely.","category":"page"},{"location":"DeflatedContinuation/#Basic-example","page":"Deflated continuation","title":"Basic example","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"We show a quick and simple example of use. Note in particular that the algorithm is able to find the disconnected branch. The starting points are marked with crosses","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"using BifurcationKit, LinearAlgebra, Setfield, SparseArrays, Plots\nconst BK = BifurcationKit\n\nk = 2\nN = 1\nF(x, p) = @. p * x + x^(k+1)/(k+1) + 0.01\nJac_m(x, p) = diagm(0 => p .+ x.^k)\n\n# bifurcation problem\nprob = BifurcationProblem(F, [0.], 0.5, (@lens _), J = Jac_m)\n\n# continuation options\nopts = BK.ContinuationPar(dsmax = 0.051, dsmin = 1e-3, ds=0.001, max_steps = 140, p_min = -3., newton_options = NewtonPar(tol = 1e-8), save_eigenvectors = false)\n\n# algorithm\nalg = BK.DefCont(deflation_operator = DeflationOperator(2, .001, [[0.]]), perturb_solution = (x,p,id) -> (x .+ 0.1 .* rand(length(x))))\n\nbrdc = continuation(prob, alg,\n\tContinuationPar(opts, ds = -0.001, max_steps = 800, newton_options = NewtonPar(verbose = false, max_iterations = 6), plot_every_step = 40),\n\t; plot=true, verbosity = 0,\n\tcallback_newton = BK.cbMaxNorm(1e3) # reject newton step if residual too large\n\t)\nplot(brdc)","category":"page"},{"location":"Predictors/#Predictors-Correctors","page":"Predictors / correctors","title":"Predictors - Correctors","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"The continuation method works with the following pattern (see [Allgower1990]):","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"compute tangent\ncall predictor (based on tangent, mostly)\ncall corrector","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"[Allgower1990]: Allgower and Georg, Numerical Continuation Methods, 1990","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"There are several couples predictor-tangent/corrector which can be used in BifurcationKit.jl as we now explain. The tangent computation is formally included in the predictor whereas it is a distinct function in the code.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"info: Corrector\nNote that setting the predictor also sets the corresponding corrector: it selects the couple predictor-corrector. You don't have (in fact cannot) set them independently.","category":"page"},{"location":"Predictors/#.-Natural,-zeroth-order-predictor","page":"Predictors / correctors","title":"1. Natural, zeroth order predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This is the dumbest predictor based on the formula (x_1p_1) = (x_0 p_0 + ds) with Newton corrector ; it fails at Turning points. This is set by the algorithm Natural() in continuation. For matrix based jacobian, it is not faster than the pseudo-arclength predictor because the factorisation of the jacobian is cached. For Matrix-free methods, this predictor can be faster than the following ones until it hits a Turning point.","category":"page"},{"location":"Predictors/#.-First-order-predictor","page":"Predictors / correctors","title":"2. First order predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This predictor is based on a computation of the tangent tau = (dxdp) to the curve of solutions, it is given by (x_1p_1) = (x_0p_0) + dscdot tau. This predictor passes Turning points when used with PALC Newton corrector. BifurcationKit.jl provides two ways to compute the tangent (dx dp).","category":"page"},{"location":"Predictors/#a.-Secant-predictor","page":"Predictors / correctors","title":"2a. Secant predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This predictor is called secant and is parametrized by the algorithm PALC(tangent = Secant()) in continuation with Secant . It is computed by (dx dp) = (z_1 p_1) - (z_0 p_0) and normalized by the norm (x p)^2_theta = fracthetalength(x) langle xxrangle + (1 - theta)cdot p^2.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"warning: Parameter `θ`\nThe parameter θ in the struct ContinuationParis very important. It should be tuned for the continuation to work properly especially in the case of large problems where the langle x - x_0 dx_0rangle component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint N involves the term 1-θ.","category":"page"},{"location":"Predictors/#b.-Bordered-predictor","page":"Predictors / correctors","title":"2b. Bordered predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This predictor departs from the previous one in the way the tangent is estimated. It computes (dx dp) by solving solving the bordered linear system beginbmatrix F_x F_p\t fracthetalength(x)dx_0 (1-theta)dp_0endbmatrixbeginbmatrixdx dpendbmatrix =beginbmatrix0 1endbmatrix.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"It is set by the algorithm PALC(tangent = Bordered()) in continuation with Bordered. The linear solver for the linear problem in (dx dp) is set by the option bls in PALC: it is one of Bordered linear solvers (BLS).","category":"page"},{"location":"Predictors/#.-Polynomial-predictor","page":"Predictors / correctors","title":"3. Polynomial predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"The polynomial predictor is based on a fit (least square regression) of an nth-order polynomial P on the last k solution vectors, where n k. The arclength s is used for the polynomial which then fits the solution (x_ip_is_i) as P(s_i)approx (x_ip_i). To keep s in suitable range (see [Waugh]), we rescale it as sto fracs-bar ssigma where sigma is the standard deviation of the s_i.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This algorithm is parametrized by alg = Polynomial(Fred, n, k, v0) where pred::AbstractTangentComputation is the tangent predictor used only for the first k solutions before the polynomial predictor is operational and v0 is an example of guess. More information is available in Polynomial.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"[Waugh]: Waugh, Illingworth, and Juniper, “Matrix-Free Continuation of Limit Cycles for Bifurcation Analysis of Large Thermoacoustic Systems.”","category":"page"},{"location":"Predictors/#.-Multiple-predictor-(aka-pmcont-in-pde2path)","page":"Predictors / correctors","title":"4. Multiple predictor (aka pmcont in pde2path)","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"The predictor is designed [Uecker2014] to avoid spurious branch switching and pass singular points especially in PDE where branch point density can be quite high. It is based on the use of many predictors with increasing \"jumps\" (x_ip_i) = (x_0p_0) + icdot dscdot tau ileq nb and use a corrector (PALC Newton) with the following twist. The criterion is that in each Newton step, the residual has to decrease by a factor 0alpha1:","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":" F(u_np_n)leq alpha F(u_n-1p_n-1) ","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"otherwise the corrector fails. The solution that is returned is the one for the highest i. We refer to [Uecker2014] for an exposition of the step size adaption strategy.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This algorithm is parametrized by alg = Multiple(pred, x0, α, nb) where τ is an initial tangent vector (used to set the types) and pred::PALC is a predictor. The default value is pred = PALC(). More information is available in Multiple.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"[Uecker2014]: 1.Uecker, H. pde2path - A Matlab Package for Continuation and Bifurcation in 2D Elliptic Systems. NMTMA 7, 58–106 (2014).","category":"page"},{"location":"tutorials/tutorials3b/#bruss","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Pages = [\"tutorials3b.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"unknown: References\nThis example is taken from Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust, 1997.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"info: Goal\nThe goal of this tutorial is to show similar computations as in the previous tutorial but without using the automatic branch switching tools. This is for the experienced used who wants to dive more in the internals of the package. ","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We look at the Brusselator in 1d. The equations are as follows","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"beginaligned frac partial X partial t = frac D _ 1 l ^ 2 frac partial ^ 2 X partial z ^ 2 + X ^ 2 Y - ( β + 1 ) X + α frac partial Y partial t = frac D _ 2 l ^ 2 frac partial ^ 2 Y partial z ^ 2 + β X - X ^ 2 Y endaligned","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"with Dirichlet boundary conditions","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"beginarray l X ( t z = 0 ) = X ( t z = 1 ) = α Y ( t z = 0 ) = Y ( t z = 1 ) = β α endarray","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"These equations have been introduced to reproduce an oscillating chemical reaction. There is an obvious equilibrium (α β α). Here, we consider bifurcations with respect to the parameter l.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We start by writing the PDE","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"using Revise\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Setfield, Parameters\nconst BK = BifurcationKit\n\nf1(u, v) = u * u * v\n\nfunction Fbru!(f, x, p, t = 0)\n\t@unpack α, β, D1, D2, l = p\n\tn = div(length(x), 2)\n\th2 = 1.0 / n^2\n\tc1 = D1 / l^2 / h2\n\tc2 = D2 / l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\t# Dirichlet boundary conditions\n\tf[1] = c1 * (α\t - 2u[1] + u[2] ) + α - (β + 1) * u[1] + f1(u[1], v[1])\n\tf[end] = c2 * (v[n-1] - 2v[n] + β / α)\t\t\t + β * u[n] - f1(u[n], v[n])\n\n\tf[n] = c1 * (u[n-1] - 2u[n] + α ) + α - (β + 1) * u[n] + f1(u[n], v[n])\n\tf[n+1] = c2 * (β / α - 2v[1] + v[2])\t\t\t + β * u[1] - f1(u[1], v[1])\n\n\tfor i=2:n-1\n\t\t f[i] = c1 * (u[i-1] - 2u[i] + u[i+1]) + α - (β + 1) * u[i] + f1(u[i], v[i])\n\t\tf[n+i] = c2 * (v[i-1] - 2v[i] + v[i+1])\t\t\t + β * u[i] - f1(u[i], v[i])\n\tend\n\treturn f\nend\n\nFbru(x, p, t = 0) = Fbru!(similar(x), x, p, t)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"For computing periodic orbits, we will need a Sparse representation of the Jacobian:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"function Jbru_sp(x, p)\n\t@unpack α, β, D1, D2, l = p\n\t# compute the Jacobian using a sparse representation\n\tn = div(length(x), 2)\n\th = 1.0 / n; h2 = h*h\n\n\tc1 = D1 / p.l^2 / h2\n\tc2 = D2 / p.l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\tdiag = zeros(eltype(x), 2n)\n\tdiagp1 = zeros(eltype(x), 2n-1)\n\tdiagm1 = zeros(eltype(x), 2n-1)\n\n\tdiagpn = zeros(eltype(x), n)\n\tdiagmn = zeros(eltype(x), n)\n\n\t@. diagmn = β - 2 * u * v\n\t@. diagm1[1:n-1] = c1\n\t@. diagm1[n+1:end] = c2\n\n\t@. diag[1:n] = -2c1 - (β + 1) + 2 * u * v\n\t@. diag[n+1:2n] = -2c2 - u * u\n\n\t@. diagp1[1:n-1] = c1\n\t@. diagp1[n+1:end] = c2\n\n\t@. diagpn = u * u\n\treturn spdiagm(0 => diag, 1 => diagp1, -1 => diagm1, n => diagpn, -n => diagmn)\nend\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"tip: Tip\nWe could have used DiffEqOperators.jl like for the Swift-Hohenberg tutorial.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We shall now compute the equilibria and their stability.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"n = 500\n\n# parameters of the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\n\n# bifurcation problem\nprobBif = BK.BifurcationProblem(Fbru, sol0, par_bru, (@lens _.l);\n J = Jbru_sp,\n plot_solution = (x, p; kwargs...) -> (plotsol(x; label=\"\", kwargs... )),\n record_from_solution = (x, p) -> x[div(n,2)])\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"For the eigensolver, we use a Shift-Invert algorithm (see Eigen solvers (Eig))","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"eigls = EigArpack(1.1, :LM)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We continue the trivial equilibrium to find the Hopf points","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"opt_newton = NewtonPar(eigsolver = eigls, tol = 1e-9)\nopts_br_eq = ContinuationPar(dsmin = 0.001, dsmax = 0.01, ds = 0.001,\n\tp_max = 1.9, detect_bifurcation = 3, nev = 21,\n\tnewton_options = opt_newton, max_steps = 1000,\n\t# specific options for precise localization of Hopf points\n\tn_inversion = 6)\n\nbr = continuation(probBif, PALC(),opts_br_eq, verbosity = 0, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We obtain the following bifurcation diagram with 3 Hopf bifurcation points","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"scene = plot(br)","category":"page"},{"location":"tutorials/tutorials3b/#Normal-form-computation","page":"🟠 1d Brusselator","title":"Normal form computation","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We can compute the normal form of the Hopf points as follows","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"hopfpt = get_normal_form(br, 1)","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-Hopf-points","page":"🟠 1d Brusselator","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We use the bifurcation points guesses located in br.specialpoint to turn them into precise bifurcation points. For the second one, we have","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# index of the Hopf point in br.specialpoint\nind_hopf = 2\n\n# newton iterations to compute the Hopf point\nhopfpoint = newton(br, ind_hopf; normN = norminf)\nBK.converged(hopfpoint) && printstyled(color=:red, \"--> We found a Hopf Point at l = \", hopfpoint.u.p[1], \", ω = \", hopfpoint.u.p[2], \", from l = \", br.specialpoint[ind_hopf].param, \"\\n\")","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We now perform a Hopf continuation with respect to the parameters l, β","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"tip: Tip\nYou don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)\nbr_hopf = continuation(br, ind_hopf, (@lens _.β), optcdim2, normC = norminf, jacobian_ma = :minaug)\nscene = plot(br_hopf)","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-periodic-orbits-(Finite-differences)","page":"🟠 1d Brusselator","title":"Continuation of periodic orbits (Finite differences)","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Here, we perform continuation of periodic orbits branching from the Hopf bifurcation points.We need an educated guess for the periodic orbit which is given by guess_from_hopf:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# number of time slices\nM = 51\n\nl_hopf, Th, orbitguess2, hopfpt, vec_hopf = BK.guess_from_hopf(br, ind_hopf,\n\topts_br_eq.newton_options.eigsolver,\n\tM, 2.7; phase = 0.25)\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We wish to make two remarks at this point. The first is that an initial guess is composed of a space time solution and of the guess for the period Th of the solution. Note that the argument 2.7 is a guess for the amplitude of the orbit.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# orbit initial guess from guess_from_hopf, is not a vector, so we reshape it\norbitguess_f2 = reduce(vcat, orbitguess2)\norbitguess_f = vcat(vec(orbitguess_f2), Th) |> vec\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"The second remark concerns the phase 0.25 written above. To account for the additional unknown (i.e. the period), periodic orbit localisation using Finite Differences requires an additional constraint (see Periodic orbits based on Trapezoidal rule for more details). In the present case, this constraint is","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":" u(0) - u_hopf phi = 0","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"where u_{hopf} is the equilibrium at the Hopf bifurcation and phi is real.(vec_hopf) where vec_hopf is the eigenvector. This is akin to a Poincaré section. We do not put any constraint on u(t) albeit this is possible (see Periodic orbits based on Trapezoidal rule.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"The phase of the periodic orbit is set so that the above constraint is satisfied. We shall now use Newton iterations to find a periodic orbit.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Given our initial guess, we create a (family of) problem which encodes the functional associated to finding Periodic orbits based on Trapezoidal rule (see Periodic orbits based on Trapezoidal rule for more information):","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"poTrap = PeriodicOrbitTrapProblem(\n\tprobBif, \t\t # pass the bifurcation problem\n\treal.(vec_hopf),\t # used to set ϕ, see the phase constraint\n\thopfpt.u, # used to set uhopf, see the phase constraint\n\tM, 2n; # number of time slices\n\tjacobian = :FullSparseInplace) # jacobian of PO functional\t\t\t \n\nnothing #hide \t","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"To evaluate the functional at x, you call it like a function: poTrap(x, par) for the parameter par.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"note: Using the functional for deflation, Fold of limit cycles...\nThe functional poTrap gives you access to the underlying methods to call a regular newton. For example the functional is x -> poTrap(x, par) at parameter par. The (sparse) Jacobian at (x,p) is computed like this poTrap(Val(:JacFullSparse), x, p) while the Matrix Free version is dx -> poTrap((x, p, dx). This also allows you to call the newton deflated method (see Deflated problems) or to locate Fold point of limit cycles see PeriodicOrbitTrapProblem. You can also use preconditioners. In the case of more computationally intense problems (like the 2d Brusselator), this might be mandatory as using LU decomposition for the linear solve will use too much memory. See also the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"For convenience, we provide a simplified newton / continuation methods for periodic orbits. One has just to pass a PeriodicOrbitTrapProblem.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# we use the linear solver LSFromBLS to speed up the computations\nopt_po = NewtonPar(tol = 1e-10, verbose = true, max_iterations = 14, linsolver = BK.LSFromBLS())\n\n# we set the parameter values\npoTrap = @set poTrap.prob_vf.params = (@set par_bru.l = l_hopf + 0.01)\n\noutpo_f = @time newton(poTrap, orbitguess_f, opt_po, normN = norminf)\nBK.converged(outpo_f) && printstyled(color=:red, \"--> T = \", outpo_f.u[end], \", amplitude = \", BK.amplitude(outpo_f.u, n, M; ratio = 2),\"\\n\")\n# plot of the periodic orbit\nBK.plot_periodic_potrap(outpo_f.u, n, M; ratio = 2)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"and obtain","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.5225e-03 │ 0 │\n│ 1 │ 2.6324e-03 │ 2 │\n│ 2 │ 3.0558e-04 │ 2 │\n│ 3 │ 5.7499e-05 │ 2 │\n│ 4 │ 2.0407e-06 │ 2 │\n│ 5 │ 2.8184e-09 │ 2 │\n│ 6 │ 8.3969e-14 │ 2 │\n└─────────────┴──────────────────────┴────────────────┘\n 3.210008 seconds (77.85 k allocations: 2.497 GiB, 5.42% gc time)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Finally, we can perform continuation of this periodic orbit using the specialized call continuationPOTrap","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"opt_po = @set opt_po.eigsolver = EigArpack(; tol = 1e-5, v0 = rand(2n))\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.03, ds= 0.01,\n\tp_max = 3.0, max_steps = 20,\n\tnewton_options = opt_po, nev = 5, tol_stability = 1e-8, detect_bifurcation = 0)\n\nbr_po = continuation(poTrap,\n\toutpo_f.u, PALC(),\n\topts_po_cont;\n\tverbosity = 2,\tplot = true,\n\tplot_solution = (x, p;kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...),\n\tnormC = norminf)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/tutorials3b/#Deflation-for-periodic-orbit-problems","page":"🟠 1d Brusselator","title":"Deflation for periodic orbit problems","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Looking for periodic orbits branching of bifurcation points, it is very useful to use newton algorithm with deflation. We thus define a deflation operator (see previous example)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"deflationOp = DeflationOperator(2, (x,y) -> dot(x[1:end-1], y[1:end-1]), 1.0, [zero(orbitguess_f)])","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"which allows to find periodic orbits different from orbitguess_f. Note that the dot product removes the last component, i.e. the period of the cycle is not considered during this particular deflation. We can now use","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"outpo_f = @time newton(poTrap, orbitguess_f, deflationOp, opt_po; normN = norminf)","category":"page"},{"location":"tutorials/tutorials3b/#Floquet-coefficients","page":"🟠 1d Brusselator","title":"Floquet coefficients","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"A basic method for computing Floquet coefficients based on the eigenvalues of the monodromy operator is available (see FloquetQaD). It is precise enough to locate bifurcations. Their computation is triggered like in the case of a regular call to continuation:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"opt_po = @set opt_po.eigsolver = DefaultEig()\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.04, ds= -0.01, p_max = 3.0, max_steps = 200, newton_options = opt_po, nev = 5, tol_stability = 1e-6, detect_bifurcation = 3)\nbr_po = @time continuation(poTrap, outpo_f.u, PALC(),\n\topts_po_cont; verbosity = 3, plot = true,\n\tplot_solution = (x, p;kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...), normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"A more complete diagram can be obtained combining the methods (essentially deflation and Floquet) described above. It shows the period of the periodic orbits as function of l. See example/brusselator.jl for more information.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"danger: Floquet multipliers computation\nThe computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of the eigensolver. Nevertheless, note that for most implemented eigensolvers in the current Package, the proper option is set when the computation of Floquet multipliers is requested.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"tip: Performances\nThis example is clearly not optimized because we wanted to keep it simple. We can use a Matrix-Free version of the functional and preconditioners to speed this up. Floquet multipliers could also be computed in a Matrix-Free manner. See examples/brusselator.jl for more efficient methods. See also 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS) for a more advanced example where we introduce those methods.","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-periodic-orbits-(Standard-Shooting)","page":"🟠 1d Brusselator","title":"Continuation of periodic orbits (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Note that what follows is not really optimized on the DifferentialEquations.jl side. Indeed, we do not use automatic differentiation, we do not pass the sparsity pattern,...","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We now turn to a different method based on the flow of the Brusselator. To compute this flow (time stepper), we need to be able to solve the differential equation (actually a PDE) associated to the vector field Fbru. We will show how to do this with an implicit method Rodas4P from DifferentialEquations.jl. Note that the user can pass its own time stepper but for convenience, we use the ones in DifferentialEquations.jl. More information regarding the shooting method is contained in Periodic orbits based on the shooting method.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"n = 100\n\n# different parameters to define the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\nprobBif = re_make(probBif, u0 = sol0)\n\neigls = EigArpack(1.1, :LM)\nopts_br_eq = ContinuationPar(dsmin = 0.001, dsmax = 0.00615, ds = 0.0061, p_max = 1.9,\n\tdetect_bifurcation = 3, nev = 21, plot_every_step = 50,\n\tnewton_options = NewtonPar(eigsolver = eigls, tol = 1e-9), max_steps = 1060)\n\nbr = @time continuation(probBif, PALC(), opts_br_eq, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We need to create a guess for the periodic orbit. We proceed as previously:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# number of time slices\nM = 5\n\n# index of the Hopf point in the branch br\nind_hopf = 1\n\nl_hopf, Th, orbitguess2, hopfpt, vec_hopf = BK.guess_from_hopf(br, ind_hopf,\n\topts_br_eq.newton_options.eigsolver, M, 22*0.075)\n#\norbitguess_f2 = reduce(hcat, orbitguess2)\norbitguess_f = vcat(vec(orbitguess_f2), Th) |> vec","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Let us now initiate the Standard Shooting method. To this aim, we need to provide a guess of the periodic orbit at times TM_sh where T is the period of the cycle and M_sh is the number of slices along the periodic orbits. If M_sh = 1, this the Standard Simple Shooting and the Standard Multiple one otherwise. See ShootingProblem for more information.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"dM = 2\norbitsection = Array(orbitguess_f2[:, 1:dM:M])\n\n# the last component is an estimate of the period of the cycle.\ninitpo = vcat(vec(orbitsection), 3.0)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Finally, we need to build a problem which encodes the Shooting functional. This done as follows where we first create the time stepper. For performance reasons, we rely on SparseDiffTools","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"using DifferentialEquations, DiffEqOperators, SparseDiffTools, SparseArrays\n\nFOde(f, x, p, t) = Fbru!(f, x, p)\n\nu0 = sol0 .+ 0.01 .* rand(2n)\n\n# parameter close to the Hopf bifurcation point\npar_hopf = (@set par_bru.l = l_hopf + 0.01)\n\njac_prototype = Jbru_sp(ones(2n), @set par_bru.β = 0)\njac_prototype.nzval .= ones(length(jac_prototype.nzval))\n_colors = matrix_colors(jac_prototype)\nvf = ODEFunction(FOde; jac_prototype = jac_prototype, colorvec = _colors)\nprob = ODEProblem(vf, sol0, (0.0, 520.), par_bru)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We create the parallel standard shooting problem:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# this encodes the functional for the Shooting problem\nprobSh = ShootingProblem(\n\t# we pass the ODEProblem encoding the flow and the time stepper\n\tprob, Rodas4P(),\n\n\t# this is for the phase condition, you can pass your own section as well\n\t[orbitguess_f2[:,ii] for ii=1:dM:M];\n\n\t# enable threading\n\tparallel = true,\n\n\t# these are options passed to the ODE time stepper\n\tabstol = 1e-10, reltol = 1e-8,\n\n # parameter axis\n lens = (@lens _.l),\n\n # parameters\n par = par_hopf,\n\n # jacobian of the periodic orbit functional\n jacobian = BK.FiniteDifferencesMF())","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We are now ready to call newton","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"ls = GMRESIterativeSolvers(reltol = 1e-7, N = length(initpo), maxiter = 100)\noptn_po = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 20, linsolver = ls)\noutpo = @time newton(probSh, initpo, optn_po; normN = norminf)\nplot(initpo[1:end-1], label = \"Init guess\")\nplot!(outpo.u[1:end-1], label = \"sol\")","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"which gives (note that we did not have a really nice guess...)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.9613e-01 │ 0 │\n│ 1 │ 5.6101e-02 │ 45 │\n│ 2 │ 1.0307e-01 │ 49 │\n│ 3 │ 4.1119e-03 │ 48 │\n│ 4 │ 8.0511e-03 │ 49 │\n│ 5 │ 3.8250e-02 │ 48 │\n│ 6 │ 9.8080e-03 │ 49 │\n│ 7 │ 2.1179e+01 │ 53 │\n│ 8 │ 2.0105e+00 │ 36 │\n│ 9 │ 2.0545e+00 │ 49 │\n│ 10 │ 4.8793e-01 │ 49 │\n│ 11 │ 4.8457e-02 │ 46 │\n│ 12 │ 2.3299e-02 │ 49 │\n│ 13 │ 1.6365e-02 │ 48 │\n│ 14 │ 1.3534e-04 │ 49 │\n│ 15 │ 1.4582e-05 │ 48 │\n│ 16 │ 1.5886e-08 │ 49 │\n│ 17 │ 1.7228e-11 │ 49 │\n└─────────────┴──────────────────────┴────────────────┘\n 9.706977 seconds (7.61 M allocations: 13.964 GiB, 3.62% gc time)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"and","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Note that using Simple Shooting, the convergence is much faster. Indeed, running the code above with dM = 10 gives:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.1712e-03 │ 0 │\n│ 1 │ 3.4465e-03 │ 6 │\n│ 2 │ 1.0516e-01 │ 8 │\n│ 3 │ 7.4614e-03 │ 6 │\n│ 4 │ 1.6620e-03 │ 7 │\n│ 5 │ 3.9589e-04 │ 7 │\n│ 6 │ 4.3043e-05 │ 8 │\n│ 7 │ 1.7232e-06 │ 8 │\n│ 8 │ 8.0455e-09 │ 8 │\n│ 9 │ 3.9453e-11 │ 8 │\n└─────────────┴──────────────────────┴────────────────┘\n 0.612070 seconds (217.21 k allocations: 523.069 MiB, 4.83% gc time)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"info: Convergence and speedup\nThe convergence is much worse for the multiple shooting than for the simple one. This is reflected above in the number of linear iterations made during the newton solve. The reason for this is because of the cyclic structure of the jacobian which impedes GMRES from converging fast. This can only be resolved with an improved GMRES which we'll provide in the future.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Finally, we can perform continuation of this periodic orbit using a specialized version of continuation:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# note the eigensolver computes the eigenvalues of the monodromy matrix. Hence\n# the dimension of the state space for the eigensolver is 2n\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 1.5,\n\tmax_steps = 500, newton_options = (@set optn_po.tol = 1e-7), nev = 25,\n\ttol_stability = 1e-8, detect_bifurcation = 0)\n\nbr_po = @time continuation(probSh, outpo.u, PALC(),\n\topts_po_cont; verbosity = 2,\n\t# specific bordered linear solver\n\tlinear_algo = MatrixFreeBLS(@set ls.N = ls.N+1),\n\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], length(1:dM:M); kwargs...),\n\trecord_from_solution = (u, p) -> u[end], normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We can observe that simple shooting is faster but the Floquet multipliers are less accurate than for multiple shooting. Also, when the solution is very unstable, simple shooting can have spurious branch switching. Finally, note the 0=log 1 eigenvalue of the monodromy matrix in the graph below.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-periodic-orbits-(Poincaré-Shooting)","page":"🟠 1d Brusselator","title":"Continuation of periodic orbits (Poincaré Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We now turn to another Shooting method, namely the Poincaré one. We can provide this method thanks to the unique functionalities of DifferentialEquations.jl. More information is provided at PoincareShootingProblem and Periodic orbits based on the shooting method but basically, it is a shooting method between Poincaré sections Sigma_i (along the orbit) defined by hyperplanes. As a consequence, the dimension of the unknowns is M_shcdot(N-1) where N is the dimension of the phase space. Indeed, each time slice lives in an hyperplane Sigma_i. Additionally, the period T is not an unknown of the method but rather a by-product. However, the method requires the time stepper to find when the flow hits an hyperplane Sigma_i, something called event detection.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We show how to use this method, the code is very similar to the case of the Standard Shooting. We first define the functional for Poincaré Shooting Problem","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# sub-sampling factor of a initial guess for the periodic orbit\ndM = 5\n\n# vectors to define the hyperplanes Sigma_i\nnormals = [Fbru(orbitguess_f2[:,ii], par_hopf)/(norm(Fbru(orbitguess_f2[:,ii], par_hopf))) for ii = 1:dM:M]\ncenters = [orbitguess_f2[:,ii] for ii = 1:dM:M]\n\n# functional to hold the Poincare Shooting Problem\nprobHPsh = PoincareShootingProblem(\n\t# ODEProblem, ODE solver used to compute the flow\n\tprob, Rodas4P(),\n\n\t# parameters for the Poincaré sections\n\tnormals, centers;\n\n\t# enable threading\n\tparallel = true,\n\n\t# Parameters passed to the ODE solver\n\tabstol = 1e-10, reltol = 1e-8,\n\n # parameter axis\n lens = (@lens _.l),\n\n # parameters\n par = par_hopf,\n\n # jacobian of the periodic orbit functional\n jacobian = BK.FiniteDifferencesMF())","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Let us now compute an initial guess for the periodic orbit, it must live in the hyperplanes Sigma_i. Fortunately, we provide projections on these hyperplanes.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# projection of the initial guess on the hyperplanes. We assume that the centers[ii]\n# form the periodic orbit initial guess.\ninitpo_bar = reduce(vcat, BK.projection(probHPsh, centers))","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We can now call continuation to get the first branch.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# eigen / linear solver\neig = EigKrylovKit(tol= 1e-12, x₀ = rand(2n-1), dim = 40)\nls = GMRESIterativeSolvers(reltol = 1e-11, N = length(vec(initpo_bar)), maxiter = 500)\n\n# newton options\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 140, linsolver = ls)\n\n# continuation options\nopts_po_cont_floquet = ContinuationPar(dsmin = 0.0001, dsmax = 0.05, ds= 0.001,\n\tp_max = 2.5, max_steps = 500, nev = 10,\n\ttol_stability = 1e-5, detect_bifurcation = 3, plot_every_step = 3)\nopts_po_cont_floquet = @set opts_po_cont_floquet.newton_options =\n\tNewtonPar(linsolver = ls, eigsolver = eig, tol = 1e-9, verbose = true)\n\n# continuation run\nbr_po = @time continuation(probHPsh, vec(initpo_bar), PALC(),\n\topts_po_cont_floquet; verbosity = 3,\n\tlinear_algo = MatrixFreeBLS(@set ls.N = ls.N+1),\n\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot!(x; label=\"\", kwargs...),\n\tnormC = norminf)\t\t","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We also obtain the following information:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"julia> br_po\nBranch number of points: 41\nBifurcation points:\n- # 1, bp at p ≈ 1.20987963 ∈ (1.20128196, 1.20987963), |δp|=9e-03, [converged], δ = ( 1, 0), step = 21, eigenelements in eig[ 22], ind_ev = 1\n- # 2, ns at p ≈ 1.78687615 ∈ (1.77831727, 1.78687615), |δp|=9e-03, [converged], δ = ( 2, 2), step = 30, eigenelements in eig[ 31], ind_ev = 3\n- # 3, pd at p ≈ 1.85103701 ∈ (1.84676466, 1.85103701), |δp|=4e-03, [converged], δ = ( 1, 1), step = 31, eigenelements in eig[ 32], ind_ev = 4\n- # 4, ns at p ≈ 1.87667870 ∈ (1.86813520, 1.87667870), |δp|=9e-03, [converged], δ = ( 2, 2), step = 32, eigenelements in eig[ 33], ind_ev = 6\n","category":"page"},{"location":"bautin/#Normal-form-of-the-Bautin-bifurcation","page":"Bautin","title":"Normal form of the Bautin bifurcation","text":"","category":"section"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"We follow the paper[Kuznetsov] and consider a Cauchy problem","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"dot x=mathbf F(xp)","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"mathbf L q=i omega_0 q quad mathbf L^T p=-i omega_0 p quad langle p qrangle=1","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"Under some conditions, x(t)approx x_0+2Re w(t)q where w satisfies the normal form:","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"dotw=i omega_0 w+frac12 G_21 ww^2+frac112 G_32 ww^4+Oleft(w^6right)tagE","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"The second Lyapunov coefficient is ","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"l_2=frac112 operatornameRe G_32","category":"page"},{"location":"bautin/#Normal-form-computation","page":"Bautin","title":"Normal form computation","text":"","category":"section"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Bautin.","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"bautin/#References","page":"Bautin","title":"References","text":"","category":"section"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"tutorials/detonationEngine/#detonation","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"Pages = [\"detonationEngine.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"This is a model of a detonation engine, a new kind of reactor developed for planes. The model[Koch] quantifies the spatio-temporal evolution of a property analogous to specific internal energy, u(xt), on a one dimensional (1D) periodic domain:","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"left\nbegingathered\nfracpartial upartial t=nu_1 fracpartial^2 upartial x^2-u fracpartial upartial x+k q(1-lambda) exp left(fracu-u_calpharight)-epsilon u^2 \nfracpartial lambdapartial t=nu_2 fracpartial^2 lambdapartial x^2+k(1-lambda) exp left(fracu-u_calpharight) -fracs u_p lambda1+exp left(rleft(u-u_pright)right)\nendgatheredright","category":"page"},{"location":"tutorials/detonationEngine/#Problem-discretization","page":"🟠 Detonation engine","title":"Problem discretization","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We start by discretizing the above PDE based on finite differences.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"using Revise, Parameters\nusing DiffEqOperators, ForwardDiff, DifferentialEquations, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\nω(u, p) = p.k * exp((u - p.uc) / p.α)\nβ(u, p) = p.s * p.up /(1 + exp(p.r * (u - p.up)) )\n\n# utilities for plotting solutions\nfunction plotsol!(x; k...)\n\tn = length(x) ÷ 2\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\tplot!(u; label=\"u\", k...)\n\tplot!(v; label=\"λ\", k...)\nend\nplotsol(x; k...) = (plot();plotsol!(x; k...))\n\n# function to build derivative operators\nfunction DiffOp(N, lx; order = 2)\n\th = lx/N\n\n\tD2 = CenteredDifference(2, order, h, N)\n\tD = CenteredDifference(1, order, h, N)\n\n\tQ = PeriodicBC(Float64)\n\n\tΔ = sparse(D2 * Q)[1]\n\tD = sparse(D * Q)[1]\n\treturn D, Δ\nend\n\n# nonlinearity of the model\nfunction NL!(dest, U, p, t = 0.)\n\tN = p.N\n\tu = @view U[1:N]\n\tλ = @view U[N+1:2N]\n\tdest[1:N] .= p.q .* (1 .- λ) .* ω.(u, Ref(p)) .- p.ϵ .* u.^2\n\tdest[N+1:2N] .= (1 .- λ) .* ω.(u, Ref(p)) .- λ .* β.(u, Ref(p))\n\treturn dest\nend\n\n# function which encodes the right hand side of the PDE\n@views function Fdet!(f, u, p, t = 0)\n\tN = p.N\n\tNL!(f, u, p) \t\t\t\t\t\t# nonlinearity\n\tmul!(f, p.Δ, u, p.ν1, 1) \t\t\t# put Laplacian\n\tf[1:p.N] .-= (p.D * u[1:N].^2) ./ 2\t# add drift a la Burger\n\treturn f\nend\nNL(U, p, t = 0.) = NL!(similar(U), U, p, t)\nJNL(U, p, t = 0.) = ForwardDiff.jacobian(x -> NL(x, p), U)\nFdet(x, p, t = 0) = Fdet!(similar(x), x, p, t)\nJdet(x, p) = sparse(ForwardDiff.jacobian(x -> Fdet(x, p), x))\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We can now instantiate the model","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"N = 300\nlx = 2pi\nX = LinRange(0, lx, N)\n\nD, Δ = DiffOp(N, lx)\n_ν1 = 0.0075\n# model parameters\npar_det = (N = N, q = 0.5, α = 0.3, up = 0.0, uc = 1.1, s = 3.5, k = 1., ϵ = 0.15, r = 5.0, ν1 = _ν1, ν2 = _ν1, Δ = blockdiag(Δ, Δ), D = D, Db = blockdiag(D, D))\n\n# initial conditions\nu0 = 0.5ones(N)\nλ0 = 0.5ones(N)\nU0 = vcat(u0, λ0)\nU0cons = vcat(copy(U0), 1.)\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/#Jacobian-with-sparsity-detection","page":"🟠 Detonation engine","title":"Jacobian with sparsity detection","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"Writing the jacobian explicitly is cumbersome. We rely on automatic differentiation to get the sparse jacobian.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"# improved jacobian with sparse coloring\nusing SparseArrays, SparseDiffTools, Test\nconst L1 = copy(Jdet(rand(2N), par_det))\nconst colors = matrix_colors(L1)\nfunction JlgvfColorsAD(J, u, p, colors)\n\tSparseDiffTools.forwarddiff_color_jacobian!(J, (out, x) -> out .= Fdet(x,p), u, colorvec = colors)\n\tJ\nend\nJdetAD(x,p) = JlgvfColorsAD(L1, x, p, colors)\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We are now ready to compute the bifurcation of the trivial (constant in space) solution:","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"# bifurcation problem\nprob = BifurcationProblem(Fdet, U0, setproperties(par_det; q = 0.5), (@lens _.up); J = JdetAD,\n\tplot_solution = (x, p; k...) -> plotsol!(x; k...),\n\trecord_from_solution = (x, p) -> (u∞ = norminf(x[1:N]), n2 = norm(x)))\n\nprob = re_make(prob, params = (@set par_det.up = 0.56))\n\n# iterative eigen solver\neig = EigArpack(0.2, :LM, tol = 1e-13, v0 = rand(2N))\neig = EigArnoldiMethod(sigma=0.2, which = BifurcationKit.LM(),x₀ = rand(2N ))\n\n# newton options\noptnew = NewtonPar(verbose = true, eigsolver = eig)\nsolhomo = newton(prob, optnew; normN = norminf)\noptcont = ContinuationPar(newton_options = setproperties(optnew, verbose = false),\n\tdetect_bifurcation = 3, nev = 50, n_inversion = 8, max_bisection_steps = 25,\n\tdsmax = 0.01, ds = 0.01, p_max = 1.4, max_steps = 1000, plot_every_step = 50)\n\nbr = continuation(\n\t\tre_make(prob, params = (@set par_det.q = 0.5), u0 = solhomo.u),\n\t\tPALC(), optcont; plot = true)\nScene = title!(\"\")","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"br","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We have detected 6 Hopf bifurcations. We now study the periodic orbits branching from them.","category":"page"},{"location":"tutorials/detonationEngine/#Computing-the-branches-of-Travelling-waves","page":"🟠 Detonation engine","title":"Computing the branches of Travelling waves","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"The periodic orbits emanating from the Hopf points look like travelling waves. This is intuitive because the equation is mostly advective as the diffusion coefficients nu_i are small. We will thus seek for travelling waves instead of periodic orbits. The advantage is that the possible Neimark-Sacker bifurcation is transformed into a regular Hopf one which allows the study of modulated travelling waves.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"As we will do the same thing 3 times, we bundle the procedure in functions. We first use the regular Hopf normal form to create a guess for the travelling wave:","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"function getGuess(br, nb; δp = 0.005)\n\tnf = get_normal_form(br, nb; verbose = false)\n\tpred = predictor(nf, δp)\n\treturn pred.p, pred.orbit(0)\nend\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"Using this guess, we can continue the travelling wave as function of a parameter. Note that in the following code, a generalized eigensolver is automatically created during the call to continuation which properly computes the stability of the wave.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"function computeBranch(br, nb; δp = 0.005, max_steps = 190)\n\t_p, sol = getGuess(br, nb)\n\t# travelling wave problem\n\tprobTW = TWProblem(\n\t\tre_make(br.prob, params = setproperties(getparams(br); up = _p)),\n\t\tgetparams(br).Db,\n\t\tcopy(sol),\n\t\tjacobian = :AutoDiff)\n\t# newton parameters with iterative eigen solver\n\t# eig = EigArnoldiMethod(sigma=0.2, which = BifurcationKit.LM(),x₀ = rand(2N ))\n\teig = EigArpack(nev = 10, which = :LM, sigma = 0.4)\n\toptn = NewtonPar(verbose = true, eigsolver = eig)\n\t# continuation parameters\n\topt_cont_br = ContinuationPar(p_min = 0.1, p_max = 1.3, newton_options = optn, ds= -0.001, dsmax = 0.01, plot_every_step = 5, detect_bifurcation = 3, nev = 10, max_steps = max_steps)\n\t# we build a guess for the travelling wave with speed -0.9\n\ttwguess = vcat(sol, -0.9)\n\tbr_wave = continuation(probTW, twguess, PALC(), opt_cont_br;\n\t\tverbosity = 3, plot = true, bothside = true,\n\t\trecord_from_solution = (x, p) -> (u∞ = maximum(x[1:N]), s = x[end], amp = amplitude(x[1:N])),\n\t\tplot_solution = (x, p; k...) -> (plotsol!(x[1:end-1];k...);plot!(br,subplot=1, legend=false)),\n\t\tcallback_newton = BK.cbMaxNorm(1e2),\n\t\tfinalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\t\tamplitude(z.u[N+1:2N]) > 0.01\n\t\tend,\n\t\t)\nend\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We can try this continuation as follows","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"amplitude(x) = maximum(x) - minimum(x)\nbr_wave = computeBranch(br, 1; max_steps = 10)\nScene = title!(\"\")","category":"page"},{"location":"tutorials/detonationEngine/#Building-the-full-diagram","page":"🟠 Detonation engine","title":"Building the full diagram","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"branches = [computeBranch(br, i) for i in 1:3]\nplot(br, branches..., legend=:topleft, xlims = (0.5, 1.25), ylims=(0.5, 2.3))","category":"page"},{"location":"tutorials/detonationEngine/#References","page":"🟠 Detonation engine","title":"References","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"[Koch]: Koch, James, Mitsuru Kurosaka, Carl Knowlen, and J. Nathan Kutz. “Multi-Scale Physics of Rotating Detonation Engines: Autosolitons and Modulational Instabilities.” ArXiv:2003.06655 [Nlin, Physics:Physics], March 14, 2020. http://arxiv.org/abs/2003.06655.","category":"page"},{"location":"tutorials/tutorials1/#temperature","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"","category":"section"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Pages = [\"tutorials1.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"This is a classical example from the Trilinos library.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"This is a simple example in which we aim at solving Delta T+alpha N(Tbeta)=0 with boundary conditions T(0) = T(1)=beta. This example is coded in examples/chan.jl. We start with some imports:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"using BifurcationKit, LinearAlgebra, Plots, Parameters\nconst BK = BifurcationKit\n\nN(x; a = 0.5, b = 0.01) = 1 + (x + a*x^2)/(1 + b*x^2)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We then write our functional:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"function F_chan(x, p)\n\t@unpack α, β = p\n\tf = similar(x)\n\tn = length(x)\n\tf[1] = x[1] - β\n\tf[n] = x[n] - β\n\tfor i=2:n-1\n\t\tf[i] = (x[i-1] - 2 * x[i] + x[i+1]) * (n-1)^2 + α * N(x[i], b = β)\n\tend\n\treturn f\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We want to call a Newton solver. We first need an initial guess:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"n = 101\nsol0 = [(i-1)*(n-i)/n^2+0.1 for i=1:n]\n\n# set of parameters\npar = (α = 3.3, β = 0.01)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Finally, we need to provide some parameters for the Newton iterations. This is done by calling","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"optnewton = NewtonPar(tol = 1e-11, verbose = true)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We call the Newton solver:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"prob = BifurcationProblem(F_chan, sol0, par, (@lens _.α),\n\t# function to plot the solution\n\tplot_solution = (x, p; k...) -> plot!(x; ylabel=\"solution\", label=\"\", k...))\nsol = newton(prob, @set optnewton.verbose=false) # hide\nsol = @time newton( prob, optnewton)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can perform numerical continuation w.r.t. the parameter alpha. This time, we need to provide additional parameters, but now for the continuation method:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"optcont = ContinuationPar(dsmin = 0.01, dsmax = 0.2, ds= 0.1, p_min = 0., p_max = 4.2,\n\tnewton_options = NewtonPar(max_iterations = 10, tol = 1e-9))\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Next, we call the continuation routine as follows.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"br = continuation(prob, PALC(), optcont; plot = true)\nnothing #hide\t\t","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"The parameter axis lens = @lens _.α is used to extract the component of par corresponding to α. Internally, it is used as get(par, lens) which returns 3.3.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"You should see","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"scene = title!(\"\") #hide\t\t","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"The left figure is the norm of the solution as function of the parameter p=alpha, the y-axis can be changed by passing a different recordFromSolution to BifurcationProblem. The top right figure is the value of alpha as function of the iteration number. The bottom right is the solution for the current value of the parameter. This last plot can be modified by changing the argument plotSolution to BifurcationProblem.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"note: Bif. point detection\nTwo Fold points were detected. This can be seen by looking at br.specialpoint, by the black\tdots on the continuation plots when doing plot(br, plotfold=true) or by typing br in the REPL. Note that the bifurcation points are located in br.specialpoint.","category":"page"},{"location":"tutorials/tutorials1/#Continuation-of-Fold-points","page":"🟡 Temperature model (codim 2)","title":"Continuation of Fold points","text":"","category":"section"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We get a summary of the branch by doing","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"br","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can take the first Fold point, which has been guessed during the previous continuation run and locate it precisely. However, this only works well when the jacobian is computed analytically. We use automatic differentiation for that","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"# index of the Fold bifurcation point in br.specialpoint\nindfold = 2\n\noutfold = newton(\n\t#index of the fold point\n\tbr, indfold)\nBK.converged(outfold) && printstyled(color=:red, \"--> We found a Fold Point at α = \", outfold.u.p, \", β = 0.01, from \", br.specialpoint[indfold].param,\"\\n\")","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can finally continue this fold point in the plane (α β) by performing a Fold Point continuation. In the present case, we find a Cusp point.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"tip: Tip\nWe don't need to call newton first in order to use continuation for the codim 2 curve of bifurcation points.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"outfoldco = continuation(br, indfold,\n\t# second parameter axis to use for codim 2 curve\n\t(@lens _.β),\n\t# we disable the computation of eigenvalues, it makes little sense here\n\tContinuationPar(optcont, detect_bifurcation = 0))\nscene = plot(outfoldco, plotfold = true, legend = :bottomright)","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"tip: Tip\nThe performances for computing the curve of Fold is not that great. It is because we use the default solver tailored for ODE. If you pass jacobian_ma = :minaug to the last continuation call, you should see a great improvement in performances.","category":"page"},{"location":"tutorials/tutorials1/#Using-GMRES-or-another-linear-solver","page":"🟡 Temperature model (codim 2)","title":"Using GMRES or another linear solver","text":"","category":"section"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We continue the previous example but now using Matrix Free methods. The user can pass its own solver by implementing a version of LinearSolver. Some linear solvers have been implemented from KrylovKit.jl and IterativeSolvers.jl (see Linear solvers (LS) for more information), we can use them here. Note that we can also use preconditioners as shown below. The same functionality is present for the eigensolver.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"# derivative of N\ndN(x; a = 0.5, b = 0.01) = (1-b*x^2+2*a*x)/(1+b*x^2)^2\n\n# Matrix Free version of the differential of F_chan\n# Very easy to write since we have F_chan.\n# We could use Automatic Differentiation as well\nfunction dF_chan(x, dx, p)\n\t@unpack α, β = p\n\tout = similar(x)\n\tn = length(x)\n\tout[1] = dx[1]\n\tout[n] = dx[n]\n\tfor i=2:n-1\n\t\tout[i] = (dx[i-1] - 2 * dx[i] + dx[i+1]) * (n-1)^2 + α * dN(x[i], b = β) * dx[i]\n\tend\n\treturn out\nend\n\n# we create a new linear solver\nls = GMRESKrylovKit(dim = 100)\n\n# and pass it to the newton parameters\noptnewton_mf = NewtonPar(verbose = true, linsolver = ls, tol = 1e-10)\n\n# we change the problem with the new jacobian\nprob = re_make(prob;\n\t# we pass the differential a x,\n\t# which is a linear operator in dx\n\tJ = (x, p) -> (dx -> dF_chan(x, dx, p))\n\t)\n\n# we can then call the newton solver\nout_mf = @time newton(prob,\toptnewton_mf)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can improve this computation, i.e. reduce the number of Linear-Iterations, by using a preconditioner","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"using SparseArrays\n\n# define preconditioner which is basically Δ\nP = spdiagm(0 => -2 * (n-1)^2 * ones(n), -1 => (n-1)^2 * ones(n-1), 1 => (n-1)^2 * ones(n-1))\nP[1,1:2] .= [1, 0.];P[end,end-1:end] .= [0, 1.]\n\n# define gmres solver with left preconditioner\nls = GMRESIterativeSolvers(reltol = 1e-4, N = length(sol.u), restart = 10, maxiter = 10, Pl = lu(P))\n\toptnewton_mf = NewtonPar(verbose = true, linsolver = ls, tol = 1e-10)\n\tout_mf = @time newton(prob, optnewton_mf)\nnothing #hide","category":"page"},{"location":"PALC/#Pseudo-arclength-continuation","page":"PALC","title":"Pseudo arclength continuation","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"This is one of the various continuation methods implemented in BifurcationKit.jl. It is set by the option PALC(tangent = Bordered()) or PALC(tangent = Secant()) in continuation. See also PALC for more information.","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"For solving","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"mathbb R^nni F(xp) = 0 quadtagE","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"using a Newton algorithm, we miss an equation. The simplest way is to select an hyperplane in the space mathbb R^ntimes mathbb R passing through (x_0p_0):","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"N(x p) = fracthetan langle x - x_0 dx_0rangle + (1 - theta)cdot(p - p_0)cdot dp_0 - ds = 0tagN","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"with thetain01 and where ds is the pseudo arclength (see [Keller]).","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"warning: Parameter `θ`\nThe parameter θ in the struct ContinuationPar is very important. It should be tuned for the continuation to work properly especially in the case of large problems where the langle x - x_0 dx_0rangle component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint N involves the term 1-θ.","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"(Image: )","category":"page"},{"location":"PALC/#Predictor","page":"PALC","title":"Predictor","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"The possible predictors are listed in Predictors - Correctors.","category":"page"},{"location":"PALC/#Corrector","page":"PALC","title":"Corrector","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"The corrector is the newton algorithm for finding the roots (xp) of","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"beginbmatrix F(xp) \tN(xp)endbmatrix = 0tagPALC","category":"page"},{"location":"PALC/#Linear-Algebra","page":"PALC","title":"Linear Algebra","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"Let us discuss more about the norm and dot product. First, the option normC continuation specifies the norm used to evaluate the residual in the following way: max(normC(F(xp)) N(xp))tol. It is thus used as a stopping criterion for the corrector. The dot product (resp. norm) used in N and in the (iterative) linear solvers is LinearAlgebra.dot (resp. LinearAlgebra.norm). It can be changed by importing these functions and redefining it. Note that by default, the mathcal L^2 norm is used. These details are important because of the constraint N which incorporates the factor length. For some custom composite type implementing a Vector space, the dot product could already incorporates the length factor in which case you should either redefine the dot product or change theta.","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"The linear solver for the linear problem associated to (PALC) is set by the option linear_algo in continuation: it is one of Bordered linear solvers (BLS).","category":"page"},{"location":"PALC/#Dot-product","page":"PALC","title":"Dot product","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"In the constraint N above, the scalar product is in fact saved in BifurcationKit.jl as dotp(x,y) -> dot(x,y)/length(y). This is used in the bordered linear solvers associated to PALC. If you want to use your own dot product, you can pass","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"dotPALC = BK.DotTheta(mydot),","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"to continuation. Additionally, you may want to provide the linear operator P such that mydot(x,y) = dot(x, A*y), especially if you intend too use the linear solver MatrixBLS. We refer to BifurcationKit.DotTheta for more details.","category":"page"},{"location":"PALC/#Step-size-control","page":"PALC","title":"Step size control","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"Each time the corrector fails, the step size ds is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.","category":"page"},{"location":"PALC/#References","page":"PALC","title":"References","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"[Keller]: Keller, Herbert B. Lectures on Numerical Methods in Bifurcation Problems. Springer, 1988","category":"page"},{"location":"iterator/#Iterator-Interface","page":"Iterator Interface","title":"Iterator Interface","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The iterator interface gives the possibility of stepping through the numerical steps of the continuation procedure. It thus allows to inject custom monitoring function (saving, plotting, bifurcation detection, ...) at will and during the continuation run. In short, it allows to completely re-write the continuation algorithm as one sees fit and this, in a straightforward manner.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The general method continuation is built upon this iterator interface and we refer to the source code for a complete example of use.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"warning: Warning\nThe iterator provided below does not compute eigenvalues nor perform bifurcations detection. ","category":"page"},{"location":"iterator/#Initialization","page":"Iterator Interface","title":"Initialization","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"More information about iterators can be found on the page of julialang.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The interface is set by defining an iterator, pretty much in the same way one calls continuation:","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"iter = ContIterable(prob, alg, opts; kwargs...)","category":"page"},{"location":"iterator/#Stepping","page":"Iterator Interface","title":"Stepping","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"Once an iterator iter has been defined, one can step through the numerical continuation using a for loop:","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"for state in iter\n\tprintln(\"Continuation step = \", state.step)\nend","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The state::ContState has the following description. It is a mutable object which holds the current state of the continuation procedure from which one can step to the next state.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The for loop stops when done(iter, state) returns false. The condition which is implemented is basically that the number of iterations should be smaller than maxIter, that the parameters should be in (p_min, p_max)...","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"ContState","category":"page"},{"location":"iterator/#BifurcationKit.ContState","page":"Iterator Interface","title":"BifurcationKit.ContState","text":"state = ContState(ds = 1e-4,...)\n\nReturns a variable containing the state of the continuation procedure. The fields are meant to change during the continuation procedure.\n\nArguments\n\nz_pred current solution on the branch\nconverged Boolean for newton correction\nτ tangent predictor\nz previous solution\nitnewton Number of newton iteration (in corrector)\nstep current continuation step\nds step size\nstopcontinuation Boolean to stop continuation\n\nUseful functions\n\ncopy(state) returns a copy of state\ncopyto!(dest, state) returns a copy of state\ngetsolution(state) returns the current solution (x, p)\ngetx(state) returns the x component of the current solution\ngetp(state) returns the p component of the current solution\ngetpreviousp(state) returns the p component of the previous solution\nis_stable(state) whether the current state is stable\n\n\n\n\n\n","category":"type"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"tip: continuation\nYou can also call continuation(iter) to have access to the regular continuation method used throughout the tutorials.","category":"page"},{"location":"iterator/#Basic-example","page":"Iterator Interface","title":"Basic example","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"We show a quick and simple example of use. Note that it is not very optimized because of the use of global variables.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"using BifurcationKit, Plots\nconst BK = BifurcationKit\n\nk = 2\n\n# functional we want to study\nF(x, p) = (@. p + x - x^(k+1)/(k+1))\n\n# bifurcation problem\nprob = BifurcationProblem(F, [0.8], 1., (@lens _))\n\n# parameters for the continuation\nopts = ContinuationPar(dsmax = 0.1, dsmin = 1e-3, ds = -0.001, max_steps = 130, p_min = -3., p_max = 3., newton_options = NewtonPar(tol = 1e-8))\n\n# we define an iterator to hold the continuation routine\niter = BK.ContIterable(prob, PALC(), opts; verbosity = 2)\n\nresp = Float64[]\nresx = Float64[]\n\n# this is the PALC algorithm\nfor state in iter\n\t# we save the current solution on the branch\n\tpush!(resx, getx(state)[1])\n\tpush!(resp, getp(state))\nend\n\n# plot the result\nplot(resp, resx; label = \"\", xlabel = \"p\")","category":"page"},{"location":"iterator/#Additional-information","page":"Iterator Interface","title":"Additional information","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"If you want to customize the iterator to your needs, perhaps the best source of inspiration is the code of the function continuation!(it::ContIterable, state::ContState, contRes::ContResult) where the iterator is used at its fullest. You will see how the eigen-elements and the stability are computed, how bifurcations are detected and how results are saved.","category":"page"},{"location":"tutorials/tutorials3/#brusauto","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Pages = [\"tutorials3.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"unknown: References\nThis example is taken from Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust, 1997.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We look at the Brusselator in 1d. The equations are as follows","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"beginaligned frac partial X partial t = frac D _ 1 l ^ 2 frac partial ^ 2 X partial z ^ 2 + X ^ 2 Y - ( β + 1 ) X + α frac partial Y partial t = frac D _ 2 l ^ 2 frac partial ^ 2 Y partial z ^ 2 + β X - X ^ 2 Y endaligned","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"with Dirichlet boundary conditions","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"beginarray l X ( t z = 0 ) = X ( t z = 1 ) = α Y ( t z = 0 ) = Y ( t z = 1 ) = β α endarray","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"These equations have been introduced to reproduce an oscillating chemical reaction. There is an obvious equilibrium (α β α). Here, we consider bifurcations with respect to the parameter l.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We start by writing the PDE","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"using Revise\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Setfield, Parameters\nconst BK = BifurcationKit\n\nf1(u, v) = u * u * v\n\nfunction Fbru!(f, x, p, t = 0)\n\t@unpack α, β, D1, D2, l = p\n\tn = div(length(x), 2)\n\th2 = 1.0 / n^2\n\tc1 = D1 / l^2 / h2\n\tc2 = D2 / l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\t# Dirichlet boundary conditions\n\tf[1] = c1 * (α\t - 2u[1] + u[2] ) + α - (β + 1) * u[1] + f1(u[1], v[1])\n\tf[end] = c2 * (v[n-1] - 2v[n] + β / α)\t\t\t + β * u[n] - f1(u[n], v[n])\n\n\tf[n] = c1 * (u[n-1] - 2u[n] + α ) + α - (β + 1) * u[n] + f1(u[n], v[n])\n\tf[n+1] = c2 * (β / α - 2v[1] + v[2])\t\t\t + β * u[1] - f1(u[1], v[1])\n\n\tfor i=2:n-1\n\t\t f[i] = c1 * (u[i-1] - 2u[i] + u[i+1]) + α - (β + 1) * u[i] + f1(u[i], v[i])\n\t\tf[n+i] = c2 * (v[i-1] - 2v[i] + v[i+1])\t\t\t + β * u[i] - f1(u[i], v[i])\n\tend\n\treturn f\nend\n\nFbru(x, p, t = 0) = Fbru!(similar(x), x, p, t)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"For computing periodic orbits, we will need a Sparse representation of the Jacobian:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"function Jbru_sp(x, p)\n\t@unpack α, β, D1, D2, l = p\n\t# compute the Jacobian using a sparse representation\n\tn = div(length(x), 2)\n\th = 1.0 / n; h2 = h*h\n\n\tc1 = D1 / p.l^2 / h2\n\tc2 = D2 / p.l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\tdiag = zeros(eltype(x), 2n)\n\tdiagp1 = zeros(eltype(x), 2n-1)\n\tdiagm1 = zeros(eltype(x), 2n-1)\n\n\tdiagpn = zeros(eltype(x), n)\n\tdiagmn = zeros(eltype(x), n)\n\n\t@. diagmn = β - 2 * u * v\n\t@. diagm1[1:n-1] = c1\n\t@. diagm1[n+1:end] = c2\n\n\t@. diag[1:n] = -2c1 - (β + 1) + 2 * u * v\n\t@. diag[n+1:2n] = -2c2 - u * u\n\n\t@. diagp1[1:n-1] = c1\n\t@. diagp1[n+1:end] = c2\n\n\t@. diagpn = u * u\n\treturn spdiagm(0 => diag, 1 => diagp1, -1 => diagm1, n => diagpn, -n => diagmn)\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"tip: Tip\nWe could have used DiffEqOperators.jl like for the Swift-Hohenberg tutorial instead of writing our laplacian ourselves.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Finally, it will prove useful to have access to the hessian and third derivative","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We shall now compute the equilibria and their stability.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"n = 300\n\n# parameters of the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\n\n# bifurcation problem\nprobBif = BK.BifurcationProblem(Fbru, sol0, par_bru, (@lens _.l);\n J = Jbru_sp,\n plot_solution = (x, p; kwargs...) -> (plotsol(x; label=\"\", kwargs... )),\n record_from_solution = (x, p) -> x[div(n,2)])\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"For the eigensolver, we use a Shift-Invert algorithm (see Eigen solvers (Eig))","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"eigls = EigArpack(1.1, :LM)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We continue the trivial equilibrium to find the Hopf points","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"opt_newton = NewtonPar(eigsolver = eigls, tol = 1e-9)\nopts_br_eq = ContinuationPar(dsmin = 0.001, dsmax = 0.01, ds = 0.001,\n\tp_max = 1.9, detect_bifurcation = 3, nev = 21,\n\tnewton_options = opt_newton, max_steps = 1000,\n\t# specific options for precise localization of Hopf points\n\tn_inversion = 6)\n\nbr = continuation(probBif, PALC(), opts_br_eq, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We obtain the following bifurcation diagram with 3 Hopf bifurcation points","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"scene = plot(br)","category":"page"},{"location":"tutorials/tutorials3/#Normal-form-computation","page":"🟡 1d Brusselator (automatic)","title":"Normal form computation","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We can compute the normal form of the Hopf points as follows","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"hopfpt = get_normal_form(br, 1)","category":"page"},{"location":"tutorials/tutorials3/#Continuation-of-Hopf-points","page":"🟡 1d Brusselator (automatic)","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We use the bifurcation points guesses located in br.specialpoint to turn them into precise bifurcation points. For the second one, we have","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# index of the Hopf point in br.specialpoint\nind_hopf = 2\n\n# newton iterations to compute the Hopf point\nhopfpoint = newton(br, ind_hopf; normN = norminf)\nBK.converged(hopfpoint) && printstyled(color=:red, \"--> We found a Hopf Point at l = \", hopfpoint.u.p[1], \", ω = \", hopfpoint.u.p[2], \", from l = \", br.specialpoint[ind_hopf].param, \"\\n\")","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now perform a Hopf continuation with respect to the parameters l, β","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"tip: Tip\nYou don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)\n\nbr_hopf = continuation(br, ind_hopf, (@lens _.β),\n\toptcdim2, verbosity = 2,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\tjacobian_ma = :minaug, # specific to large dimensions\n\tnormC = norminf)\n\nscene = plot(br_hopf) \t","category":"page"},{"location":"tutorials/tutorials3/#Computation-of-the-branch-of-periodic-orbits-(Finite-differences)","page":"🟡 1d Brusselator (automatic)","title":"Computation of the branch of periodic orbits (Finite differences)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now compute the bifurcated branches of periodic solutions from the Hopf points using Periodic orbits based on Trapezoidal rule. One has just to pass a PeriodicOrbitTrapProblem.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We start by providing a linear solver and some options for the continuation to work","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# automatic branch switching from Hopf point\nopt_po = NewtonPar(tol = 1e-10, verbose = true, max_iterations = 15)\nopts_po_cont = ContinuationPar(dsmin = 0.001,\n\t\tdsmax = 0.04, ds = 0.01,\n\t\tp_max = 2.2,\n\t\tmax_steps = 20,\n\t\tnewton_options = opt_po,\n\t\tsave_sol_every_step = 2,\n\t\tplot_every_step = 1,\n\t\tnev = 11,\n\t\ttol_stability = 1e-6,\n\t\tdetect_bifurcation = 3,\n\t\tdsmin_bisection = 1e-6,\n\t\tmax_bisection_steps = 15,\n\t\tn_inversion = 4)\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# number of time slices for the periodic orbit\nM = 51\nprobFD = PeriodicOrbitTrapProblem(M = M;\n # specific method for solving linear system\n # of Periodic orbits with trapeze method\n # You could use the default one :FullLU (slower here)\n jacobian = :BorderedSparseInplace)\nbr_po = continuation(\n\t# arguments for branch switching from the first\n\t# Hopf bifurcation point\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont, probFD;\n\t# OPTIONAL parameters\n\t# we want to jump on the new branch at phopf + δp\n\t# ampfactor is a factor to increase the amplitude of the guess\n\tδp = 0.01, ampfactor = 1,\n\t# regular options for continuation\n\tverbosity = 3,\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...),\n\tnormC = norminf)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Using the above call, it is very easy to find the first branches:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We note that there are several branch points (blue points) on the above diagram. This means that there are additional branches in the neighborhood of these points. We now turn to automatic branch switching on these branches. This functionality, as we shall see, is only provided for PeriodicOrbitTrapProblem.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Let's say we want to branch from the first branch point of the first curve pink branch. The syntax is very similar to the previous one:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"br_po2 = continuation(\n\t# arguments for branch switching\n\tbr_po, 1,\n\t# arguments for continuation\n\topts_po_cont;\n\tampfactor = 1., δp = 0.01,\n\tverbosity = 3,\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"It is now straightforward to get the following diagram","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3/#Computation-of-the-branch-of-periodic-orbits-(Standard-Shooting)","page":"🟡 1d Brusselator (automatic)","title":"Computation of the branch of periodic orbits (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Note that what follows is not really optimized on the DifferentialEquations.jl side. Indeed, we do not use automatic differentiation, we do not pass the sparsity pattern, ...","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now turn to a different method based on the flow of the Brusselator. To compute this flow (time stepper), we need to be able to solve the differential equation (actually a PDE) associated to the vector field Fbru. We will show how to do this with an implicit method Rodas4P from DifferentialEquations.jl. Note that the user can pass its own time stepper but for convenience, we use the ones in DifferentialEquations.jl. More information regarding the shooting method is contained in Periodic orbits based on the shooting method.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We then recompute the locus of the Hopf bifurcation points using the same method as above.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"n = 100\n\n# different parameters to define the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\nprobBif = re_make(probBif, u0 = sol0)\n\neigls = EigArpack(1.1, :LM)\nopts_br_eq = ContinuationPar(dsmin = 0.001,\n\t\tdsmax = 0.00615, ds = 0.0061,\n\t\tp_max = 1.9,\n\t\tdetect_bifurcation = 3,\n\t\tnev = 21,\n\t\tplot_every_step = 50,\n\t\tnewton_options = NewtonPar(eigsolver = eigls,\n\t\t\ttol = 1e-9), max_steps = 200)\n\nbr = continuation(probBif, PALC(), opts_br_eq, verbosity = 0, plot = false, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We need to build a problem which encodes the Shooting functional. This done as follows where we first create the time stepper:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"using DifferentialEquations, DiffEqOperators\n\nFOde(f, x, p, t) = Fbru!(f, x, p, t)\n\nu0 = sol0 .+ 0.01 .* rand(2n)\n\n# we pass our jacobian function to increase performances\n# an inplace jacobian would be favoured\nvf = ODEFunction(FOde, jac = (J,u,p,t) -> J .= Jbru_sp(u, p), jac_prototype = Jbru_sp(u0, par_bru))\n\n# this is the ODE time stepper when used with `solve`\nprob = ODEProblem(vf, u0, (0., 1000.), par_bru; abstol = 1e-10, reltol = 1e-8)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"tip: Performance\nYou can really speed this up by using the improved ODEProblemusing SparseDiffTools, SparseArrays\njac_prototype = Jbru_sp(ones(2n), par_bru)\njac_prototype.nzval .= ones(length(jac_prototype.nzval))\n_colors = matrix_colors(jac_prototype)\nvf = ODEFunction(FOde; jac_prototype = jac_prototype, colorvec = _colors)\nprobsundials = ODEProblem(vf, u0, (0.0, 520.), par_bru) # gives 0.22s","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We are now ready to call the automatic branch switching. Note how similar it is to the previous section based on finite differences. This case is more deeply studied in the tutorial 1d Brusselator (advanced user). We use a parallel Shooting.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# linear solvers\nls = GMRESIterativeSolvers(reltol = 1e-7, maxiter = 100)\neig = EigKrylovKit(tol= 1e-12, x₀ = rand(2n), dim = 40)\n# newton parameters\noptn_po = NewtonPar(verbose = true, tol = 1e-7, max_iterations = 25, linsolver = ls, eigsolver = eig)\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.03, ds= 0.01, p_max = 2.5, max_steps = 10,\n\tnewton_options = optn_po, nev = 15, tol_stability = 1e-3,\n\tdetect_bifurcation = 0, plot_every_step = 2)\n\nMt = 2 # number of shooting sections\nbr_po = continuation(\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n\t# this is where we tell that we want Parallel Standard Shooting\n\tShootingProblem(Mt, prob, Rodas4P(), abstol = 1e-10, reltol = 1e-8, parallel = true, jacobian = BK.FiniteDifferencesMF());\n\tampfactor = 1.0, δp = 0.0075,\n\t# the next option is not necessary\n\t# it speeds up the newton iterations\n\t# by combining the linear solves of the bordered linear system\n\tlinear_algo = MatrixFreeBLS(@set ls.N = 2+2n*Mt),\n\tverbosity = 3,\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], Mt; kwargs...),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"and you should see","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3/#Computation-of-the-branch-of-periodic-orbits-(Poincaré-Shooting)","page":"🟡 1d Brusselator (automatic)","title":"Computation of the branch of periodic orbits (Poincaré Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now turn to another Shooting method, namely the Poincaré one. We can provide this method thanks to the unique functionalities of DifferentialEquations.jl. More information is provided at PoincareShootingProblem and Periodic orbits based on the shooting method but basically, it is a shooting method between Poincaré sections Sigma_i (along the orbit) defined by hyperplanes. As a consequence, the dimension of the unknowns is M_shcdot(N-1) where N is the dimension of the phase space. Indeed, each time slice lives in an hyperplane Sigma_i. Additionally, the period T is not an unknown of the method but rather a by-product. However, the method requires the time stepper to find when the flow hits an hyperplane Sigma_i, something called event detection.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We show how to use this method, the code is very similar to the case of the Parallel Standard Shooting:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# linear solvers\nls = GMRESIterativeSolvers(reltol = 1e-8, maxiter = 100)\neig = EigKrylovKit(tol= 1e-12, x₀ = rand(2n-1), dim = 50)\n# newton parameters\noptn_po = NewtonPar(verbose = true, tol = 1e-7, max_iterations = 15, linsolver = ls, eigsolver = eig)\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.03, ds= 0.005, p_max = 2.5, max_steps = 100, newton_options = optn_po, nev = 10, tol_stability = 1e-5, detect_bifurcation = 3, plot_every_step = 2)\n\n# number of time slices\nMt = 2\nbr_po = continuation(\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n PoincareShootingProblem(Mt, prob, Rodas4P(); abstol = 1e-10, reltol = 1e-8,\n jacobian = BK.FiniteDifferencesMF());\n\t# the next option is not necessary\n\t# it speeds up the newton iterations\n\t# by combining the linear solves of the bordered linear system\n\tlinear_algo = MatrixFreeBLS(@set ls.N = (2n-1)*Mt+1),\n\tampfactor = 1.0, δp = 0.005,\n\tverbosity = 3, plot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], Mt; kwargs...),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"and you should see:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"intro-abs/#Branch-switching-page","page":"Introduction","title":"Branch switching","text":"","category":"section"},{"location":"intro-abs/","page":"Introduction","title":"Introduction","text":"The precise definition of the methods are given in Branch switching (branch point) and Branch switching (Hopf point).","category":"page"},{"location":"intro-abs/#Summary-of-branching-procedures","page":"Introduction","title":"Summary of branching procedures","text":"","category":"section"},{"location":"intro-abs/","page":"Introduction","title":"Introduction","text":"We collect in the following table the list of automatic branch switching (aBS) functions. Their detailed explanation follows in this page.","category":"page"},{"location":"intro-abs/","page":"Introduction","title":"Introduction","text":"function ind-th bif. point Type T description\ncontinuation(br::ContResult{T}, ind::Int; kw...) :bp, :nd EquilibriumCont aBS from equilibria to equilibria\ncontinuation(br::ContResult{T}, ind::Int, lens2::Lens; kw...) :bp, :hopf EquilibriumCont Fold/Hopf continuation w.r.t. parameters getlens(br) and lens2\ncontinuation(br::ContResult{T}, ind::Int; kw...) :bt,:zh,:hh FoldCont,HopfCont switch to Fold/Hopf continuation from Hopf/Fold w.r.t. parameters of codim 2 br\ncontinuation(br::ContResult{T}, ind_hopf::Int, ::ContinuationPar, prob::AbstractPeriodicOrbitProblem) :hopf EquilibriumCont Branch switching from Hopf point to periodic orbits\ncontinuation(br::ContResult{T}, ind::Int, kw...) :bp,:pd PeriodicOrbitCont Branch switching from Branch / Period-doubling point of periodic orbits to curve of periodic orbits\ncontinuation(br::ContResult{T}, ind::Int, kw...) :gh,:zh,:hh TwoParamCont Branch switching from Bautin / Zero-Hopf/ Hopf-Hopf point to curve of Fold/NS of periodic orbits","category":"page"},{"location":"cusp/#Normal-form-of-the-Cusp-bifurcation","page":"Cusp","title":"Normal form of the Cusp bifurcation","text":"","category":"section"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"We follow the paper[Kuznetsov] and consider a Cauchy problem","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"dot x=mathbf F(xp)","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"mathbf L q=0 quad mathbf L^T p=0 quad langle p qrangle=1","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"Under some conditions, x(t)approx x_0+ w(t)q where w satisfies the normal form:","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"dotw=c w^3+Oleft(w^4right)tagE","category":"page"},{"location":"cusp/#Normal-form-computation","page":"Cusp","title":"Normal form computation","text":"","category":"section"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Cusp.","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"cusp/#References","page":"Cusp","title":"References","text":"","category":"section"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"ANM/#Asymptotic-numerical-method-(ANM)","page":"ANM","title":"Asymptotic numerical method (ANM)","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"warning: Work in progress\nAutomatic branch switching is being tested, it will be available soon.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"warning: Dimensions\nThis is a method for small dimensions, less than several thousands.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"To access this algorithm, you have to use the package AsymptoticNumericalMethod.jl ","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"The method [Rubbert],[Charpentier] seeks a Taylor approximation of the solutions of","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"mathbf F(Xp)=0inmathbb R^n","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"where Xinmathbb R^n pinmathbb R. The solution is found by solving","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"F(x(s)p(s))= 0","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"langle x(s)-x(0)fracpartial upartial s(0)rangle + (p(s)-p(0))fracpartial ppartial s(0) = s","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"where","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"x(s)=sumlimits_k=0^K x_ks^kquad p(s)=sumlimits_k=0^K p_ks^k","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"for some user passed K0. It gives","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"F(x(s)p(s)) = sumlimits_k=0^K F_ks^k+hot","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"from which we deduce the equations F_k=0. We then find:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"F_1 x_1=Id p_1=1(x_kp_k) = -F_kx_k=0p_k=0","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"The validity range of the solution can be estimated by","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"r_K = left(fracepsilonlvertlvert F_Klvertlvertright)^1K","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"This allows to iterate and find a sequence of series which spans the parameter range.","category":"page"},{"location":"ANM/#Implementation","page":"ANM","title":"Implementation","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"The method is based on the package TaylorSeries.jl which makes it easy to manipulate Taylor series based on Automatic Differentiation.","category":"page"},{"location":"ANM/#Method","page":"ANM","title":"Method","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"See AsymptoticNumericalMethod.ANM for more information.","category":"page"},{"location":"ANM/#Example","page":"ANM","title":"Example","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"We provide an example of use. We define a BifurcationProblem as usual and pass the continuation algorithm ANM.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"using AsymptoticNumericalMethod, Plots, Parameters, Setfield\nusing LinearAlgebra: norm\nusing BifurcationKit\nconst BK = BifurcationKit\n\nnorminf(x) = norm(x, Inf)\n\nfunction F(x, p)\n\t@unpack α = p\n\tf = similar(x)\n\n\tf[1] = (-2x[1]+x[2]) + α * exp(x[1])\n\tf[2] = ( x[1]-2x[2]) + α * exp(x[2])\n\n\treturn f\nend\n\nsol0 = zeros(2)\npar = (α = 0.0, )\nprob = BifurcationProblem(F, sol0, par, (@lens _.α); record_from_solution = (x,p) -> norminf(x))","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"optanm = ContinuationPar(dsmin = 0.01, dsmax = 0.15, detect_bifurcation = 3, ds= 0.01, newton_options = NewtonPar(tol = 1e-9, verbose = false), n_inversion = 6, max_bisection_steps = 15, max_steps = 15, )\n\nbranm = continuation(prob, ANM(20, 1e-8), optanm, normC = norminf, verbosity = 2)","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"You can plot the result as usual:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"plot(branm)","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"You can also show the radius of convergence of each series:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"plot(branm, plotseries = true)","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"Finally, for each series, we ca evaluate the residual norm:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"plot()\nfor ii in eachindex(branm.polU)\n\ts = LinRange(-0*branm.radius[ii], branm.radius[ii], 20)\n\tplot!([branm.polp[ii].(s)], [norminf(F(branm.polU[ii](_s), BK.setparam(prob,branm.polp[ii](_s)))) for _s in s], legend = false, linewidth=5)#, marker=:d)\nend\ntitle!(\"\")","category":"page"},{"location":"ANM/#References","page":"ANM","title":"References","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"[Charpentier]: Charpentier, Isabelle, Bruno Cochelin, and Komlanvi Lampoh. “Diamanlab - An Interactive Taylor-Based Continuation Tool in MATLAB,” n.d., 12.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"[Rubbert]: Rubbert, Lennart, Isabelle Charpentier, Simon Henein, and Pierre Renaud. “Higher-Order Continuation Method for the Rigid-Body Kinematic Design of Compliant Mechanisms”, n.d., 18.","category":"page"},{"location":"ns/#Neimark-Sacker-point","page":"Neimarck-Sacker","title":"Neimark-Sacker point","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"Pages = [\"ns.md\"]\nDepth = 2","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"At a Neimark-Sacker (NS) bifurcation of a periodic orbit gamma (with period T) for parameter value p_0 for the Cauchy problem ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"fracdudt=F(up)tagE","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"the eigenvalues (Floquet coefficients) of the monodromy operator mathcal M=Y(T) solution to","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"fracdYdt=A(t)Y(t) Y(0)=I_n","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"contain the eigenvalues e^pm i theta with theta and ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"e^i q theta-1 neq 0 quad q=1234 text (no strong resonances) ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"There are two ways to compute the normal form of this bifurcation","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"using the Poincaré return map [Kuznetsov]\nusing the method of [Iooss], see also [Kuz2]","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"You can obtain the normal form of a NS bifurcation using ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"pd = get_normal_form(br, ind; prm = false)","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where prm indicates whether you want to use the method based on Poincaré return map (PRM) or the one based on Iooss method.","category":"page"},{"location":"ns/#Normal-form-based-on-Poincaré-return-map","page":"Neimarck-Sacker","title":"Normal form based on Poincaré return map","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"Given a transversal section Sigma to gamma at gamma(0), the Poincaré return map mathcal P associates to each point xinSigma close to gamma(0) the first point mathcal P(xp)inSigma where the orbit of (E) with initial condition x intersects again Sigma at mathcal P(xp). Hence, the discrete map x_n+1=mathcal P(x_np) has normal form","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"z_n+1 = z_ne^itheta(1+dz_n^2)","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where[Kuz2]","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"d=frac12 e^-i thetaleftlangle v^* mathcalC(v v barv)+2 mathcalBleft(vleft(I_n-1-mathcalAright)^-1 mathcalB(v barv)right)+mathcalBleft(barvleft(e^2 i theta I_n-1-mathcalAright)^-1 mathcalB(v v)right)rightrangle","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where mathcal C=d^3mathcal P(gamma(0)), mathcal B = d^2mathcal P(gamma(0)) and mathcal A = dmathcal P(gamma(0)). Also:","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"mathcalA v=e^i theta v mathcalA^mathrmT v^*=e^-i theta v^* text and leftlangle v^* vrightrangle=1","category":"page"},{"location":"ns/#Normal-form-based-on-Iooss-method","page":"Neimarck-Sacker","title":"Normal form based on Iooss method","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"This is based on [Iooss],[Kuz2]. Suppose that the T periodic orbit gamma(tau) has a Neimark-Sacker bifurcation for a parameter value p_0. We also assume that there are no strong resonances. Locally, the orbits can be represented by ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"x(tau) = gamma(tau)+Q_0(tau)xi+Phi(tau xi)","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"leftbeginaligned\nfracd taud t =1+axi^2+cdots \nfracd xid t =fraci thetaT xi+d xixi^2+cdots\nendalignedright","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"with center manifold correction Phi(tau xi) being T periodic in tau and Q_0(tau) is the Floquet operator.","category":"page"},{"location":"ns/#References","page":"Neimarck-Sacker","title":"References","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"[Kuznetsov]: Yu. A. Kuznetsov, \"Elements of Applied Bifurcation Theory\", 2nd ed., 1998.","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"[Kuz2]: Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"[Iooss]: Iooss, \"Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.\", 1988","category":"page"},{"location":"overview/#Overview-of-BifurcationKit.jl","page":"Overview","title":"Overview of BifurcationKit.jl","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"The general workflow for using the package is as follows:","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Define a problem\nSolve the problem\nAnalyze the output","category":"page"},{"location":"overview/#Defining-Problems","page":"Overview","title":"Defining Problems","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"Problems are specified via a type interface. The problem types are designed to contain the necessary information to fully define their associated continuation method. For example, a bifurcation problem is defined by","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"F(u pars) = 0","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"with some parameters pars, some initial guess u0, and scalar parameter axis lens contained in pars. Therefore the BifurcationProblem is defined by those components:","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"prob = BifurcationProblem(F, u0, pars, lens)","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Note that the number types in the solution will match the types you designate in the problem. However complex types are not advised as they mess up the detection of bifurcation points.","category":"page"},{"location":"overview/#Continuing-from-the-initial-guess","page":"Overview","title":"Continuing from the initial guess","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"Each type of bifurcation problem has its own problem type which allow the solvers to dispatch to the right methods. The common interface for calling the solvers is:","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"br = continuation(prob, alg; kwargs)","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Into the command, one passes the bifurcation problem that was defined prob, choose an algorithm alg, and change the properties of the solver using keyword arguments. The solver returns a branch object br which holds all the details for the branch.","category":"page"},{"location":"overview/#Analyzing-the-branch","page":"Overview","title":"Analyzing the branch","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"The solution type has a common interface, which makes handling the solution similar between the different types of bifurcation problems. Tools such as interpolations are seamlessly built into the solution interface to make analysis easy. This interface is described in the ContResult.","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Plotting functionality is provided by a recipe to Plots.jl. To use plot branches, simply call the plot(br) and the plotter will generate appropriate plots. Plots can be customized using all the keyword arguments provided by Plots.jl. Please see Plots.jl's documentation for more information.","category":"page"},{"location":"#BifurcationKit.jl","page":"Home","title":"BifurcationKit.jl","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This Julia package aims at performing automatic bifurcation analysis of possibly large dimensional equations F(u, λ)=0 where λ∈ℝ by taking advantage of iterative methods, dense / sparse formulation and specific hardwares (e.g. GPU).","category":"page"},{"location":"","page":"Home","title":"Home","text":"It incorporates continuation algorithms (PALC, deflated continuation, ...) based on a Newton-Krylov method to correct the predictor step and a Matrix-Free/Dense/Sparse eigensolver is used to compute stability and bifurcation points.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Despite initial focus on large scale problems, the package can easily handle low dimensional problems.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The package can also seek for periodic orbits of Cauchy problems by casting them into an equation F(up)=0 of high dimension. It is by now, one of the only softwares which provides shooting methods AND methods based on finite differences or collocation to compute periodic orbits.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Hence, large scale nonlinear problems and different hardwares are possible. The goal is to use Matrix Free methods on GPU (see PDE example and Periodic orbit example) or on a cluster to solve non linear PDE, nonlocal problems, compute sub-manifolds...","category":"page"},{"location":"","page":"Home","title":"Home","text":"One design choice is that we try not to require u to be a subtype of an AbstractArray as this would forbid the use of spectral methods like the one from ApproxFun.jl. For now, our implementation does not allow this for all methods of the package.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package requires Julia >= v1.3.0 because of the use of methods added to abstract types (see #31916).","category":"page"},{"location":"","page":"Home","title":"Home","text":"To install it, please run","category":"page"},{"location":"","page":"Home","title":"Home","text":"] add BifurcationKit","category":"page"},{"location":"","page":"Home","title":"Home","text":"To install the bleeding edge version, please run","category":"page"},{"location":"","page":"Home","title":"Home","text":"] add BifurcationKit#master","category":"page"},{"location":"#Citing-this-work","page":"Home","title":"Citing this work","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"If you use this package for your work, we ask that you cite the following paper!! Open source development strongly depends on this. It is referenced on HAL-Inria as follows:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@misc{veltz:hal-02902346,\n TITLE = {{BifurcationKit.jl}},\n AUTHOR = {Veltz, Romain},\n URL = {https://hal.archives-ouvertes.fr/hal-02902346},\n INSTITUTION = {{Inria Sophia-Antipolis}},\n YEAR = {2020},\n MONTH = Jul,\n KEYWORDS = {pseudo-arclength-continuation ; periodic-orbits ; floquet ; gpu ; bifurcation-diagram ; deflation ; newton-krylov},\n PDF = {https://hal.archives-ouvertes.fr/hal-02902346/file/354c9fb0d148262405609eed2cb7927818706f1f.tar.gz},\n HAL_ID = {hal-02902346},\n HAL_VERSION = {v1},\n}","category":"page"},{"location":"#Other-softwares","page":"Home","title":"Other softwares","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"There are many good softwares already available.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For continuation in small dimension, most softwares are listed on DSWeb. One can mention the widely used AUTO-07p, or also, XPPAUT, MATCONT, PyDSTool and COCO. All these are very reliable and some address high codimensional bifurcations.\nFor large scale problems, there is the versatile and feature full pde2path but also Trilinos-LOCA, CL_MATCONTL, COCO, GetFEM and the python libraries pyNCT and pacopy. There are also some nice lectures by D. Avitabile et al. on matrix free secant continuation based on a concise Matlab implementation which are used in the influential paper [Rankin]. At the time of initial release of BifurcationKit.jl, these lectures provided one of the only libraries for matrix-free continuation, much easier to use than Trilinos-LOCA.\nFor deflated continuation, there is defcont (by the inventor of the algo. P. E. Farrell) and this code by N. M. Evstigneev.","category":"page"},{"location":"","page":"Home","title":"Home","text":"In Julia, we also have Bifurcations.jl which is unmaintained.","category":"page"},{"location":"#A-word-on-performance","page":"Home","title":"A word on performance","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The examples which follow have not all been written with the goal of performance but rather simplicity (except maybe 2d Ginzburg-Landau equation and Langmuir–Blodgett model). One could surely turn them into more efficient codes. The intricacies of PDEs make the writing of efficient code highly problem dependent and one should take advantage of every particularity of the problem under study.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For example, in one of the simplest tutorials, Temperature model, one could use BandedMatrices.jl for the jacobian and an inplace modification when the jacobian is called ; using a composite type would be favored. Porting them to GPU could be another option.","category":"page"},{"location":"#Requested-methods-for-Custom-State","page":"Home","title":"Requested methods for Custom State","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Needless to say, if you use regular arrays, you don't need to worry about what follows.","category":"page"},{"location":"","page":"Home","title":"Home","text":"We make the same requirements as KrylovKit.jl. Hence, we refer to its docs for more information. We additionally require the following methods to be available:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Base.length(x): it is used in the constraint equation of the pseudo arclength continuation method (see continuation for more details). If length is not available for your \"vector\", define it length(x) = 1 and adjust tuning the parameter θ in PALC.\nBase.copyto!(dest, in) this is required to reduce the allocations by avoiding too many copies\nBase.eltype must be extended to your vector type. It is mainly used for branching.","category":"page"},{"location":"#Citations","page":"Home","title":"Citations","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The papers citing this work are collected on google scholar.","category":"page"},{"location":"#Reproducibility","page":"Home","title":"Reproducibility","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"
      The documentation of BifurcationKit was built using these direct dependencies,","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Pkg # hide\nPkg.status() # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      ","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      and using this machine and Julia version.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using InteractiveUtils # hide\nversioninfo() # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      ","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      A more complete overview of all dependencies and their versions is also provided.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Pkg # hide\nPkg.status(;mode = PKGMODE_MANIFEST) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      ","category":"page"},{"location":"","page":"Home","title":"Home","text":"You can also download the\nmanifest file and the\nproject file.","category":"page"},{"location":"#References","page":"Home","title":"References","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"[Rankin]: J. Rankin et al., \"Continuation of localized coherent structures in nonlocal neural field equations\", SIAM J. Scientific Computing 36, pp. B70–B93 (2014): https://epubs.siam.org/doi/10.1137/130918721","category":"page"},{"location":"diffeq/#Wrapper-to-the-package-DifferentialEquations.jl","page":"DiffEq wrapper","title":"Wrapper to the package DifferentialEquations.jl","text":"","category":"section"},{"location":"diffeq/","page":"DiffEq wrapper","title":"DiffEq wrapper","text":"warning: Warning\nThis is work in progress. ","category":"page"},{"location":"diffeq/","page":"DiffEq wrapper","title":"DiffEq wrapper","text":"The current package will provide basic methods to wrap some of the functionality of DifferentialEquations.jl. ","category":"page"},{"location":"diffeq/","page":"DiffEq wrapper","title":"DiffEq wrapper","text":"Basically, the ultimate idea is that you provide a prob::ODEProblem to our newton, continuation... and they will use the expression of the jacobians, the linear solvers... that you already provided for the construction of prob.","category":"page"},{"location":"NSContinuationPO/#Continuation-of-Neimark-Sacker-(NS)-bifurcations-of-periodic-orbits","page":"Neimark-Sacker continuation (2 params)","title":"Continuation of Neimark-Sacker (NS) bifurcations of periodic orbits","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"warning: Work in progress\nContinuation of NS of POs is a recent addition. It has not been thoroughly tested.","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In this page, we explain how to perform continuation of NS points of periodic orbits and detect the associated codim 2 bifurcations.","category":"page"},{"location":"NSContinuationPO/#List-of-detected-codim-2-bifurcation-points","page":"Neimark-Sacker continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"Bifurcation symbol used\nCusp cusp\nStrong resonance 1:1 bifurcation R1\nFold / Flip foldFlip\nFold / Neimark-Sacker foldNS\nDouble Niemark-Sacker nsns\nChenciner ch","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"NSContinuationPO/#Neimark-Sacker-continuation","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"The continuation of Neimark-Sacker bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation), except the Trapezoid one, for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.","category":"page"},{"location":"NSContinuationPO/#Detection-of-codim-2-bifurcation-points","page":"Neimark-Sacker continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the keyword argument detect_codim2_bifurcation in the method continuation ","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"the detection of Chenciner bifurcation is done by the the computating the NS normal form\nthe detection the above bifurcation points is done by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"NSContinuationPO/#Setting-the-jacobian","page":"Neimark-Sacker continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In order to apply the newton algorithm to the PD functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the PD functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.","category":"page"},{"location":"NSContinuationPO/#Codim-2-continuation","page":"Neimark-Sacker continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"To compute the codim 2 curve of Fold points of periodic orbits, one can call continuation with the following options","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"NSContinuationPO/#Algorithmic-details","page":"Neimark-Sacker continuation (2 params)","title":"Algorithmic details","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"The continuation of NS points is based on the formulation","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"G(upomega) = (F_po(upomega) Resigma(upomega) Imsigma(upomega))inmathbb R^n+2quadquad (mathcal F_ns)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"where F_po is the functional for locating periodic orbits and the test function sigma is solution of","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"leftbeginarraycc\nN(upomega) w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(uomegap)\nendarrayright=leftbeginarrayc\n0_n \n1\nendarrayright","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In the case of Multiple Standard Shooting, the matrix N is based on the monodromy M(x_iT_i)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"N=left(beginarraycccccc\nM_1 -I 0 cdots 0 \n0 M_2 -I cdots 0 \nvdots cdots ddots ddots vdots \n0 cdots cdots ddots -I \ne^iomegaI cdots cdots 0 M_m \nendarrayright)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"The jacobian of the NS functional to use for the Newton algorithm","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"leftbeginarrayccc\npartial_uF_po partial_pF_po 0 \npartial_usigma_r partial_psigma_r partial_omegasigma_r\npartial_usigma_i partial_psigma_i partial_omegasigma_i\nendarrayright","category":"page"},{"location":"NSContinuationPO/#References","page":"Neimark-Sacker continuation (2 params)","title":"References","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"abs-from-codim2-po/#From-codim-2-to-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Pages = [\"abs-from-codim2-po.md\"]\nDepth = 2","category":"page"},{"location":"abs-from-codim2-po/#From-Bautin-point-to-curve-Folds-of-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From Bautin point to curve Folds of periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"From the Bautin normal form, we know that there is a curve of Fold of periodic orbits near the bifurcation point.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"We provide an automatic branch switching method in this case which reads as follows:","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"continuation(br::HopfCont, ind_BAUTIN::Int, \n\t_contParams::ContinuationPar,\n prob::AbstractPeriodicOrbitProblem ;\n δp = nothing, ampfactor = 1, kwargs...)","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information).","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Note that the two parameters in br will be used for the continuation of Fold points of periodic orbits.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"See ODE for an example of use.","category":"page"},{"location":"abs-from-codim2-po/#From-Zero-Hopf-(ZH)-point-to-curve-NS-of-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From Zero-Hopf (ZH) point to curve NS of periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"From the Zero-Hopf normal form, we know that there is a curve of Neimark-Sacker (NS) bifurcations of periodic orbits near the bifurcation point.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"We provide an automatic branch switching method in this case which reads as follows:","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"continuation(br::TwoParamCont, ind_ZH::Int, \n\t_contParams::ContinuationPar,\n prob::AbstractPeriodicOrbitProblem ;\n δp = nothing, ampfactor = 1, kwargs...)","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information).","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Note that the two parameters in br will be used for the continuation of NS points of periodic orbits.","category":"page"},{"location":"abs-from-codim2-po/#From-Hopf-Hopf-(HH)-point-to-curve-NS-of-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From Hopf-Hopf (HH) point to curve NS of periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"From the Hopf-Hopf normal form, we know that there are two curves of Neimark-Sacker (NS) bifurcations of periodic orbits near the bifurcation point.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"We provide an automatic branch switching method in this case which reads as follows:","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"continuation(br::TwoParamCont, ind_HH::Int, \n\t_contParams::ContinuationPar,\n prob::AbstractPeriodicOrbitProblem ;\n δp = nothing, ampfactor = 1, \n whichns = 1,\n kwargs...)","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information). The option whichns which belongs to {1,2} controls which NS curve you want to compute. ","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Note that the two parameters in br will be used for the continuation of NS points of periodic orbits.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"See ODE for an example of use.","category":"page"},{"location":"zh/#Normal-form-of-the-Zero-Hopf-bifurcation","page":"Zero-Hopf","title":"Normal form of the Zero-Hopf bifurcation","text":"","category":"section"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"We follow the paper[Kuznetsov],[Kuznetsov2] and consider a Cauchy problem","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"dot x=mathbf F(xp)","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"mathbf L q_0=0 quad mathbf L q_1=i omega_0 q_1","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"Under some conditions, x(t)approx x_0+2Re w_1(t)q_1+w_0(t)q_0 where w_i satisfy the normal form:","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"leftbeginaligned\ndotw_0= frac12 G_200 w_0^2+G_011leftw_1right^2+frac16 G_300 w_0^3 +G_111 w_0leftw_1right^2+Oleft(leftleft(w_0 w_1 barw_1right)right^4right) \ndotw_1= i omega_0 w_1+G_110 w_0 w_1+frac12 G_210 w_0^2 w_1+frac12 G_021 w_1leftw_1right^2 +Oleft(leftleft(w_0 w_1 barw_1right)right^4right) \nendalignedrighttagE","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"This normal form is usually computed in order to branch from a Zero-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the G_ijk is returned.","category":"page"},{"location":"zh/#Normal-form-computation","page":"Zero-Hopf","title":"Normal form computation","text":"","category":"section"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type ZeroHopf.","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"zh/#References","page":"Zero-Hopf","title":"References","text":"","category":"section"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"[Kuznetsov2]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.","category":"page"},{"location":"eigensolver/#Eigen-solvers-(Eig)","page":"Eigen solvers","title":"Eigen solvers (Eig)","text":"","category":"section"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"The eigen solvers must be subtypes of AbstractEigenSolver. ","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"They provide a way of computing the eigen elements of the Jacobian J. Such eigen solver eigsolve will be called like ev, evecs, itnumber = eigsolve(J, nev; kwargs...) throughout the package, nev being the number of requested eigen elements of largest real part and kwargs being used to send information about the algorithm (perform bisection,...).","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"Here is an example of the simplest of them (see src/EigSolver.jl for the true implementation) to give you an idea:","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"struct DefaultEig <: AbstractEigenSolver end\n\nfunction (l::DefaultEig)(J, nev; kwargs...)\n\t# I put Array so we can call it on small sparse matrices\n\tF = eigen(Array(J))\n\tI = sortperm(F.values, by = real, rev = true)\n\tnev2 = min(nev, length(I))\n\treturn F.values[I[1:nev2]], F.vectors[:, I[1:nev2]], true, 1\nend","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"warning: Eigenvalues\nThe eigenvalues must be ordered by increasing real part for the detection of bifurcations to work properly.","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"warning: Eigenvectors\nYou have to implement the method geteigenvector(eigsolver, eigenvectors, i::Int) for newtonHopf to work properly.","category":"page"},{"location":"eigensolver/#Methods-for-computing-eigenvalues","page":"Eigen solvers","title":"Methods for computing eigenvalues","text":"","category":"section"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"Like for the linear solvers, computing the spectrum of operators A associated to PDE is a highly non trivial task because of the clustering of eigenvalues. Most methods are based on the so-called power method but this only yields the eigenvalues with largest modulus. In case of the Laplacian operator, this can be disastrous and it is better to apply the power method to (sigma I-A)^-1 instead. ","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"This method, called Shift-invert, is readily available for the solvers EigArpack and EigArnoldiMethod, see below. It is mostly used to compute interior eigenvalues. For the solver EigKrylovKit, one must implement its own shift invert operator, using for example GMRESKrylovKit.","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"In some cases, it may be advantageous to consider the Cayley transform (sigma I-A)^-1(tau I+A) to focus on a specific part of the spectrum. As it is mathematically equivalent to the Shift-invert method, we did not implement it.","category":"page"},{"location":"eigensolver/#List-of-implemented-eigen-solvers","page":"Eigen solvers","title":"List of implemented eigen solvers","text":"","category":"section"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"Default eigen Julia eigensolver for matrices. You can create it via eig = DefaultEig(). Note that you can also specify how the eigenvalues are ordered (by decreasing real part by default). You can then compute 3 eigenelements of J like eig(J, 3).\nEigensolver from Arpack.jl. You can create one via eigsolver = EigArpack() and pass appropriate options (see Arpack.jl). For example, you can compute eigenvalues using Shift-Invert method with shift σ by using EigArpack(σ, :LR). Note that you can specify how the eigenvalues are ordered (by decreasing real part by default). Finally, this method can be used for (sparse) matrix or Matrix-Free formulation. For a matrix J, you can compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigArpack(v0 = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3). \nEigensolver from KrylovKit.jl. You create one via eig = EigKrylovKit() and pass appropriate options (see KrylovKit.jl). This method can be used for (sparse) matrix or Matrix-Free formulation. In the case of a matrix J, you can create a solver like this eig = EigKrylovKit(). Then, you compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigKrylovKit(x₀ = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3).\nEigensolver from ArnoldiMethod.jl. You can create one via eig = EigArnoldiMethod() and pass appropriate options (see ArnoldiMethod.jl). For example, you can compute eigenvalues using the Shift-Invert method with shift σ by using EigArnoldiMethod(σ, LR()). Note that you can also specify how the eigenvalues are ordered (by decreasing real part by default). In the case of a matrix J, you can create a solver like eig = EigArnoldiMethod(). Then, you compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigArnoldiMethod(x₀ = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3). ","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"tip: Slow computations \nThis is probably due to iterative refinement conducted by SuiteSparse as explained in this blog post. You can disable this usingusing SuiteSparse\nSuiteSparse.UMFPACK.umf_ctrl[8] = 0","category":"page"},{"location":"interfaceLS/#Interface-for-Linear-Solvers","page":"Vector","title":"Interface for Linear Solvers","text":"","category":"section"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"The linear solver ls must be a subtype of the abstract type AbstractLinearSolver. It is then called as follows","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"Required methods Brief description\nls(J, rhs; a₀ = 0, a₁ = 1, kwargs...) Compute the solution sol of the linear problem (a₀ * I + a₁ * J) * sol = rhs where J is the jacobian. Returns (sol, success::Bool, itnumber) where itnumber is the number of iterations for solving the problem.","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"tip: Shifts\nTwo methods _axpy and _axpy_op are provided to help implementing this shift a₀ * I + a₁ * J","category":"page"},{"location":"interfaceLS/#Interface-for-Eigen-Solvers","page":"Vector","title":"Interface for Eigen Solvers","text":"","category":"section"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"The linear solver eig must be a subtype of the abstract type AbstractEigenSolver. It is then called as follows","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"Required methods Brief description\neig(J, nev::Int; kwargs...) Compute the nev eigen-elements with largest real part. Returns (eigenvalues, eigenvectors, success:Bool, itnumber) where itnumber is the number of iterations for completing the computation. kwargs can be used to send information about the algorithm (perform bisection,...).\ngeteigenvector(eig, eigenvectors, i::Int) Returns the ith eigenvectors from the set of eigenvectors.","category":"page"},{"location":"interfaceLS/#Interface-for-Bordered-Linear-Solvers","page":"Vector","title":"Interface for Bordered Linear Solvers","text":"","category":"section"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"The bordered linear solver bls must be a subtype of the abstract type AbstractBorderedLinearSolver (which is itself a subtype of AbstractLinearSolver). It is used to solve","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"tagBLSleftbeginarrayll\ntextshiftcdot I+J dR \n(xi_u cdot dz_u)^T xi_p cdot dz_p\nendarrayright cdotleftbeginarrayl\ndX \ndl\nendarrayright = leftbeginarrayl\nR \nn\nendarrayright","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"where xi_uxi_pinmathbb C and dRxi_uinmathbb C^N.","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"Required methods Brief description\nbls(J, dR, dzu, dzp, R, n, ξu::Number, ξp::Number; shift = nothing, kwargs...) Compute the solution dX, dl of the linear problem (BLS) where J is the jacobian and dR, dzu are vectors (not necessarily subtypes of AbstractVector). shift = nothing is used in place of saying shift=0. Returns (dX, dl, success::Bool, itnumber) where itnumber is the number of iterations for solving the problem.","category":"page"},{"location":"educational/#Educational-introduction-to-bifurcation-analysis-(contributed-by-G.-Datseris)","page":"Educational introduction","title":"Educational introduction to bifurcation analysis (contributed by G. Datseris)","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"This page is an educational introduction to bifurcation analysis and creation of bifurcation diagrams. It will show a completely self-contained approach, and its goal is to serve as an introduction to users not yet fully familiar with bifurcation analysis. ","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The text here is based on Chapter 4 of Nonlinear Dynamics: a concise introduction interlaced with code and is presented in a shortened form. It is focusing on using the simplest possible method for bifurcation continuation (the secant method) and can only address fixed points (the standard version of Newton's algorithm). Of course, this does not reflect the full features and power of BifurcationKit.jl, but it shows the basic guiding principles.","category":"page"},{"location":"educational/#Newton's-method-for-finding-fixed-points","page":"Educational introduction","title":"Newton's method for finding fixed points","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let mathbfx be a D-dimensional vector participating in the continuous dynamical system dotmathbfx = f(mathbfx p) which also depends on some arbitrary parameter pinmathbb R. To identify fixed points, we want to find the roots mathbfx^* of f. Notice that everything that follows also applies to discrete dynamical systems where mathbfx_n+1 = g(mathbfx_n). The difference is that we simply define f = g - mathbfId and find the roots of f again.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"To find the roots we can use Newton's method. Starting for some point mathbfx_0, the following sequence will (typically) converge to a root:","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"mathbfx_j+1 = mathbfx_j - delta J_f^-1(mathbfx_j) f(mathbfx_j)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"for 0le delta le 1 and with J_f the Dtimes D Jacobian matrix of f.","category":"page"},{"location":"educational/#Continuation-of-a-bifurcation-curve","page":"Educational introduction","title":"Continuation of a bifurcation curve","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"A bifurcation curve (in the simplified context of this page) is the location of fixed points versus a parameter p. The simplest, but also most brute force, way to compute such a curve would be to scan the parameter axis, and for each parameter value apply Newton's method to find the fixed point. Because there could be more than one fixed points at a given parameter, one needs several initial conditions plugged into Newton's method, to ensure all fixed points are found.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"A bit better approach would be to true and continue the curve of the fixed point mathbfx^*(p). To do this one needs two ingredients: (1) a predictor and (2) a corrector. The first estimates a new \"seed\" for Newton's method that attempts to continue the existing points we have found on the curve. The second corrects this prediction to a point in the state-parameter space that is on the bifurcation curve.","category":"page"},{"location":"educational/#The-secant-predictor","page":"Educational introduction","title":"The secant predictor","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The simplest predictor is the secant. Let mathbfz = (mathbfx p). Assuming we have found at least two points mathbfz^*_m mathbfz^*_m-1 on the bifurcation curve, we can estimate a continuation tildemathbfz = 2mathbfz^*_m - mathbfz^*_m-1 (linear extrapolation). This is called the secant predictor.","category":"page"},{"location":"educational/#The-corrector","page":"Educational introduction","title":"The corrector","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The prediction tildemathbfz of the secant needs to be corrected not only in the variable space mathbfx, which is what Newton's method currently does, but also on parameter space. To do this, we need to extend the function f to have one more element (because otherwise we would have 1 too many unknowns give the amount of equations we have to estimate the zero of f(mathbfz)). We will extend f so that its D+1 entry enforces the k-th element of the root to be the one suggested by the predictor. I.e., we define the function h","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"h(mathbfx) = (f_1(mathbfz) ldots f_D(mathbfz) mathbfzk - tildemathbfzk)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"and will try to find the zeros of h now via Newton's method. Notice that now the Jacobian J_h is D+1 dimensional, with the last column being the derivatives of f towards the parameter p.","category":"page"},{"location":"educational/#Code:-Newton's-algorithm-in-mixed-space","page":"Educational introduction","title":"Code: Newton's algorithm in mixed space","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let's first write the code that will be performing Newton's algorithm for the function h in the mixed space of mathbfz. For convenience, we would expect the user to only provide the functions f J_f as functions f(x, p), J(x,p) with x a vector and p a number. We can do everything else using automatic differentiation.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"(Notice: for simplicity, and to be in style with BifurcationKit.jl we will make everything allocate and return new Vector instances. Performance-wise, the code written in this page is as bad as it can possibly get)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"First, define a function that given f, J, the mixed state z and the index k it returns the mixed Jacobian J_h","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"using ForwardDiff # for auto-differentiation\nusing LinearAlgebra\n\nfunction mixed_jacobian(z, k, f, J)\n x = z[1:end-1]; p = z[end]\n # start creating the mixed space jacobian\n j = J(x, p)\n # to the state space jacobian add one more column, derivative towards p\n pder = ForwardDiff.derivative(p -> f(x, p), p)\n Jmixed = hcat(j, pder)\n # add the last row, which is 1 for the `k` entry, 0 everywhere else\n last_row = zeros(length(z)); last_row[k] = 1.0\n Jfinal = vcat(Jmixed, last_row')\n return Jfinal\nend","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Then we write a function that takes one step of the Newton's algorithm:","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"using LinearAlgebra\n\nfunction newton_step!(zⱼ, zpred, i, f, J, δ)\n Jfinal = mixed_jacobian(zⱼ, i, f, J)\n xⱼ = zⱼ[1:end-1]; pⱼ = zⱼ[end]\n g = f(xⱼ, pⱼ)\n gz = vcat(g, zⱼ[i] - zpred[i])\n zⱼ₊₁ = zⱼ - Jfinal \\ gz\n return zⱼ₊₁\nend","category":"page"},{"location":"educational/#Code:-Corrector-function","page":"Educational introduction","title":"Code: Corrector function","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"And with this, we are ready to compose our corrector function, that takes a guess zpred and brings it to a point that is on the bifurcation curve. The keyword arguments help us give a convergence criterion to Newton's algorithm and also catch problematic cases where convergence never happens in time.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function corrector(zpred, f, J; δ = 0.9, max_steps = 200, ε = 1e-6, k = 1)\n c = 0\n zⱼ = zpred\n zⱼ₊₁ = newton_step!(zⱼ, zpred, k, f, J, δ)\n while norm(zⱼ₊₁ - zⱼ) > ε\n zⱼ = zⱼ₊₁\n zⱼ₊₁ = newton_step!(zⱼ, zpred, k, f, J, δ)\n c += 1\n if c > max_steps\n @warn(\"Newton did not converge.\")\n return (zⱼ₊₁, false)\n end\n end\n return zⱼ₊₁, true\nend","category":"page"},{"location":"educational/#Code:-Predictor-function","page":"Educational introduction","title":"Code: Predictor function","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Coding the predictor is trivial. If we have no previous entries we start from the initial seed given by the user, otherwise we take do the linear extrapolation discussed above. A user also needs to provide an initial direction dmathbfz to go towards.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function predictor(zs, dz0)\n if length(zs) == 1\n return zs[end]\n elseif length(zs) == 2 # 1 entry is z0, 2nd entry is 1st found fixed point\n return zs[end] .+ dz0\n else\n return 2zs[end] .- zs[end-1]\n end\nend","category":"page"},{"location":"educational/#Code:-Continuation-function","page":"Educational introduction","title":"Code: Continuation function","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Alright, now we can put it all together into the a single \"continuation\" function.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function continuation!(zs, f, J; dz0, pmin, pmax)\n zpred = predictor(zs, dz0)\n (pmin ≤ zpred[end] ≤ pmax) || return false\n zˣ, success = corrector(zpred, f, J)\n push!(zs, zˣ)\n return success\nend\n\nusing LinearAlgebra: eigvals\n\n# Continuation loop: do continuation for a given amount of steps\nfunction continuation(f, J, x0, p0; pmin, pmax, dp0, dx0, N = 1000)\n\n z0 = vcat(x0, p0); zs = [z0]; dz0 = vcat(dx0, dp0)\n\n ps = [p0]\n xs = [x0]\n stability = Bool[]\n for i in 1:N\n success = continuation!(zs, f, J; dz0, pmin, pmax)\n # Stop iteration if we exceed given parameter margins\n success || break\n # Detect stability of found fixed point (needs `Array` coz of StaticArrays.jl)\n eigenvalues = eigvals(J(zs[end][1:end-1], zs[end][end]))\n isstable = maximum(real, eigenvalues) < 0\n push!(stability, isstable)\n end\n xs = [z[1:end-1] for z in zs]\n ps = [z[end] for z in zs]\n popfirst!(xs); popfirst!(ps) # remove initial guess\n return xs, ps, stability\nend","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The code also returns the fixed point stability, although it does assume we have a continuous dynamical system. Adjusting for discrete systems is straightforward.","category":"page"},{"location":"educational/#Running-an-example","page":"Educational introduction","title":"Running an example","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let's use the code we have defined to run an example. The following dynamical system has a single saddle node bifurcation, and a fixed point that is \"flat\" versus the parameter change.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function maasch_rule(u, p)\n x, y, z = u\n q, r, s = 1.2, 0.8, 0.8\n dx = -x - y\n dy = -p*z + r*y + s*z^2 - z^2*y\n dz = -q*(x + z)\n return [dx, dy, dz]\nend\n\nfunction maasch_jacob(u, p)\n x, y, z = u\n q, r, s = 1.2, 0.8, 0.8\n return [-1 -1 0;\n 0 (r - z^2) (-p + 2z*s - 2z*y);\n -q 0 -q]\nend","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"We now use it to get the bifurcation curve.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"pmin = -0.1\npmax = 2\nδ = 0.9\np0 = 0.0\nx0 = [-1.4, -1.4, -1.4]\ndp0 = 0.02\ndx0 = [0.01, 0.01, 0.01]\n\nxs, ps, stability = continuation(maasch_rule, maasch_jacob, x0, p0;\n pmin, pmax, dp0, dx0\n)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let's plot this","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"using Plots\ncolors = [s ? :blue : :red for s in stability]\np = scatter(ps, [x[1] for x in xs]; color = colors, markerstrokecolor = colors, xlabel = \"p\", ylabel = \"x\", label = \"\")","category":"page"},{"location":"tutorials/ode/tutorialPP2/#pp2-example-from-AUTO07p-(aBD-Hopf-aBS)","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"","category":"section"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"Pages = [\"tutorialsPP2.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"The goal of this example is to show how to use automatic bifurcation diagram computation for a simple ODE.","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"The following equations are a model of type predator-prey. The example is taken from Auto07p:","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"beginarrayl\nu_1^prime=3 u_1left(1-u_1right)-u_1 u_2-p_1left(1-e^-5 u_1right) \nu_2^prime=-u_2+3 u_1 u_2\nendarray","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\n\n# function to record information from a solution\nrecordFromSolution(x, p) = (u1 = x[1], u2 = x[2])\n\nfunction pp2!(dz, z, p, t = 0)\n\t@unpack p1, p2, p3, p4 = p\n\tu1, u2 = z\n\tdz[1] = p2 * u1 * (1 - u1) - u1 * u2 - p1 * (1 - exp(-p3 * u1))\n\tdz[2] =\t-u2 + p4 * u1 * u2\n\tdz\nend\n\n# parameters of the model\npar_pp2 = (p1 = 1., p2 = 3., p3 = 5., p4 = 3.)\n\n# initial condition\nz0 = zeros(2)\n\n# bifurcation problem\nprob = BifurcationProblem(pp2!, z0, par_pp2,\n\t# specify the continuation parameter\n\t(@lens _.p1), record_from_solution = recordFromSolution)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialPP2/#Automatic-bifurcation-diagram-computation","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"Automatic bifurcation diagram computation","text":"","category":"section"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"We set up the options or the continuation","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = 0.1, p_max = 1.0, dsmax = 0.01,\n\t# options to detect bifurcations\n\tdetect_bifurcation = 3, n_inversion = 8, max_bisection_steps = 25,\n\t# number of eigenvalues\n\tnev = 2,\n\t# maximum number of continuation steps\n\tmax_steps = 1000,)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"We are now ready to compute the diagram","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"diagram = bifurcationdiagram(prob, PALC(),\n\t# very important parameter. It specifies the maximum amount of recursion\n\t# when computing the bifurcation diagram. It means we allow computing branches of branches of branches\n\t# at most in the present case.\n\t3,\n\t(args...) -> setproperties(opts_br; ds = -0.001, dsmax = 0.01, n_inversion = 8, detect_bifurcation = 3);\n\t# δp = -0.01,\n\tverbosity = 0, plot = false)\n\nscene = plot(diagram; code = (), title=\"$(size(diagram)) branches\", legend = false)","category":"page"},{"location":"tutorials/ode/tutorialPP2/#Branch-of-periodic-orbits-with-finite-differences","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"Branch of periodic orbits with finite differences","text":"","category":"section"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"As you can see on the diagram, there is a Hopf bifurcation indicated by a red dot. Let us compute the periodic orbit branching from the Hopf point.","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"We first find the branch","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"# branch of the diagram with Hopf point\nbrH = get_branch(diagram, (2,1)).γ\n\n# newton parameters\noptn_po = NewtonPar(tol = 1e-8, max_iterations = 25)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.1, ds= -0.001, dsmin = 1e-4,\n newton_options = (@set optn_po.tol = 1e-8), tol_stability = 1e-2,\n detect_bifurcation = 1)\n\nMt = 101 # number of time sections\n\tbr_po = continuation(\n\tbrH, 1, opts_po_cont,\n\tPeriodicOrbitTrapProblem(M = Mt;\n\t # specific linear solver for ODEs\n \tjacobian = :Dense);\n\trecord_from_solution = (x, p) -> (xtt=reshape(x[1:end-1],2,Mt);\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\tmin = minimum(xtt[1,:]),\n\t\t\tperiod = x[end])),\n\tfinalise_solution = (z, tau, step, contResult; prob = nothing, kwargs...) -> begin\n\t\t# limit the period\n\t\tz.u[end] < 100\n\t\tend,\n\tnormC = norminf)\n\n\nplot(diagram); plot!(br_po, label = \"Periodic orbits\", legend = :bottomright)","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"Let us now plot an orbit","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"# extract the different components\norbit = get_periodic_orbit(br_po, 10)\nplot(orbit.t, orbit.u[1,:]; label = \"u1\", markersize = 2)\nplot!(orbit.t, orbit.u[2,:]; label = \"u2\", xlabel = \"time\", title = \"period = $(orbit.t[end])\")","category":"page"},{"location":"tutorials/tutorials2/#sh2dfd","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Pages = [\"tutorials2.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We study the following PDE","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"-(I+Delta)^2 u+lcdot u +nu u^2-u^3 = 0","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"with Neumann boundary conditions. This full example is in the file example/SH2d-fronts.jl. This example is also treated in the MATLAB package pde2path. We use a Sparse Matrix to express the operator L_1=(I+Delta)^2.","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"using DiffEqOperators, Setfield, Parameters\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays\nconst BK = BifurcationKit\n\n# helper function to plot solution\nheatmapsol(x) = heatmap(reshape(x,Nx,Ny)',color=:viridis)\nheatmapsol!(x; k...) = heatmap!(reshape(x,Nx,Ny)';color=:viridis, k...)\n\nNx = 151\nNy = 100\nlx = 4*2pi\nly = 2*2pi/sqrt(3)\n\n# we use DiffEqOperators to compute the Laplacian operator\nfunction Laplacian2D(Nx, Ny, lx, ly)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\tQx = Neumann0BC(hx)\n\tQy = Neumann0BC(hy)\n\n\tA = kron(sparse(I, Ny, Ny), sparse(D2x * Qx)[1]) + kron(sparse(D2y * Qy)[1], sparse(I, Nx, Nx))\n\treturn A, D2x\nend","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We also write the functional and its Jacobian which is a Sparse Matrix","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"function F_sh(u, p)\n\t@unpack l, ν, L1 = p\n\treturn -L1 * u .+ (l .* u .+ ν .* u.^2 .- u.^3)\nend\n\nfunction dF_sh(u, p)\n\t@unpack l, ν, L1 = p\n\treturn -L1 .+ spdiagm(0 => l .+ 2 .* ν .* u .- 3 .* u.^2)\nend\n\n# we compute the differentials\nd2F_sh(u, p, dx1, dx2) = (2 .* p.ν .* dx2 .- 6 .* dx2 .* u) .* dx1\nd3F_sh(u, p, dx1, dx2, dx3) = (-6 .* dx2 .* dx3) .* dx1","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We first look for hexagonal patterns. This is done with","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"X = -lx .+ 2lx/(Nx) * collect(0:Nx-1)\nY = -ly .+ 2ly/(Ny) * collect(0:Ny-1)\n\n# initial guess for hexagons\nsol0 = [(cos(x) + cos(x/2) * cos(sqrt(3) * y/2) ) for x in X, y in Y]\n\tsol0 .= sol0 .- minimum(vec(sol0))\n\tsol0 ./= maximum(vec(sol0))\n\tsol0 = sol0 .- 0.25\n\tsol0 .*= 1.7\n\theatmap(sol0',color=:viridis)\n\n# define parameters for the PDE\nΔ, _ = Laplacian2D(Nx, Ny, lx, ly);\nL1 = (I + Δ)^2;\npar = (l = -0.1, ν = 1.3, L1 = L1);\n\n# Bifurcation Problem\nprob = BifurcationProblem(F_sh, vec(sol0), par, (@lens _.l);\n\t\tJ = dF_sh,\n\t\tplot_solution = (x, p; kwargs...) -> (heatmapsol!(x; label=\"\", kwargs...)),\n\t\trecord_from_solution = (x, p) -> (n2 = norm(x), n8 = norm(x, 8)),\n\t\td2F = d2F_sh,\n\t\td3F = d3F_sh)\n\n# newton corrections of the initial guess\noptnewton = NewtonPar(verbose = true, tol = 1e-8, max_iterations = 20)\nsol_hexa = @time newton(prob, optnewton)\nprintln(\"--> norm(sol) = \",norm(sol_hexa.u, Inf64))\nheatmapsol(sol_hexa.u)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"which produces the results","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.7391e+02 │ 0 │\n│ 1 │ 5.0465e+03 │ 1 │\n│ 2 │ 1.4878e+03 │ 1 │\n│ 3 │ 4.3529e+02 │ 1 │\n│ 4 │ 1.2560e+02 │ 1 │\n│ 5 │ 3.5512e+01 │ 1 │\n│ 6 │ 9.5447e+00 │ 1 │\n│ 7 │ 2.1763e+00 │ 1 │\n│ 8 │ 3.3503e-01 │ 1 │\n│ 9 │ 7.7259e-02 │ 1 │\n│ 10 │ 7.4767e-03 │ 1 │\n│ 11 │ 7.9505e-05 │ 1 │\n│ 12 │ 8.8395e-09 │ 1 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.441525 seconds (1.74 k allocations: 659.488 MiB, 1.25% gc time)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"with sol_hexa being","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/#Continuation-and-bifurcation-points","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"Continuation and bifurcation points","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We can now continue this solution as follows. We want to detect bifurcations along the branches. We thus need an eigensolver. However, if we use an iterative eigensolver, like eig = EigArpack(), it has trouble computing the eigenvalues. One can see that using","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"# compute the jacobian\nJ0 = dF_sh(sol_hexa.u, par)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"The reason is that the jacobian operator is not very well conditioned unlike its inverse. We thus opt for the shift-invert method (see Eigen solvers (Eig) for more information) with shift 0.1:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"eig = EigArpack(0.1, :LM)\n\n# compute 10 eigenvalues\neig(J0, 10)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"If we want to compute the bifurcation points along the branches, we have to tell the solver by setting detect_bifurcation = 2. However, this won't be very precise and each bifurcation point will be located at best at the step size precision. We can use bisection to locate this points more precisely using the option detect_bifurcation = 3 (see Detection of bifurcation points of Equilibria for more information).","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We are now ready to compute the branches:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"optcont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= -0.001, p_max = 0.00, p_min = -1.0,\n\tnewton_options = setproperties(optnewton; tol = 1e-9, max_iterations = 15), max_steps = 125,\n\tdetect_bifurcation = 3, nev = 40, detect_fold = false,\n\tdsmin_bisection =1e-7, save_sol_every_step = 4)\noptcont = @set optcont.newton_options.eigsolver = EigArpack(0.1, :LM)\n\nbr = continuation(\n\tre_make(prob, u0 = sol_hexa.u), PALC(), optcont;\n\tplot = true,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Note that we can get some information about the branch as follows. The [converged] indicates if the bisection routine was successful, otherwise it shows [guess]. Finally δ = ( 2, 0) says that the bifurcation point has been detected by 2 new eigenvalues with zero real part among which zero have non zero imaginary part. A Hopf bifurcation point would thus have δ = ( 2, 2) or δ = ( -2, 2).","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"julia> br\n ┌─ Branch number of points: 98\n ├─ Branch of Equilibrium\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter l starts at -0.1, ends at 0.0\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, bp at l ≈ -0.21554719 ∈ (-0.21554719, -0.21554706), |δp|=1e-07, [converged], δ = ( 1, 0), step = 35, eigenelements in eig[ 36], ind_ev = 1\n- # 2, bp at l ≈ -0.21551160 ∈ (-0.21552059, -0.21551160), |δp|=9e-06, [converged], δ = ( 1, 0), step = 36, eigenelements in eig[ 37], ind_ev = 2\n- # 3, bp at l ≈ -0.21498624 ∈ (-0.21505972, -0.21498624), |δp|=7e-05, [converged], δ = ( 1, 0), step = 38, eigenelements in eig[ 39], ind_ev = 3\n- # 4, bp at l ≈ -0.21288704 ∈ (-0.21296786, -0.21288704), |δp|=8e-05, [converged], δ = ( 1, 0), step = 41, eigenelements in eig[ 42], ind_ev = 4\n- # 5, nd at l ≈ -0.20991950 ∈ (-0.21014903, -0.20991950), |δp|=2e-04, [converged], δ = ( 2, 0), step = 43, eigenelements in eig[ 44], ind_ev = 6\n- # 6, nd at l ≈ -0.20625778 ∈ (-0.20683030, -0.20625778), |δp|=6e-04, [converged], δ = ( 2, 0), step = 45, eigenelements in eig[ 46], ind_ev = 8\n- # 7, bp at l ≈ -0.19979039 ∈ (-0.19988091, -0.19979039), |δp|=9e-05, [converged], δ = ( 1, 0), step = 48, eigenelements in eig[ 49], ind_ev = 9\n- # 8, bp at l ≈ -0.18865313 ∈ (-0.18887470, -0.18865313), |δp|=2e-04, [converged], δ = ( 1, 0), step = 52, eigenelements in eig[ 53], ind_ev = 10\n- # 9, bp at l ≈ -0.18102735 ∈ (-0.18105752, -0.18102735), |δp|=3e-05, [converged], δ = ( 1, 0), step = 55, eigenelements in eig[ 56], ind_ev = 11\n- # 10, bp at l ≈ -0.14472390 ∈ (-0.14531199, -0.14472390), |δp|=6e-04, [converged], δ = (-1, 0), step = 64, eigenelements in eig[ 65], ind_ev = 11\n- # 11, bp at l ≈ -0.13818496 ∈ (-0.13878446, -0.13818496), |δp|=6e-04, [converged], δ = (-1, 0), step = 66, eigenelements in eig[ 67], ind_ev = 10\n- # 12, bp at l ≈ -0.11129567 ∈ (-0.11161237, -0.11129567), |δp|=3e-04, [converged], δ = (-1, 0), step = 72, eigenelements in eig[ 73], ind_ev = 9\n- # 13, bp at l ≈ -0.08978296 ∈ (-0.09010769, -0.08978296), |δp|=3e-04, [converged], δ = (-1, 0), step = 77, eigenelements in eig[ 78], ind_ev = 8\n- # 14, bp at l ≈ -0.08976771 ∈ (-0.08977278, -0.08976771), |δp|=5e-06, [converged], δ = (-1, 0), step = 78, eigenelements in eig[ 79], ind_ev = 7\n- # 15, bp at l ≈ -0.07014208 ∈ (-0.07145756, -0.07014208), |δp|=1e-03, [converged], δ = (-1, 0), step = 82, eigenelements in eig[ 83], ind_ev = 6\n- # 16, bp at l ≈ -0.06091464 ∈ (-0.06223456, -0.06091464), |δp|=1e-03, [converged], δ = (-1, 0), step = 84, eigenelements in eig[ 85], ind_ev = 5\n- # 17, bp at l ≈ -0.05306984 ∈ (-0.05315247, -0.05306984), |δp|=8e-05, [converged], δ = (-1, 0), step = 86, eigenelements in eig[ 87], ind_ev = 4\n- # 18, bp at l ≈ -0.02468398 ∈ (-0.02534143, -0.02468398), |δp|=7e-04, [converged], δ = (-1, 0), step = 92, eigenelements in eig[ 93], ind_ev = 3\n- # 19, bp at l ≈ -0.00509751 ∈ (-0.00639292, -0.00509751), |δp|=1e-03, [converged], δ = (-1, 0), step = 96, eigenelements in eig[ 97], ind_ev = 2\n- # 20, bp at l ≈ +0.00000000 ∈ (-0.00509751, +0.00000000), |δp|=5e-03, [ guess], δ = (-1, 0), step = 97, eigenelements in eig[ 98], ind_ev = 1","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We get the following plot during computation:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials2/#Snaking-computed-with-deflation","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"Snaking computed with deflation","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We know that there is snaking near the left fold. Let us look for other solutions like fronts. The problem is that if the guess is not precise enough, the newton iterations will converge to the solution with hexagons sol_hexa. We appeal to the technique initiated by P. Farrell and use a deflated problem (see DeflationOperator and DeflatedProblem for more information). More precisely, we apply the newton iterations to the following functional uto Pi_i=1^n_sleft( u-sol_hexai^-p + sigmaright)F_sh(u) which penalizes sol_hexa.","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"# this define the above penalizing factor with p=2, sigma=1, norm associated to dot\n# and the set of sol_{hexa} is of length ns=1\ndeflationOp = DeflationOperator(2, 1.0, [sol_hexa.u])\noptnewton = @set optnewton.max_iterations = 250\noutdef = newton(\n\t\t\t\tre_make(prob, u0 = 0.2vec(sol_hexa.u) .* vec([exp.(-(x+lx)^2/25) for x in X, y in Y])),\n\t\t\t\tdeflationOp,\n\t\t\t\toptnewton, normN = norminf)\nheatmapsol(outdef.u) |> display\nBK.converged(outdef) && push!(deflationOp, outdef.u)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"which gives:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Note that push!(deflationOp, outdef) deflates the newly found solution so that by repeating the process we find another one:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"outdef = newton(\n\t\t\t\tre_make(prob, u0 = 0.2vec(sol_hexa.u) .* vec([exp.(-(x)^2/25) for x in X, y in Y])),\n\t\t\t\tdeflationOp, optnewton, normN = norminf)\nheatmapsol(outdef.u) |> display\nBK.converged(outdef) && push!(deflationOp, outdef.u)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Again, repeating this from random guesses, we find several more solutions, like for example","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We can now continue the solutions located in deflationOp.roots","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"br1 = @time continuation(re_make(prob, u0 = deflationOp[2]),\n\tPALC(), optcont;\n\tplot = true)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"and using plot(br, br1), we obtain:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Note that the plot provides the stability of solutions and bifurcation points. Interested readers should consult the associated file example/SH2d-fronts.jl in the example folder.","category":"page"},{"location":"tutorials/tutorials2/#Automatic-branch-switching","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"Automatic branch switching","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Instead of relying on deflated newton, we can use Branch switching to compute the different branches emanating from the bifurcation point. For example, the following code will perform automatic branch switching from the second bifurcation point of br:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"br2 = continuation(br, 2, setproperties(optcont; ds = -0.001, detect_bifurcation = 3, plot_every_step = 5, max_steps = 170); nev = 30,\n\tplot = true, verbosity = 2,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We can then plot the branches using plot(br, br2, br3) and get","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"periodicOrbitShooting/#Periodic-orbits-based-on-the-shooting-method","page":"Shooting","title":"Periodic orbits based on the shooting method","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"A set of shooting algorithms is provided which are called either Simple Shooting (SS) if a single shooting is used and Multiple Shooting (MS) otherwise. For the exposition, we follow the PhD thesis[Lust] and also [Umbria].","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We aim at finding periodic orbits for the Cauchy problem ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"tag1 fracd xd t=f(x)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"and we write phi^t(x_0) the associated flow (or semigroup of solutions).","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"tip: Tip about convenience functions\nFor convenience, we provide some functions plotPeriodicShooting for plotting, get_amplitude (resp. get_maximum) for getting the amplitude (resp. maximum) of the solution encoded by a shooting problem. See the tutorials for examples of use.","category":"page"},{"location":"periodicOrbitShooting/#Standard-Shooting","page":"Shooting","title":"Standard Shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/#Simple-shooting","page":"Shooting","title":"Simple shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"A periodic orbit is found when we have a couple (x T) such that phi^T(x) = x and the trajectory is non constant. Therefore, we want to solve the equations G(xT)=0 given by","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"tagSS\nbeginarraylphi^T(x)-x=0 s(xT)=0endarray","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The section s(xT)=0 is a phase condition to remove the indeterminacy of the point on the limit cycle.","category":"page"},{"location":"periodicOrbitShooting/#Multiple-shooting","page":"Shooting","title":"Multiple shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"This case is similar to the previous one but more sections are used. To this end, we partition the unit interval with m+1 points 0=s_0s_1cdotss_m-1s_m=1 and consider the equations G(x_1cdotsx_mT)=0","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"beginaligned\nphi^delta s_1T(x_1)-x_2 =0 \nphi^delta s_2T(x_2)-x_3 =0 vdots \nphi^delta s_m-1T(x_m-1)-x_m =0 \nphi^delta s_mT(x_m)-x_1 =0 s(x_1 T) =0 \nendalignedtagMS","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"where delta s_i=s_i+1-s_i. The Jacobian of the system of equations w.r.t. (xT) is given by ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"mathcalJ=left(beginarrayccmathcal J_c partial_TG star dendarrayright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"where the cyclic matrix mathcal J_c is","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"mathcal J_c = \nleft(beginarrayccccc\nM_1 -I \n M_2 -I \n ddots -I \n-I M_m \nendarrayright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"and M_i=partial_xphi^delta s_i T(x_i).","category":"page"},{"location":"periodicOrbitShooting/#Section","page":"Shooting","title":"Section","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The periodic orbits solutions of (SS) or (MS) are not uniquely defined because of the phase invariance. A section s(xT)=0 (resp. s(x_1T)=0) for (SS) (resp. (MS)) must be provided. The default is the same for both $ s(x,T) = T\\cdot \\langle x-x_\\pi, \\phi\\rangle.$","category":"page"},{"location":"periodicOrbitShooting/#Encoding-of-the-functional","page":"Shooting","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The functional is encoded in the composite type ShootingProblem. In particular, the user can pass its own time stepper or one can use the different ODE solvers in DifferentialEquations.jl which makes it very easy to choose a solver tailored for the a specific problem. See the link ShootingProblem for more information ; for example on how to access the underlying functional, its jacobian...","category":"page"},{"location":"periodicOrbitShooting/#Poincaré-shooting","page":"Shooting","title":"Poincaré shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The algorithm is based on the one described in Newton–Krylov Continuation of Periodic Orbits for Navier–Stokes Flows., Sánchez, J., M. Net, B. Garcı́a-Archilla, and C. Simó (2004) and Matrix-Free Continuation of Limit Cycles for Bifurcation Analysis of Large Thermoacoustic Systems. Waugh, Iain, Simon Illingworth, and Matthew Juniper (2013). ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We look for periodic orbits solutions of (1) using the hyperplanes Sigma_i=x langle x-x^c_I n_irangle=0 for i=1cdotsM, centered on x^c_i, which intersect transversally an initial periodic orbit guess. We write Pi_iSigma_itoSigma_mod(i+1M), the Poincaré return map to Sigma_mod(i+1M). The main idea of the algorithm is to use the fact that the problem is (N-1)cdot M dimensional if x_iinmathbb R^N because each x_i lives in Sigma_i. Hence, one has to constrain the unknowns to these hyperplanes otherwise the Newton algorithm does not converge well.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We thus need to parametrize these hyperplanes.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"To this end, we introduce the projection operator R_imathbb R^Nto mathbb R^N-1 such that ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"R_ileft(x_1 x_2 ldots x_k_i-1 x_k_i x_k_i+1 ldots x_Nright)=left(x_1 x_2 ldots x_k_i-1 x_k_i+1 ldots x_Nright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"where k_i=argmax_p n_ip. The inverse operator E_imathbb R^N-1toSigma_i is defined by (where bar x=R_i(x))","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"E_i(bar x) = E_ileft(x_1 x_2 ldots x_k_i-1 x_k_i+1 ldots x_Nright)=\nleft(x_1 x_2 ldots x_k_i-1 x^c_ik_i-fracbarn_i cdotleft(overlinex-overlinex^c_iright)n_ik_i x_k_i+1 ldots x_Nright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We note that R_icirc E_i = I_mathbb R^N-1 and E_icirc R_i = I_mathbb R^N.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We then look for solutions of the following problem:","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"beginaligned \nbar x_1 - R_MPi_M(E_M(bar x_M))=0 \nbar x_2 - R_1Pi_1(E_i(bar x_1))=0 vdots \nbar x_M - R_M-1Pi_M-1(E_M-1(bar x_M-1))=0 \nendaligned","category":"page"},{"location":"periodicOrbitShooting/#Encoding-of-the-functional-2","page":"Shooting","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The functional is encoded in the composite type PoincareShootingProblem. In particular, the user can pass their own time stepper or he can use the different ODE solvers in DifferentialEquations.jl which makes it very easy to choose a tailored solver: the partial Poincaré return maps are implemented using callbacks. See the link PoincareShootingProblem for more information, in particular on how to access the underlying functional, its jacobian...","category":"page"},{"location":"periodicOrbitShooting/#Floquet-multipliers-computation","page":"Shooting","title":"Floquet multipliers computation","text":"","category":"section"},{"location":"periodicOrbitShooting/#Standard-shooting","page":"Shooting","title":"Standard shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The Floquet multipliers are computed as the eigenvalues of the monodromy matrix M=M_Mcdots M_1.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"Unlike the case with Finite differences, the matrices M_i are not sparse.","category":"page"},{"location":"periodicOrbitShooting/#Poincaré-shooting-2","page":"Shooting","title":"Poincaré shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The (non trivial) Floquet exponents are eigenvalues of the Poincaré return map PiSigma_1toSigma_1. We have Pi = Pi_McircPi_M-1circcdotscircPi_2circPi_1. Its differential is thus","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"dPi(x)cdot h = dPi_M(x_M)dPi_M-1(x_M-1)cdots dPi_1(x_1)cdot h","category":"page"},{"location":"periodicOrbitShooting/#Numerical-method","page":"Shooting","title":"Numerical method","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We provide two methods to compute the Floquet coefficients.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"A not very precise algorithm for computing the Floquet multipliers is provided. The method, dubbed Quick and Dirty (QaD), is not numerically very precise for large / small Floquet exponents. ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"It amounts to computing the eigenvalues of M=M_Mcdots M_1 (resp. dPi) for the Standard (resp. Poincaré) Shooting. The method allows, nevertheless, to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. For more information, have a look at FloquetQaD.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbitShooting/#Computation-with-newton","page":"Shooting","title":"Computation with newton","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We provide a simplified call to newton to locate the periodic orbit. Have a look at the tutorial Continuation of periodic orbits (Standard Shooting) for a simple example on how to use the above methods. ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The docs for this specific newton are located at newton.","category":"page"},{"location":"periodicOrbitShooting/#Computation-with-newton-and-deflation","page":"Shooting","title":"Computation with newton and deflation","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We also provide a simplified call to newton to locate the periodic orbit with a deflation operator:","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"newton(prob::BifurcationKit.AbstractShootingProblem,\n\t\t\t\torbitguess,\n\t\t\t\toptions::NewtonPar;\n\t\t\t\tlens::Union{Setfield.Lens, Nothing} = nothing,\n\t\t\t\tkwargs...)","category":"page"},{"location":"periodicOrbitShooting/#BifurcationKit.newton-Tuple{AbstractShootingProblem, Any, NewtonPar}","page":"Shooting","title":"BifurcationKit.newton","text":"newton(prob, orbitguess, options; lens, δ, kwargs...)\n\n\nThis is the Newton-Krylov Solver for computing a periodic orbit using the (Standard / Poincaré) Shooting method. Note that the linear solver has to be appropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is either a ShootingProblem or a PoincareShootingProblem. These two problems have specific options to be tuned, we refer to their link for more information and to the tutorials.\n\nprob a problem of type <: AbstractShootingProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit. See ShootingProblem and See PoincareShootingProblem for information regarding the shape of orbitguess.\npar parameters to be passed to the functional\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"and","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"newton(prob::BifurcationKit.AbstractShootingProblem,\n\t\t\t\torbitguess::vectype,\n\t\t\t\tdefOp::DeflationOperator{Tp, Tdot, T, vectype},\n\t\t\t\toptions::NewtonPar{T, S, E};\n\t\t\t\tlens::Union{Lens, Nothing} = nothing,\n\t\t\t\tkwargs...,\n\t\t\t) where {T, Tp, Tdot, vectype, S, E}","category":"page"},{"location":"periodicOrbitShooting/#Continuation","page":"Shooting","title":"Continuation","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"Have a look at the Continuation of periodic orbits (Standard Shooting) example for the Brusselator.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"In order to plot the orbit during continuation, one has to recompute the orbit inside a plotSolution function passed to continuation. This is simplified by the function get_periodic_orbit which returns a solution to be plotted. We refer to Period doubling in Lur'e problem for an example of use.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The docs for this specific continuation are located at continuation.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"continuation(probPO::BifurcationKit.AbstractShootingProblem, orbitguess,\n\t\t\t\t\t\talg::BifurcationKit.AbstractContinuationAlgorithm,\n\t\t\t\t\t\tcontParams::ContinuationPar,\n\t\t\t\t\t\tlinear_algo::BifurcationKit.AbstractBorderedLinearSolver;\n\t\t\t\t\t\tδ = convert(eltype(orbitguess), 1e-8),\n\t\t\t\t\t\tkwargs...,\n\t\t\t\t\t)","category":"page"},{"location":"periodicOrbitShooting/#BifurcationKit.continuation-Tuple{AbstractShootingProblem, Any, BifurcationKit.AbstractContinuationAlgorithm, ContinuationPar, BifurcationKit.AbstractBorderedLinearSolver}","page":"Shooting","title":"BifurcationKit.continuation","text":"continuation(\n probPO,\n orbitguess,\n alg,\n contParams,\n linear_algo;\n δ,\n eigsolver,\n record_from_solution,\n plot_solution,\n kwargs...\n)\n\n\nThis is the continuation method for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to continuation except that probPO is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.\n\nOptional arguments\n\neigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitShooting/#References","page":"Shooting","title":"References","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"[Lust]: Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust Kurt, 1997. ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"[Umbria]: J. S. Umbría and M. Net. Numerical continuation methods for large-scale dissipative dynamical systems. The European Physical Journal Special Topics, 225(13):2465–2486, 2016.","category":"page"},{"location":"codim2Continuation/#Fold-/-Hopf-Continuation","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Pages = [\"codim2Continuation.md\"]\nDepth = 2","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"In this page, we explain how to perform continuation of Fold / Hopf points and detect the associated bifurcations.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"For this to work best, it is advised to have an analytical expression for the jacobian. See the tutorial Temperature model for more details although BifurcationProblem implement it with AD by default.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"A quite complete example for detection of codim 2 bifurcations of equilibria is Extended Lorenz-84 model (codim 2 + BT/ZH aBS).","category":"page"},{"location":"codim2Continuation/#List-of-detected-codim-2-bifurcation-points","page":"Fold / Hopf Continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Bifurcation symbol used\nBogdanov-Takens bt\nBautin gh\nCusp cusp\nZero-Hopf zh\nHopf-Hopf hh","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"codim2Continuation/#Fold-continuation","page":"Fold / Hopf Continuation (2 params)","title":"Fold continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"The continuation of Fold bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities. The continuation of Fold points is based on the formulation","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"G(up) = (F(up) sigma(up))inmathbb R^n+1quadquad (F_f)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where the test function sigma is solution of","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarraycc\ndF(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(up)\nendarrayright=leftbeginarrayc0_n 1endarrayrightquadquad (M_f)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where wv are chosen in order to have a non-singular matrix (M_f). More precisely, v (resp. w) should be close to a null vector of dF(u,p) (resp. dF(u,p)'). During continuation, the vectors wv are updated so that the matrix (M_f) remains non-singular ; this is controlled with the argument update_minaug_every_step (see below).","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"note that there are very simplified calls for this, see Newton refinement below. In particular, you don't need to set up the Fold Minimally Augmented problem yourself. This is done in the background.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"warning: Linear Method\nYou can pass the bordered linear solver to solve (M_f) using the option bdlinsolver (see below). Note that the choice bdlinsolver = BorderingBLS() can lead to singular systems. Indeed, in this case, (M_f) is solved by inverting dF(u,p) which is singular at Fold points.","category":"page"},{"location":"codim2Continuation/#Detection-of-codim-2-bifurcation-points","page":"Fold / Hopf Continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the option detect_codim2_bifurcation in the method continuation. Under the hood, the detection of these bifurcations is done by using Event detection as explained in Event Handling.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"the detection of Cusp (Cusp) is done by the detection of Fold bifurcation points along the curve of Folds by monitoring the parameter component of the tangent.\nthe detection of Bogdanov-Takens (BT) is performed using the test function[Bindel] psi_BT(p) = langle w(p)v(p)rangle\nthe detection of Zero-Hopf (ZH) is performed by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"codim2Continuation/#Hopf-continuation","page":"Fold / Hopf Continuation (2 params)","title":"Hopf continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"The continuation of Fold bifurcation points is based on a Minimally Augmented (see [Govaerts] p. 87) formulation which is an efficient way to detect singularities. The continuation of Hopf points is based on the formulation","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"G(uomegap) = (F(uomegap) Resigma(uomegap) Imsigma(uomegap))inmathbb R^n+2quadquad (F_h)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where the test function sigma is solution of","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarraycc\ndF(up)-iomega I_n w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(uomegap)\nendarrayright=leftbeginarrayc\n0_n \n1\nendarrayrightquadquad (M_h)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where wv are chosen in order to have a non-singular matrix (M_h). More precisely, w (resp. v) should be a left (resp. right) approximate null vector of dF(up)-iomega I_n. During continuation, the vectors wv are updated so that the matrix (M_h) remains non-singular ; this is controlled with the argument update_minaug_every_step (see below).","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"note that there are very simplified calls to this, see Newton refinement below. In particular, you don't need to set up the Hopf Minimally Augmented problem yourself. This is done in the background.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"warning: Linear Method\nYou can pass the bordered linear solver to solve (M_h) using the option bdlinsolver (see below). Note that the choice bdlinsolver = BorderingBLS() can lead to singular systems. Indeed, in this case, (M_h) is solved by inverting dF(u,p)-iω I_n which is singular at Hopf points.","category":"page"},{"location":"codim2Continuation/#Detection-of-codim-2-bifurcation-points-2","page":"Fold / Hopf Continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the option detect_codim2_bifurcation in the method continuation. Under the hood, the detection of these bifurcations is done by using Event detection as explained in Event Handling.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"the detection of Bogdanov-Takens (BT) is performed using the test function[Bindel],[Blank] psi_BT(p) = \tlangle w(p)v(p)rangle\nthe detection of Bautin (GH) is based on the test function psi_GH(p) = Re(l_1(p)) where l_1 is the Lyapunov coefficient defined in Simple Hopf point.\nthe detection of Zero-Hopf (ZH) is performed by monitoring the eigenvalues.\nthe detection of Hopf-Hopf (HH) is performed by monitoring the eigenvalues.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"The continuation of Hopf points is stopped at BT and when omega100epsilon where epsilon is the newton tolerance.","category":"page"},{"location":"codim2Continuation/#jac-fold","page":"Fold / Hopf Continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"In order to apply the newton algorithm to F_f or F_h, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to F_f (or F_h) and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian F_f (or F_h) and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"codim2Continuation/#Newton-refinement","page":"Fold / Hopf Continuation (2 params)","title":"Newton refinement","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Once a Fold / Hopf point has been detected after a call to br = continuation(...), it can be refined using newton iterations. Let us say that ind_bif is the index in br.specialpoint of a Fold / Hopf point. This guess can be refined as follows:","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"outfold = newton(br::AbstractBranchResult, ind_bif::Int; \n\tnormN = norm, options = br.contparams.newton_options,\n\tbdlinsolver = BorderingBLS(options.linsolver),\n\tstart_with_eigen = false, kwargs...)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"For the options parameters, we refer to Newton.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"It is important to note that for improved performances, a function implementing the expression of the hessian should be provided. This is by far the fastest. BifurcationProblem provides it by default using AD though.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Reader interested in this advanced usage should look at the code example/chan.jl of the tutorial Temperature model.","category":"page"},{"location":"codim2Continuation/#Codim-2-continuation","page":"Fold / Hopf Continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"To compute the codim 2 curve of Fold / Hopf points, one can call continuation with the following options","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"See Temperature model for an example of use.","category":"page"},{"location":"codim2Continuation/#Advanced-use","page":"Fold / Hopf Continuation (2 params)","title":"Advanced use","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Here, we expose the solvers that are used to perform newton refinement or codim 2 continuation in case the above methods fails. This is useful in case it is too involved to expose the linear solver options. An example of advanced use is the continuation of Folds of periodic orbits, see Continuation of Fold of periodic orbits.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"newton_fold","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"newton_hopf","category":"page"},{"location":"codim2Continuation/#BifurcationKit.newton_hopf","page":"Fold / Hopf Continuation (2 params)","title":"BifurcationKit.newton_hopf","text":"newton_hopf(\n prob,\n hopfpointguess,\n par,\n eigenvec,\n eigenvec_ad,\n options;\n normN,\n bdlinsolver,\n usehessian,\n kwargs...\n)\n\n\nThis function turns an initial guess for a Hopf point into a solution to the Hopf problem based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationProblem where p is a set of parameters.\nhopfpointguess initial guess (x0, p0) for the Hopf point. It should a BorderedArray as returned by the function HopfPoint.\npar parameters used for the vector field\neigenvec guess for the iω eigenvector\neigenvec_ad guess for the -iω eigenvector\noptions::NewtonPar options for the Newton-Krylov algorithm, see NewtonPar.\n\nOptional arguments:\n\nnormN = norm\nbdlinsolver bordered linear solver for the constraint equation\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\nSimplified call:\n\nSimplified call to refine an initial guess for a Hopf point. More precisely, the call is as follows\n\nnewton_hopf(br::AbstractBranchResult, ind_hopf::Int; normN = norm, options = br.contparams.newton_options, kwargs...)\n\nThe parameters / options are as usual except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of bifurcation point in br you want to refine. You can pass newton parameters different from the ones stored in br by using the argument options.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian will be computed twice!\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\n\n\n\n\n","category":"function"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"continuation_fold","category":"page"},{"location":"codim2Continuation/#BifurcationKit.continuation_fold","page":"Fold / Hopf Continuation (2 params)","title":"BifurcationKit.continuation_fold","text":"continuation_fold(\n prob,\n alg,\n foldpointguess,\n par,\n lens1,\n lens2,\n eigenvec,\n eigenvec_ad,\n options_cont;\n update_minaug_every_step,\n normC,\n bdlinsolver,\n bdlinsolver_adjoint,\n jacobian_ma,\n compute_eigen_elements,\n usehessian,\n kind,\n record_from_solution,\n kwargs...\n)\n\n\nCodim 2 continuation of Fold points. This function turns an initial guess for a Fold point into a curve of Fold points based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationFunction\nfoldpointguess initial guess (x0, p10) for the Fold point. It should be a BorderedArray as returned by the function FoldPoint\npar set of parameters\nlens1 parameter axis for parameter 1\nlens2 parameter axis for parameter 2\neigenvec guess for the 0 eigenvector at p1_0\neigenvec_ad guess for the 0 adjoint eigenvector\noptions_cont arguments to be passed to the regular continuation\n\nOptional arguments:\n\njacobian_ma::Symbol = :autodiff, how the linear system of the Fold problem is solved. Can be :autodiff, :finiteDifferencesMF, :finiteDifferences, :minaug\nbdlinsolver bordered linear solver for the constraint equation with top-left block J. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nbdlinsolver_adjoint bordered linear solver for the constraint equation with top-left block J^*. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nupdate_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps\ncompute_eigen_elements = false whether to compute eigenelements. If options_cont.detect_event>0, it allows the detection of ZH points.\nkwargs keywords arguments to be passed to the regular continuation\n\nSimplified call\n\ncontinuation_fold(br::AbstractBranchResult, ind_fold::Int64, lens2::Lens, options_cont::ContinuationPar ; kwargs...)\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Fold point in br that you want to continue.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian would be computed twice!\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS(). This is the default setting.\n\ntip: Detection of Bogdanov-Takens and Cusp bifurcations\nIn order to trigger the detection, pass detect_event = 1,2 in options_cont.\n\n\n\n\n\n","category":"function"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"continuation_hopf","category":"page"},{"location":"codim2Continuation/#BifurcationKit.continuation_hopf","page":"Fold / Hopf Continuation (2 params)","title":"BifurcationKit.continuation_hopf","text":"continuation_hopf(\n prob_vf,\n alg,\n hopfpointguess,\n par,\n lens1,\n lens2,\n eigenvec,\n eigenvec_ad,\n options_cont;\n update_minaug_every_step,\n normC,\n linsolve_adjoint,\n bdlinsolver,\n bdlinsolver_adjoint,\n jacobian_ma,\n compute_eigen_elements,\n usehessian,\n kind,\n massmatrix,\n record_from_solution,\n kwargs...\n)\n\n\ncodim 2 continuation of Hopf points. This function turns an initial guess for a Hopf point into a curve of Hopf points based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationProblem\nhopfpointguess initial guess (x0, p10) for the Hopf point. It should be a Vector or a BorderedArray\npar set of parameters\nlens1 parameter axis for parameter 1\nlens2 parameter axis for parameter 2\neigenvec guess for the iω eigenvector at p1_0\neigenvec_ad guess for the -iω eigenvector at p1_0\noptions_cont keywords arguments to be passed to the regular continuation\n\nOptional arguments:\n\njacobian_ma::Symbol = :autodiff, how the linear system of the Fold problem is solved. Can be :autodiff, :finiteDifferencesMF, :finiteDifferences, :minaug\nlinsolve_adjoint solver for (J+iω)^* ⋅sol = rhs\nbdlinsolver bordered linear solver for the constraint equation with top-left block (J-iω). Required in the linear solver for the Minimally Augmented Hopf functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nbdlinsolver_adjoint bordered linear solver for the constraint equation with top-left block (J-iω)^*. Required in the linear solver for the Minimally Augmented Hopf functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nupdate_minaug_every_step update vectors a,b in Minimally Formulation every update_minaug_every_step steps\ncompute_eigen_elements = false whether to compute eigenelements. If options_cont.detect_event>0, it allows the detection of ZH, HH points.\nkwargs keywords arguments to be passed to the regular continuation\n\nSimplified call:\n\ncontinuation_hopf(br::AbstractBranchResult, ind_hopf::Int, lens2::Lens, options_cont::ContinuationPar ; kwargs...)\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br that you want to refine.\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS(). This is the default setting.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian would be computed twice!\n\ntip: Detection of Bogdanov-Takens and Bautin bifurcations\nIn order to trigger the detection, pass detect_event = 1,2 in options_cont. Note that you need to provide d3F in prob.\n\n\n\n\n\n","category":"function"},{"location":"codim2Continuation/#Algorithmic-details-(Fold)","page":"Fold / Hopf Continuation (2 params)","title":"Algorithmic details (Fold)","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"If we write (ssigma) the solution of the adjoint problem associated to (M_f), one can show[Govaerts] that the differential of sigma satisfies:","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"partial sigma + langle spartial dF cdot rrangle = 0","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"This allows to compute the jacobian of the Fold functional to use for the Newton algorithm:","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarraycc\npartial_uF(up) partial_pF(up) \npartial_xsigma(up) partial_psigma(up)\nendarrayright","category":"page"},{"location":"codim2Continuation/#Algorithmic-details-(Hopf)","page":"Fold / Hopf Continuation (2 params)","title":"Algorithmic details (Hopf)","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"We recall that the unknowns are (xpomega). The jacobian of the Hopf functional to use for the Newton algorithm is","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarrayccc\npartial_uF partial_pF 0 \npartial_xsigma_r partial_psigma_r partial_omegasigma_r\npartial_xsigma_i partial_psigma_i partial_omegasigma_i\nendarrayright","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"using a similar formula for partialsigma as in the Fold case.","category":"page"},{"location":"codim2Continuation/#References","page":"Fold / Hopf Continuation (2 params)","title":"References","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Blank]: Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Bindel]: Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.","category":"page"},{"location":"library/#Library","page":"Library","title":"Library","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"Pages = [\"library.md\"]\nDepth = 3","category":"page"},{"location":"library/#Parameters","page":"Library","title":"Parameters","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"NewtonPar","category":"page"},{"location":"library/#BifurcationKit.NewtonPar","page":"Library","title":"BifurcationKit.NewtonPar","text":"struct NewtonPar{T, L<:BifurcationKit.AbstractLinearSolver, E<:AbstractEigenSolver}\n\nReturns a variable containing parameters to affect the newton algorithm when solving F(x) = 0.\n\nArguments (with default values):\n\ntol::Any: absolute tolerance for F(x) Default: 1.0e-12\nmax_iterations::Int64: number of Newton iterations Default: 25\nverbose::Bool: display Newton iterations? Default: false\nlinsolver::BifurcationKit.AbstractLinearSolver: linear solver, must be <: AbstractLinearSolver Default: DefaultLS()\neigsolver::AbstractEigenSolver: eigen solver, must be <: AbstractEigenSolver Default: DefaultEig()\nlinesearch::Bool: Default: false\nα::Any: Default: convert(typeof(tol), 1.0)\nαmin::Any: Default: convert(typeof(tol), 0.001)\n\nArguments for line search (Armijo)\n\nlinesearch = false: use line search algorithm (i.e. Newton with Armijo's rule)\nα = 1.0: initial value of α (damping) parameter for line search algorithm\nαmin = 0.001: minimal value of the damping alpha\n\ntip: Mutating\nFor performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See the tutorials for examples.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"ContinuationPar","category":"page"},{"location":"library/#BifurcationKit.ContinuationPar","page":"Library","title":"BifurcationKit.ContinuationPar","text":"options = ContinuationPar(dsmin = 1e-4,...)\n\nReturns a variable containing parameters to affect the continuation algorithm used to solve F(x,p) = 0.\n\nArguments\n\ndsmin, dsmax are the minimum, maximum arclength allowed value. It controls the density of points in the computed branch of solutions.\nds = 0.01 is the initial arclength.\np_min, p_max allowed parameter range for p\nmax_steps = 100 maximum number of continuation steps\nnewton_options::NewtonPar: options for the Newton algorithm\nsave_to_file = false: save to file. A name is automatically generated or can be defined in continuation. This requires using JLD2.\nsave_sol_every_step::Int64 = 0 at which continuation steps do we save the current solution\nplot_every_step = 10 at which continuation steps do we plot the current solution\n\nHandling eigen elements, their computation is triggered by the argument detect_bifurcation (see below)\n\nnev = 3 number of eigenvalues to be computed. It is automatically increased to have at least nev unstable eigenvalues. To be set for proper bifurcation detection. See Detection of bifurcation points of Equilibria for more informations.\nsave_eig_every_step = 1 record eigen vectors every specified steps. Important for memory limited resource, e.g. GPU.\nsave_eigenvectors = true Important for memory limited resource, e.g. GPU.\n\nHandling bifurcation detection\n\ntol_stability = 1e-10 lower bound on the real part of the eigenvalues to test for stability of equilibria and periodic orbits\ndetect_fold = true detect Fold bifurcations? It is a useful option although the detection of Fold is cheap. Indeed, it may happen that there is a lot of Fold points and this can saturate the memory in memory limited devices (e.g. on GPU)\ndetect_bifurcation::Int ∈ {0, 1, 2, 3} If set to 0, nothing is done. If set to 1, the eigen-elements are computed. If set to 2, the bifurcations points are detected during the continuation run, but not located precisely. If set to 3, a bisection algorithm is used to locate the bifurcations points (slower). The possibility to switch off detection is a useful option. Indeed, it may happen that there are a lot of bifurcation points and this can saturate the memory of memory limited devices (e.g. on GPU)\ndsmin_bisection = 1e-16 dsmin for the bisection algorithm for locating bifurcation points\nn_inversion = 2 number of sign inversions in bisection algorithm\nmax_bisection_steps = 15 maximum number of bisection steps\ntol_bisection_eigenvalue = 1e-16 tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps\n\nHandling ds adaptation (see continuation for more information)\n\na = 0.5 aggressiveness factor. It is used to adapt ds in order to have a number of newton iterations per continuation step roughly constant. The higher a is, the larger the step size ds is changed at each continuation step.\n\nHandling event detection\n\ndetect_event::Int ∈ {0, 1, 2} If set to 0, nothing is done. If set to 1, the event locations are sought during the continuation run, but not located precisely. If set to 2, a bisection algorithm is used to locate the event (slower).\ntol_param_bisection_event = 1e-16 tolerance on parameter to locate event\n\nMisc\n\nη = 150. parameter to estimate tangent at first point with parameter p₀ + ds / η\ndetect_loop [WORK IN PROGRESS] detect loops in the branch and stop the continuation\n\ntip: Mutating\nFor performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See tutorials for more examples.\n\n\n\n\n\n","category":"type"},{"location":"library/#Results","page":"Library","title":"Results","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"NonLinearSolution","category":"page"},{"location":"library/#BifurcationKit.NonLinearSolution","page":"Library","title":"BifurcationKit.NonLinearSolution","text":"Structure which holds the solution from application of Newton-Krylov algorithm to a nonlinear problem.\n\nFor example\n\nsol = newton(prob, NewtonPar())\n\nFields\n\nu::Any: solution\nprob::Any: nonlinear problem, typically a BifurcationProblem\nresiduals::Any: sequence of residuals\nconverged::Bool: has algorithm converged?\nitnewton::Int64: number of newton steps\nitlineartot::Any: total number of linear iterations\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"ContResult","category":"page"},{"location":"library/#BifurcationKit.ContResult","page":"Library","title":"BifurcationKit.ContResult","text":"struct ContResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tbr, Teigvals, Teigvec, Biftype, Tsol, Tparc, Tprob, Talg} <: BifurcationKit.AbstractResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tprob}\n\nStructure which holds the results after a call to continuation.\n\nYou can see the propertynames of a result br by using propertynames(br) or propertynames(br.branch).\n\nFields\n\nbranch::StructArrays.StructArray: holds the low-dimensional information about the branch. More precisely, branch[i+1] contains the following information (record_from_solution(u, param), param, itnewton, itlinear, ds, θ, n_unstable, n_imag, stable, step) for each continuation step i.\nitnewton number of Newton iterations\nitlinear total number of linear iterations during newton (corrector)\nn_unstable number of eigenvalues with positive real part for each continuation step (to detect stationary bifurcation)\nn_imag number of eigenvalues with positive real part and non zero imaginary part at current continuation step (useful to detect Hopf bifurcation).\nstable stability of the computed solution for each continuation step. Hence, stable should match eig[step] which corresponds to branch[k] for a given k.\nstep continuation step (here equal i)\neig::Array{NamedTuple{(:eigenvals, :eigenvecs, :converged, :step), Tuple{Teigvals, Teigvec, Bool, Int64}}, 1} where {Teigvals, Teigvec}: A vector with eigen-elements at each continuation step.\nsol::Any: Vector of solutions sampled along the branch. This is set by the argument save_sol_every_step::Int64 (default 0) in ContinuationPar.\ncontparams::Any: The parameters used for the call to continuation which produced this branch. Must be a ContinuationPar\nkind::BifurcationKit.AbstractContinuationKind: Type of solutions computed in this branch. Default: EquilibriumCont()\nprob::Any: Bifurcation problem used to compute the branch, useful for branch switching. For example, when computing periodic orbits, the functional PeriodicOrbitTrapProblem, ShootingProblem... will be saved here. Default: nothing\nspecialpoint::Vector: A vector holding the set of detected bifurcation points. See SpecialPoint for a list of special points.\nalg::Any: Continuation algorithm used for the computation of the branch\n\nAssociated methods\n\nlength(br) number of the continuation steps\nshow(br) display information about the branch\neigenvals(br, ind) returns the eigenvalues for the ind-th continuation step\neigenvec(br, ind, indev) returns the indev-th eigenvector for the ind-th continuation step\nget_normal_form(br, ind) compute the normal form of the ind-th points in br.specialpoint\ngetlens(br) return the parameter axis used for the branch\ngetlenses(br) return the parameter two axis used for the branch when 2 parameters continuation is used (Fold, Hopf, NS, PD)\nbr[k+1] gives information about the k-th step. A typical run yields the following\n\njulia> br[1]\n(x = 0.0, param = 0.1, itnewton = 0, itlinear = 0, ds = -0.01, θ = 0.5, n_unstable = 2, n_imag = 2, stable = false, step = 0, eigenvals = ComplexF64[0.1 - 1.0im, 0.1 + 1.0im], eigenvecs = ComplexF64[0.7071067811865475 - 0.0im 0.7071067811865475 + 0.0im; 0.0 + 0.7071067811865475im 0.0 - 0.7071067811865475im])\n\nwhich provides the value param of the parameter of the current point, its stability, information on the newton iterations, etc. The fields can be retrieved using propertynames(br.branch). This information is stored in br.branch which is a StructArray. You can thus extract the vector of parameters along the branch as\n\njulia> br.param\n10-element Vector{Float64}:\n 0.1\n 0.08585786437626905\n 0.06464466094067263\n 0.03282485578727799\n-1.2623798512809007e-5\n-0.07160718539365075\n-0.17899902778635765\n-0.3204203840236672\n-0.4618417402609767\n-0.5\n\nget_solx(br, k) returns the k-th solution on the branch\nget_solp(br, k) returns the parameter value associated with k-th solution on the branch\ngetparams(br) Parameters passed to continuation and used in the equation F(x, par) = 0.\nsetparam(br, p0) set the parameter value p0 according to ::Lens for the parameters of the problem br.prob\ngetlens(br) get the lens used for the computation of the branch\ncontinuation(br, ind) performs automatic branch switching (aBS) from ind-th bifurcation point. Typically branching from equilibrium to equilibrium, or periodic orbit to periodic orbit.\ncontinuation(br, ind, lens2) performs two parameters (getLens(br), lens2) continuation of the ind-th bifurcation point.\ncontinuation(br, ind, probPO::AbstractPeriodicOrbitProblem) performs aBS from ind-th bifurcation point (which must be a Hopf bifurcation point) to branch of periodic orbits.\n\n\n\n\n\n","category":"type"},{"location":"library/#Problems","page":"Library","title":"Problems","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifFunction","category":"page"},{"location":"library/#BifurcationKit.BifFunction","page":"Library","title":"BifurcationKit.BifFunction","text":"struct BifFunction{Tf, Tdf, Tdfad, Tj, Tjad, Td2f, Td2fc, Td3f, Td3fc, Tsym, Tδ} <: BifurcationKit.AbstractBifurcationFunction\n\nStructure to hold the vector field and its derivatives. It should rarely be called directly. Also, in essence, it is very close to SciMLBase.ODEFunction.\n\nFields\n\nF::Any: Vector field. Function of type out-of-place result = f(x, p) or inplace f(result, x, p). For type stability, the types of x and result should match\ndF::Any: Differential of F with respect to x, signature dF(x,p,dx)\ndFad::Any: Adjoint of the Differential of F with respect to x, signature dFad(x,p,dx)\nJ::Any: Jacobian of F at (x, p). It can assume three forms. 1. Either J is a function and J(x, p) returns a ::AbstractMatrix. In this case, the default arguments of contparams::ContinuationPar will make continuation work. 2. Or J is a function and J(x, p) returns a function taking one argument dx and returning dr of the same type as dx. In our notation, dr = J * dx. In this case, the default parameters of contparams::ContinuationPar will not work and you have to use a Matrix Free linear solver, for example GMRESIterativeSolvers, 3. Or J is a function and J(x, p) returns a variable j which can assume any type. Then, you must implement a linear solver ls as a composite type, subtype of AbstractLinearSolver which is called like ls(j, rhs) and which returns the solution of the jacobian linear system. See for example examples/SH2d-fronts-cuda.jl. This linear solver is passed to NewtonPar(linsolver = ls) which itself passed to ContinuationPar. Similarly, you have to implement an eigensolver eig as a composite type, subtype of AbstractEigenSolver.\nJᵗ::Any: jacobian adjoint, it should be implemented in an efficient manner. For matrix-free methods, transpose is not readily available and the user must provide a dedicated method. In the case of sparse based jacobian, Jᵗ should not be passed as it is computed internally more efficiently, i.e. it avoids recomputing the jacobian as it would be if you pass Jᵗ = (x, p) -> transpose(dF(x, p)).\nd2F::Any: Second Differential of F with respect to x, signature d2F(x,p,dx1,dx2)\nd3F::Any: Third Differential of F with respect to x, signature d3F(x,p,dx1,dx2,dx3)\nd2Fc::Any: [internal] Second Differential of F with respect to x which accept complex vectors dxi\nd3Fc::Any: [internal] Third Differential of F with respect to x which accept complex vectors dxi\nisSymmetric::Any: Whether the jacobian is auto-adjoint.\nδ::Any: used internally to compute derivatives (with finite differences), for example for normal form computation and codim 2 continuation.\ninplace::Bool: optionally sets whether the function is inplace or not\n\nMethods\n\nresidual(pb::BifFunction, x, p) calls pb.F(x,p)\njacobian(pb::BifFunction, x, p) calls pb.J(x, p)\ndF(pb::BifFunction, x, p, dx) calls pb.dF(x,p,dx)\netc\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationProblem","category":"page"},{"location":"library/#BifurcationKit.BifurcationProblem","page":"Library","title":"BifurcationKit.BifurcationProblem","text":"struct BifurcationProblem{Tvf, Tu, Tp, Tl<:Lens, Tplot, Trec} <: BifurcationKit.AbstractAllJetBifProblem\n\nStructure to hold the bifurcation problem.\n\nFields\n\nVF::Any: Vector field, typically a BifFunction\nu0::Any: Initial guess\nparams::Any: parameters\nlens::Lens: Typically a Setfield.Lens. It specifies which parameter axis among params is used for continuation. For example, if par = (α = 1.0, β = 1), we can perform continuation w.r.t. α by using lens = (@lens _.α). If you have an array par = [ 1.0, 2.0] and want to perform continuation w.r.t. the first variable, you can use lens = (@lens _[1]). For more information, we refer to SetField.jl.\nplotSolution::Any: user function to plot solutions during continuation. Signature: plot_solution(x, p; kwargs...) for Plot.jl and plot_solution(ax, x, p; kwargs...) for the Makie package(s).\nrecordFromSolution::Any: record_from_solution = (x, p) -> norm(x) function used record a few indicators about the solution. It could be norm or (x, p) -> x[1]. This is also useful when saving several huge vectors is not possible for memory reasons (for example on GPU). This function can return pretty much everything but you should keep it small. For example, you can do (x, p) -> (x1 = x[1], x2 = x[2], nrm = norm(x)) or simply (x, p) -> (sum(x), 1). This will be stored in contres.branch where contres::ContResult is the continuation curve of the bifurcation problem. Finally, the first component is used for plotting in the continuation curve.\n\nMethods\n\nre_make(pb; kwargs...) modify a bifurcation problem\ngetu0(pb) calls pb.u0\ngetparams(pb) calls pb.params\ngetlens(pb) calls pb.lens\ngetparam(pb) calls get(pb.params, pb.lens)\nsetparam(pb, p0) calls set(pb.params, pb.lens, p0)\nrecord_from_solution(pb) calls pb.recordFromSolution\nplot_solution(pb) calls pb.plotSolution\nis_symmetric(pb) calls is_symmetric(pb.prob)\n\nConstructors\n\nBifurcationProblem(F, u0, params, lens) all derivatives are computed using ForwardDiff.\nBifurcationProblem(F, u0, params, lens; J, Jᵗ, d2F, d3F, kwargs...) and kwargs are the fields above. You can pass your own jacobian with J (see BifFunction for description of the jacobian function) and jacobian adjoint with Jᵗ. For example, this can be used to provide finite differences based jacobian using BifurcationKit.finiteDifferences.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"DeflationOperator","category":"page"},{"location":"library/#BifurcationKit.DeflationOperator","page":"Library","title":"BifurcationKit.DeflationOperator","text":"struct DeflationOperator{Tp<:Real, Tdot, T<:Real, vectype} <: BifurcationKit.AbstractDeflationFactor\n\nStructure for defining a custom distance.\n\nThis operator allows to handle the following situation. Assume you want to solve F(x)=0 with a Newton algorithm but you want to avoid the process to return some already known solutions roots_i. The deflation operator penalizes these roots. You can create a DeflationOperator to define a scalar function M(u) used to find, with Newton iterations, the zeros of the following function F(u) cdot Π_i(u - root_i^-2p + alpha) = F(u) cdot M(u) where u^2 = dot(u u). The fields of the struct DeflationOperator are as follows:\n\npower::Real: power p. You can use an Int for example\ndot::Any: function, this function has to be bilinear and symmetric for the linear solver to work well\nα::Real: shift\nroots::Vector: roots\ntmp::Any\nautodiff::Bool\nδ::Real\n\nGiven defOp::DeflationOperator, one can access its roots via defOp[n] as a shortcut for defOp.roots[n]. Note that you can also use defOp[end].\n\nAlso, one can add (resp. remove) a new root by using push!(defOp, newroot) (resp. pop!(defOp)). Finally length(defOp) is a shortcut for length(defOp.roots)\n\nConstructors\n\nDeflationOperator(p::Real, α::Real, roots::Vector{vectype}; autodiff = false)\nDeflationOperator(p::Real, dt, α::Real, roots::Vector{vectype}; autodiff = false)\nDeflationOperator(p::Real, α::Real, roots::Vector{vectype}, v::vectype; autodiff = false)\n\nThe option autodiff triggers the use of automatic differentiation for the computation of the gradient of the scalar function M. This works only on AbstractVector for now.\n\nCustom distance\n\nYou are asked to pass a scalar product like dot to build a DeflationOperator. However, in some cases, you may want to pass a custom distance dist(u, v). You can do this using\n\n`DeflationOperator(p, CustomDist(dist), α, roots)`\n\nNote that passing CustomDist(dist, true) will trigger the use of automatic differentiation for the gradient of M.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"DeflatedProblem","category":"page"},{"location":"library/#BifurcationKit.DeflatedProblem","page":"Library","title":"BifurcationKit.DeflatedProblem","text":"pb = DeflatedProblem(prob, M::DeflationOperator, jactype)\n\nCreate a DeflatedProblem.\n\nThis creates a deflated functional (problem) M(u) cdot F(u) = 0 where M is a DeflationOperator which encodes the penalization term. prob is an AbstractBifurcationProblem which encodes the functional. It is not meant not be used directly albeit by advanced users.\n\n\n\n\n\n","category":"type"},{"location":"library/#Periodic-orbits","page":"Library","title":"Periodic orbits","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"PeriodicOrbitTrapProblem","category":"page"},{"location":"library/#BifurcationKit.PeriodicOrbitTrapProblem","page":"Library","title":"BifurcationKit.PeriodicOrbitTrapProblem","text":"This composite type implements Finite Differences based on a Trapezoidal rule (Order 2 in time) to locate periodic orbits. More details (maths, notations, linear systems) can be found here.\n\nFields\n\nprob a bifurcation problem\nM::Int number of time slices\nϕ used to set a section for the phase constraint equation, of size N*M\nxπ used in the section for the phase constraint equation, of size N*M\nlinsolver: = DefaultLS() linear solver for each time slice, i.e. to solve J⋅sol = rhs. This is only needed for the computation of the Floquet multipliers in a full matrix-free setting.\nongpu::Bool whether the computation takes place on the gpu (Experimental)\nmassmatrix a mass matrix. You can pass for example a sparse matrix. Default: identity matrix.\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).\n\nThe scheme is as follows. We first consider a partition of 01 given by 0s_0cdotss_m=1 and one looks for T = x[end] such that\n\nM_acdotleft(x_i - x_i-1right) - fracTcdot h_i2 left(F(x_i) + F(x_i-1)right) = 0 i=1cdotsm-1\n\nwith u_0 = u_m-1 and the periodicity condition u_m - u_1 = 0 and\n\nwhere h_1 = s_i-s_i-1. M_a is a mass matrix. Finally, the phase of the periodic orbit is constrained by using a section (but you could use your own)\n\nsum_ilangle x_i - x_pii phi_irangle=0\n\nConstructors\n\nThe structure can be created by calling PeriodicOrbitTrapProblem(;kwargs...). For example, you can declare such a problem without vector field by doing\n\nPeriodicOrbitTrapProblem(M = 100)\n\nOrbit guess\n\nYou will see below that you can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be a vector of size M * N + 1 where N is the number of unknowns in the state space and orbitguess[M*N+1] is an estimate of the period T of the limit cycle. More precisely, using the above notations, orbitguess must be orbitguess = x_1x_2cdotsx_M T.\n\nNote that you can generate this guess from a function solution using generateSolution.\n\nFunctional\n\nA functional, hereby called G, encodes this problem. The following methods are available\n\npb(orbitguess, p) evaluates the functional G on orbitguess\npb(orbitguess, p, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du\npb(Val(:JacFullSparse), orbitguess, p) return the sparse matrix of the jacobian dG(orbitguess) at orbitguess without the constraints. It is called A_γ in the docs.\npb(Val(:JacFullSparseInplace), J, orbitguess, p). Same as pb(Val(:JacFullSparse), orbitguess, p) but overwrites J inplace. Note that the sparsity pattern must be the same independently of the values of the parameters or of orbitguess. In this case, this is significantly faster than pb(Val(:JacFullSparse), orbitguess, p).\npb(Val(:JacCyclicSparse), orbitguess, p) return the sparse cyclic matrix Jc (see the docs) of the jacobian dG(orbitguess) at orbitguess\npb(Val(:BlockDiagSparse), orbitguess, p) return the diagonal of the sparse matrix of the jacobian dG(orbitguess) at orbitguess. This allows to design Jacobi preconditioner. Use blockdiag.\n\nJacobian\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\nnote: GPU call\nFor these methods to work on the GPU, for example with CuArrays in mode allowscalar(false), we face the issue that the function extract_period_fdtrap won't be well defined because it is a scalar operation. Note that you must pass the option ongpu = true for the functional to be evaluated efficiently on the gpu.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"PeriodicOrbitOCollProblem","category":"page"},{"location":"library/#BifurcationKit.PeriodicOrbitOCollProblem","page":"Library","title":"BifurcationKit.PeriodicOrbitOCollProblem","text":"pb = PeriodicOrbitOCollProblem(kwargs...)\n\nThis composite type implements an orthogonal collocation (at Gauss points) method of piecewise polynomials to locate periodic orbits. More details (maths, notations, linear systems) can be found here.\n\nArguments\n\nprob a bifurcation problem\nϕ::AbstractVector used to set a section for the phase constraint equation\nxπ::AbstractVector used in the section for the phase constraint equation\nN::Int dimension of the state space\nmesh_cache::MeshCollocationCache cache for collocation. See docs of MeshCollocationCache\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian = AutoDiffDenseAnalytical() describes the type of jacobian used in Newton iterations. Can only be AutoDiffDense(), AutoDiffDenseAnalytical(), FullSparse(), FullSparseInplace().\nmeshadapt::Bool = false whether to use mesh adaptation\nverbose_mesh_adapt::Bool = true verbose mesh adaptation information\nK::Float64 = 500 parameter for mesh adaptation, control new mesh step size\n\nMethods\n\nHere are some useful methods you can apply to pb\n\nlength(pb) gives the total number of unknowns\nsize(pb) returns the triplet (N, m, Ntst)\ngetmesh(pb) returns the mesh 0 = τ0 < ... < τNtst+1 = 1. This is useful because this mesh is born to vary during automatic mesh adaptation\nget_mesh_coll(pb) returns the (static) mesh 0 = σ0 < ... < σm+1 = 1\nget_times(pb) returns the vector of times (length 1 + m * Ntst) at the which the collocation is applied.\ngenerate_solution(pb, orbit, period) generate a guess from a function t -> orbit(t) which approximates the periodic orbit.\nPOSolution(pb, x) return a function interpolating the solution x using a piecewise polynomials function\n\nOrbit guess\n\nYou can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be of size 1 + N * (1 + m * Ntst) where N is the number of unknowns in the state space and orbitguess[end] is an estimate of the period T of the limit cycle.\n\nConstructors\n\nPeriodicOrbitOCollProblem(Ntst::Int, m::Int; kwargs) creates an empty functional with Ntst and m.\n\nNote that you can generate this guess from a function using generate_solution.\n\nFunctional\n\nA functional, hereby called G, encodes this problem. The following methods are available\n\npb(orbitguess, p) evaluates the functional G on orbitguess\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"ShootingProblem","category":"page"},{"location":"library/#BifurcationKit.ShootingProblem","page":"Library","title":"BifurcationKit.ShootingProblem","text":"pb = ShootingProblem(flow::Flow, ds, section; parallel = false)\n\nCreate a problem to implement the Standard Simple / Parallel Multiple Standard Shooting method to locate periodic orbits. More details (maths, notations, linear systems) can be found here. The arguments are as follows\n\nflow::Flow: implements the flow of the Cauchy problem though the structure Flow.\nds: vector of time differences for each shooting. Its length is written M. If M == 1, then the simple shooting is implemented and the multiple one otherwise.\nsection: implements a phase condition. The evaluation section(x, T) must return a scalar number where x is a guess for one point on the periodic orbit and T is the period of the guess. Also, the method section(x, T, dx, dT) must be available and which returns the differential of section. The type of x depends on what is passed to the newton solver. See SectionSS for a type of section defined as a hyperplane.\nparallel whether the shooting is computed in parallel (threading). Available through the use of Flows defined by EnsembleProblem (this is automatically set up for you).\npar parameters of the model\nlens parameter axis\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).\n\nA functional, hereby called G, encodes the shooting problem. For example, the following methods are available:\n\npb(orbitguess, par) evaluates the functional G on orbitguess\npb(orbitguess, par, du; δ = 1e-9) evaluates the jacobian dG(orbitguess)⋅du functional at orbitguess on du. The optional argument δ is used to compute a finite difference approximation of the derivative of the section.\npb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.\npb(Val(:JacobianMatrix), x, par) same as above but out-of-place.\n\nYou can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N + 1 where N is the number of unknowns of the state space and orbitguess[M * N + 1] is an estimate of the period T of the limit cycle. This form of guess is convenient for the use of the linear solvers in IterativeSolvers.jl (for example) which only accept AbstractVectors. Another accepted guess is of the form BorderedArray(guess, T) where guess[i] is the state of the orbit at the ith time slice. This last form allows for non-vector state space which can be convenient for 2d problems for example, use GMRESKrylovKit for the linear solver in this case.\n\nNote that you can generate this guess from a function solution using generate_solution.\n\nJacobian\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\nSimplified constructors\n\nThe first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points:\n\npb = ShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)\n\nA convenient way to build the functional is to use:\n\npb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, centers::AbstractVector; kwargs...)\n\nwhere prob is an ODEProblem (resp. EnsembleProblem) which is used to create a flow using the ODE solver alg (for example Tsit5()). centers is list of M points close to the periodic orbit, they will be used to build a constraint for the phase. parallel = false is an option to use Parallel simulations (Threading) to simulate the multiple trajectories in the case of multiple shooting. This is efficient when the trajectories are relatively long to compute. Finally, the arguments kwargs are passed to the ODE solver defining the flow. Look at DifferentialEquations.jl for more information. Note that, in this case, the derivative of the flow is computed internally using Finite Differences.\n\nAnother way to create a Shooting problem with more options is the following where in particular, one can provide its own scalar constraint section(x)::Number for the phase:\n\npb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; parallel = false, kwargs...)\n\nor\n\npb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, ds, section; parallel = false, kwargs...)\n\nThe next way is an elaboration of the previous one\n\npb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, M::Int, section; parallel = false, kwargs...)\n\nor\n\npb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, ds, section; parallel = false, kwargs...)\n\nwhere we supply now two ODEProblems. The first one prob1, is used to define the flow associated to F while the second one is a problem associated to the derivative of the flow. Hence, prob2 must implement the following vector field tilde F(xyp) = (F(xp) dF(xp)cdot y).\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"PoincareShootingProblem","category":"page"},{"location":"library/#BifurcationKit.PoincareShootingProblem","page":"Library","title":"BifurcationKit.PoincareShootingProblem","text":"pb = PoincareShootingProblem(flow::Flow, M, sections; δ = 1e-8, interp_points = 50, parallel = false)\n\nThis composite type implements the Poincaré Shooting method to locate periodic orbits by relying on Poincaré return maps. More details (maths, notations, linear systems) can be found here. The arguments are as follows\n\nflow::Flow: implements the flow of the Cauchy problem though the structure Flow.\nM: the number of Poincaré sections. If M == 1, then the simple shooting is implemented and the multiple one otherwise.\nsections: function or callable struct which implements a Poincaré section condition. The evaluation sections(x) must return a scalar number when M == 1. Otherwise, one must implement a function section(out, x) which populates out with the M sections. See SectionPS for type of section defined as a hyperplane.\nδ = 1e-8 used to compute the jacobian of the functional by finite differences. If set to 0, an analytical expression of the jacobian is used instead.\ninterp_points = 50 number of interpolation point used to define the callback (to compute the hitting of the hyperplane section)\nparallel = false whether the shooting are computed in parallel (threading). Only available through the use of Flows defined by EnsembleProblem.\npar parameters of the model\nlens parameter axis\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).\n\nJacobian\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\nSimplified constructors\n\nThe first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points pb = PoincareShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)\nA convenient way is to create a functional is\n\npb = PoincareShootingProblem(prob::ODEProblem, alg, section; kwargs...)\n\nfor simple shooting or\n\npb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; kwargs...)\n\nfor multiple shooting . Here prob is an Union{ODEProblem, EnsembleProblem} which is used to create a flow using the ODE solver alg (for example Tsit5()). Finally, the arguments kwargs are passed to the ODE solver defining the flow. We refer to DifferentialEquations.jl for more information.\n\nAnother convenient call is\n\npb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, normals::AbstractVector, centers::AbstractVector; δ = 1e-8, kwargs...)\n\nwhere normals (resp. centers) is a list of normals (resp. centers) which defines a list of hyperplanes Sigma_i. These hyperplanes are used to define partial Poincaré return maps.\n\nComputing the functionals\n\nA functional, hereby called G encodes this shooting problem. You can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N where N is the number of unknowns in the state space and M is the number of Poincaré maps. Another accepted guess is such that guess[i] is the state of the orbit on the ith section. This last form allows for non-vector state space which can be convenient for 2d problems for example.\n\nNote that you can generate this guess from a function solution using generate_solution.\n\npb(orbitguess, par) evaluates the functional G on orbitguess\npb(orbitguess, par, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du\npb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.\npb(Val(:JacobianMatrix), x, par) same as above but out-of-place.\n\ntip: Tip\nYou can use the function getperiod(pb, sol, par) to get the period of the solution sol for the problem with parameters par.\n\n\n\n\n\n","category":"type"},{"location":"library/#Waves","page":"Library","title":"Waves","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.TWProblem","category":"page"},{"location":"library/#BifurcationKit.TWProblem","page":"Library","title":"BifurcationKit.TWProblem","text":"TWProblem(prob, ∂::Tuple, u₀; DAE = 0, jacobian::Symbol = :AutoDiff)\n\nThis composite type implements a functional for freezing symmetries in order, for example, to compute travelling waves (TW). Note that you can freeze many symmetries, not just one, by passing many Lie generators. When you call pb(x, par), it computes:\n\n ┌ ┐\n │ f(x, par) - s⋅∂⋅x │\n │ │\n └ ┘\n\nArguments\n\nprob bifurcation problem with continuous symmetries\n∂::Tuple = (T1, T2, ⋯) tuple of Lie generators. In effect, each of these is an (differential) operator which can be specified as a (sparse) matrix or as an operator implementing LinearAlgebra.mul!.\nu₀ reference solution\n\nAdditional Constructor(s)\n\npb = TWProblem(prob, ∂, u₀; kw...)\n\nThis simplified call handles the case where a single symmetry needs to be frozen.\n\nUseful function\n\nupdatesection!(pb::TWProblem, u0) updates the reference solution of the problem using u0.\nnb_constraints(::TWProblem) number of constraints (or Lie generators)\n\n\n\n\n\n","category":"type"},{"location":"library/#Newton","page":"Library","title":"Newton","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"newton","category":"page"},{"location":"library/#BifurcationKit.newton","page":"Library","title":"BifurcationKit.newton","text":" newton(prob::AbstractBifurcationProblem, options::NewtonPar; normN = norm, callback = (;x, fx, J, residual, step, itlinear, options, x0, residuals; kwargs...) -> true, kwargs...)\n\nThis is the Newton-Krylov Solver for F(x, p0) = 0 with Jacobian w.r.t. x written J(x, p0) and initial guess x0. The function normN allows to specify a norm for the convergence criteria. It is important to set the linear solver options.linsolver properly depending on your problem. This linear solver is used to solve J(x p_0)u = -F(x p_0) in the Newton step. You can for example use linsolver = DefaultLS() which is the operator backslash: it works well for Sparse / Dense matrices. See Linear solvers (LS) for more informations.\n\nArguments:\n\nprob a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.\noptions::NewtonPar variable holding the internal parameters used by the newton method\ncallback function passed by the user which is called at the end of each iteration. The default one is the following cb_default((x, fx, J, residual, step, itlinear, options, x0, residuals); k...) = true. Can be used to update a preconditionner for example. You can use for example cbMaxNorm to limit the residuals norms. If yo want to specify your own, the arguments passed to the callback are as follows\nx current solution\nfx current residual\nJ current jacobian\nresidual current norm of the residual\nstep current newton step\nitlinear number of iterations to solve the linear system\noptions a copy of the argument options passed to newton\nresiduals the history of residuals\nkwargs kwargs arguments, contain your initial guess x0\nkwargs arguments passed to the callback. Useful when newton is called from continuation\n\nOutput:\n\nsolution::NonLinearSolution, we refer to NonLinearSolution for more information.\n\nwarning: Linear solver\nMake sure that the linear solver (Matrix-Free...) corresponds to your jacobian (Matrix-Free vs. Matrix based).\n\n\n\n\n\nnewton(prob, defOp, options)\nnewton(prob, defOp, options, _linsolver; kwargs...)\n\n\nThis is the deflated version of the Krylov-Newton Solver for F(x, p0) = 0.\n\nWe refer to the regular newton for more information. It penalises the roots saved in defOp.roots. The other arguments are as for newton. See DeflationOperator for more information on defOp.\n\nArguments\n\nCompared to newton, the only different arguments are\n\ndefOp::DeflationOperator deflation operator\nlinsolver linear solver used to invert the Jacobian of the deflated functional.\ncustom solver DeflatedProblemCustomLS() which requires solving two linear systems J⋅x = rhs.\nFor other linear solvers <: AbstractLinearSolver, a matrix free method is used for the deflated functional.\nif passed Val(:autodiff), then ForwardDiff.jl is used to compute the jacobian Matrix of the deflated problem\nif passed Val(:fullIterative), then a full matrix free method is used for the deflated problem.\n\n\n\n\n\nThis specific Newton-Krylov method first tries to converge to a solution sol0 close the guess x0. It then attempts to converge from the guess x1 while avoiding the previous converged solution close to sol0. This is very handy for branch switching. The method is based on a deflated Newton-Krylov solver.\n\n\n\n\n\nnewton(\n br,\n ind_bif;\n normN,\n options,\n start_with_eigen,\n lens2,\n kwargs...\n)\n\n\nThis function turns an initial guess for a Fold / Hopf point into a solution to the Fold / Hopf problem based on a Minimally Augmented formulation.\n\nArguments\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\n\nOptional arguments:\n\noptions::NewtonPar, default value br.contparams.newton_options\nnormN = norm\noptions You can pass newton parameters different from the ones stored in br by using this argument options.\nbdlinsolver bordered linear solver for the constraint equation\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements.\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\ntip: start_with_eigen\nIt is recommended that you use the option start_with_eigen=true\n\n\n\n\n\nnewton(prob, orbitguess, options; lens, δ, kwargs...)\n\n\nThis is the Newton-Krylov Solver for computing a periodic orbit using the (Standard / Poincaré) Shooting method. Note that the linear solver has to be appropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is either a ShootingProblem or a PoincareShootingProblem. These two problems have specific options to be tuned, we refer to their link for more information and to the tutorials.\n\nprob a problem of type <: AbstractShootingProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit. See ShootingProblem and See PoincareShootingProblem for information regarding the shape of orbitguess.\npar parameters to be passed to the functional\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\nnewton(prob, orbitguess, defOp, options; lens, kwargs...)\n\n\nThis is the deflated Newton-Krylov Solver for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to newton except that prob is either a ShootingProblem or a PoincareShootingProblem.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\nOutput:\n\nsolution::NonLinearSolution, see NonLinearSolution\n\n\n\n\n\nnewton(probPO, orbitguess, options; kwargs...)\n\n\nThis is the Krylov-Newton Solver for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.\n\nArguments:\n\nprob a problem of type PeriodicOrbitTrapProblem encoding the functional G\norbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It should be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.\npar parameters to be passed to the functional\noptions same as for the regular newton method\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\n\n\n\n\nnewton(probPO, orbitguess, defOp, options; kwargs...)\n\n\nThis function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.\n\n\n\n\n\nnewton(probPO, orbitguess, options; kwargs...)\n\n\nThis is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is a PeriodicOrbitOCollProblem.\n\nprob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit.\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG\nFor AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.\nFor AutoDiffDenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\n\n\n\n\n\nnewton(probPO, orbitguess, defOp, options; kwargs...)\n\n\nThis function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.\n\n\n\n\n\n","category":"function"},{"location":"library/#Library-Continuation","page":"Library","title":"Continuation","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.DotTheta","category":"page"},{"location":"library/#BifurcationKit.DotTheta","page":"Library","title":"BifurcationKit.DotTheta","text":"struct DotTheta{Tdot, Ta}\n\ndot::Any: dot product used in pseudo-arclength constraint\napply!::Any: Linear operator associated with dot product, i.e. dot(x, y) = , where <,> is the standard dot product on R^N. You must provide an inplace function which evaluates A. For example x -> rmul!(x, 1/length(x)).\n\nThis parametric type allows to define a new dot product from the one saved in dt::dot. More precisely:\n\ndt(u1, u2, p1::T, p2::T, theta::T) where {T <: Real}\n\ncomputes, the weighted dot product langle (u_1p_1) (u_2p_2)rangle_theta = theta Re langle u_1u_2rangle +(1-theta)p_1p_2 where u_iinmathbb R^N. The Re factor is put to ensure a real valued result despite possible complex valued arguments.\n\ninfo: Info\nThis is used in the pseudo-arclength constraint with the dot product frac1N langle u_1 u_2ranglequad u_iinmathbb R^N\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"continuation","category":"page"},{"location":"library/#BifurcationKit.continuation","page":"Library","title":"BifurcationKit.continuation","text":"continuation(\n prob,\n alg,\n contparams;\n linear_algo,\n bothside,\n kwargs...\n)\n\n\nCompute the continuation curve associated to the functional F which is stored in the bifurcation problem prob. General information is available in Continuation methods: introduction.\n\nArguments:\n\nprob::AbstractBifurcationFunction a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.\nalg continuation algorithm, for example Natural(), PALC(), Multiple(),.... See algos\ncontparams parameters for continuation. See ContinuationPar\n\nOptional Arguments:\n\nplot = false whether to plot the solution/branch/spectrum while computing the branch\nbothside = true compute the branches on the two sides of p0, merge them and return it.\nfinalise_solution = (z, tau, step, contResult; kwargs...) -> true Function called at the end of each continuation step. Can be used to alter the continuation procedure (stop it by returning false), saving personal data, plotting... The notations are z=(x p) where x (resp. p) is the current solution (resp. parameter value), tau is the tangent at z, step is the index of the current continuation step and ContResult is the current branch. For advanced use, the current state::ContState of the continuation is passed in kwargs. Note that you can have a better control over the continuation procedure by using an iterator, see Iterator Interface.\nverbosity::Int = 0 controls the amount of information printed during the continuation process. Must belong to {0,1,2,3}. In case contparams.newton_options.verbose = false, the following is valid (otherwise the newton iterations are shown). Each case prints more information than the previous one:\ncase 0: print nothing\ncase 1: print basic information about the continuation: used predictor, step size and parameter values\ncase 2: print newton iterations number, stability of solution, detected bifurcations / events\ncase 3: print information during bisection to locate bifurcations / events\nnormC = norm norm used in the Newton solves\nfilename to save the computed branch during continuation. The identifier .jld2 will be appended to this filename. This requires using JLD2.\ncallback_newton callback for newton iterations. See docs of newton. For example, it can be used to change preconditioners.\nkind::AbstractContinuationKind [Internal] flag to describe continuation kind (equilibrium, codim 2, ...). Default = EquilibriumCont()\n\nOutput:\n\ncontres::ContResult composite type which contains the computed branch. See ContResult for more information.\n\ntip: Continuing the branch in the opposite direction\nJust change the sign of ds in ContinuationPar.\n\n\n\n\n\ncontinuation(\n prob,\n algdc,\n contParams;\n verbosity,\n plot,\n linear_algo,\n dot_palc,\n callback_newton,\n filename,\n normC,\n kwcont...\n)\n\n\nThis function computes the set of curves of solutions γ(s) = (x(s), p(s)) to the equation F(x,p) = 0 based on the algorithm of deflated continuation as described in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. “The Computation of Disconnected Bifurcation Diagrams.” ArXiv:1603.00809 [Math], March 2, 2016. http://arxiv.org/abs/1603.00809.\n\nDepending on the options in contParams, it can locate the bifurcation points on each branch. Note that you can specify different predictors using alg.\n\nArguments:\n\nprob::AbstractBifurcationProblem bifurcation problem\nalg::DefCont, deflated continuation algorithm, see DefCont\ncontParams parameters for continuation. See ContinuationPar for more information about the options\n\nOptional Arguments:\n\nplot = false whether to plot the solution while computing,\ncallback_newton callback for newton iterations. see docs for newton. Can be used to change preconditioners or affect the newton iterations. In the deflation part of the algorithm, when seeking for new branches, the callback is passed the keyword argument fromDeflatedNewton = true to tell the user can it is not in the continuation part (regular newton) of the algorithm,\nverbosity::Int controls the amount of information printed during the continuation process. Must belong to {0,⋯,5},\nnormC = norm norm used in the Newton solves,\ndot_palc = (x, y) -> dot(x, y) / length(x), dot product used to define the weighted dot product (resp. norm) (x p)^2_theta in the constraint N(x p) (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...),\n\nOutputs:\n\ncontres::DCResult composite type which contains the computed branches. See ContResult for more information,\n\n\n\n\n\ncontinuation(br, ind_bif, lens2)\ncontinuation(\n br,\n ind_bif,\n lens2,\n options_cont;\n prob,\n start_with_eigen,\n detect_codim2_bifurcation,\n kwargs...\n)\n\n\nCodimension 2 continuation of Fold / Hopf points. This function turns an initial guess for a Fold / Hopf point into a curve of Fold / Hopf points based on a Minimally Augmented formulation. The arguments are as follows\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\nlens2 second parameter used for the continuation, the first one is the one used to compute br, e.g. getlens(br)\noptions_cont = br.contparams arguments to be passed to the regular continuation\n\nOptional arguments:\n\nbdlinsolver bordered linear solver for the constraint equation\nupdate_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements\ndetect_codim2_bifurcation ∈ {0,1,2} whether to detect Bogdanov-Takens, Bautin and Cusp. If equals 1 non precise detection is used. If equals 2, a bisection method is used to locate the bifurcations.\nkwargs keywords arguments to be passed to the regular continuation\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br you want to refine.\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\ntip: start_with_eigen\nIt is recommended that you use the option start_with_eigen = true\n\n\n\n\n\ncontinuation(\n prob,\n x0,\n par0,\n x1,\n p1,\n alg,\n lens,\n contParams;\n kwargs...\n)\n\n\n[Internal] This function is not meant to be called directly.\n\nThis function is the analog of continuation when the first two points on the branch are passed (instead of a single one). Hence x0 is the first point on the branch (with palc s=0) with parameter par0 and x1 is the second point with parameter set(par0, lens, p1).\n\n\n\n\n\ncontinuation(br, ind_bif)\ncontinuation(\n br,\n ind_bif,\n options_cont;\n alg,\n δp,\n ampfactor,\n nev,\n usedeflation,\n verbosedeflation,\n max_iter_deflation,\n perturb,\n plot_solution,\n Teigvec,\n scaleζ,\n tol_fold,\n kwargs...\n)\n\n\nAutomatic branch switching at branch points based on a computation of the normal form. More information is provided in Branch switching. An example of use is provided in 2d generalized Bratu–Gelfand problem.\n\nArguments\n\nbr branch result from a call to continuation\nind_bif index of the bifurcation point in br from which you want to branch from\noptions_cont options for the call to continuation\n\nOptional arguments\n\nalg = br.alg continuation algorithm to be used, default value: br.alg\nδp used to specify a specific value for the parameter on the bifurcated branch which is otherwise determined by options_cont.ds. This allows to use a step larger than options_cont.dsmax.\nampfactor = 1 factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\nnev number of eigenvalues to be computed to get the right eigenvector\nusedeflation = false whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated\nverbosedeflation print deflated newton iterations\nmax_iter_deflation number of newton steps in deflated newton\nperturb = identity which perturbation function to use during deflated newton\nTeigvec = getvectortype(br) type of the eigenvector. Useful when br was loaded from a file and this information was lost\nscaleζ = norm pass a norm to normalize vectors during normal form computation\nplot_solution change plot solution method in the problem br.prob\nkwargs optional arguments to be passed to continuation, the regular continuation one and to get_normal_form.\n\ntip: Advanced use\nIn the case of a very large model and use of special hardware (GPU, cluster), we suggest to discouple the computation of the reduced equation, the predictor and the bifurcated branches. Have a look at methods(BifurcationKit.multicontinuation) to see how to call these versions. These methods has been tested on GPU with very high memory pressure.\n\n\n\n\n\ncontinuation(\n probPO,\n orbitguess,\n alg,\n contParams,\n linear_algo;\n δ,\n eigsolver,\n record_from_solution,\n plot_solution,\n kwargs...\n)\n\n\nThis is the continuation method for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to continuation except that probPO is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.\n\nOptional arguments\n\neigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\ncontinuation(\n prob,\n orbitguess,\n alg,\n _contParams;\n linear_algo,\n kwargs...\n)\n\n\nThis is the continuation routine for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to continuation except that prob is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.\n\nOptional argument\n\nlinear_algo::AbstractBorderedLinearSolver\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\ncontinuation(\n br,\n ind_bif,\n _contParams,\n probPO;\n alg,\n δp,\n ampfactor,\n usedeflation,\n nev,\n kwargs...\n)\n\n\nPerform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.\n\nArguments\n\nbr branch result from a call to continuation\nind_hopf index of the bifurcation point in br\ncontParams parameters for the call to continuation\nprobPO problem used to specify the way the periodic orbit is computed. It can be PeriodicOrbitTrapProblem, ShootingProblem or PoincareShootingProblem .\n\nOptional arguments\n\nalg = br.alg continuation algorithm\nδp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.\nampfactor = 1 factor which alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\nusedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch\nnev number of eigenvalues to be computed to get the right eigenvector\nall kwargs from continuation\n\nA modified version of prob is passed to plot_solution and finalise_solution.\n\nnote: Linear solver\nYou have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.\n\n\n\n\n\ncontinuation(\n br,\n ind_bif,\n _contParams;\n alg,\n δp,\n ampfactor,\n usedeflation,\n linear_algo,\n detailed,\n kwargs...\n)\n\n\nBranch switching at a bifurcation point on a branch of periodic orbits (PO) specified by a br::AbstractBranchResult. The functional used to compute the PO is br.prob. A deflated Newton-Krylov solver can be used to improve the branch switching capabilities.\n\nArguments\n\nbr branch of periodic orbits computed with a PeriodicOrbitTrapProblem\nind_bif index of the branch point\n_contParams parameters to be used by a regular continuation\n\nOptional arguments\n\nδp = 0.1 used to specify a particular guess for the parameter in the branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.\nampfactor = 1 factor which alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\ndetailed = false whether to fully compute the normal form. The normal form is only used to collect the eigenvector for now.\nusedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch\nrecord_from_solution = (u, p) -> u[end], record method used in the bifurcation diagram, by default this records the period of the periodic orbit.\nlinear_algo = BorderingBLS(), same as for continuation\nkwargs keywords arguments used for a call to the regular continuation and the ones specific to periodic orbits (POs).\n\n\n\n\n\ncontinuation(\n prob,\n orbitguess,\n alg,\n _contParams;\n record_from_solution,\n linear_algo,\n kwargs...\n)\n\n\nThis is the continuation routine for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.\n\nArguments\n\nprob::PeriodicOrbitTrapProblem encodes the functional G\norbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It could be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.\nalg continuation algorithm\ncontParams same as for the regular continuation method\n\nKeyword arguments\n\nlinear_algo same as in continuation\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\nNote that by default, the method prints the period of the periodic orbit as function of the parameter. This can be changed by providing your record_from_solution argument.\n\n\n\n\n\ncontinuation(\n probPO,\n orbitguess,\n alg,\n _contParams,\n linear_algo;\n δ,\n eigsolver,\n record_from_solution,\n plot_solution,\n kwargs...\n)\n\n\nThis is the continuation method for computing a periodic orbit using an orthogonal collocation method.\n\nArguments\n\nSimilar to continuation except that prob is a PeriodicOrbitOCollProblem. By default, it prints the period of the periodic orbit.\n\nKeywords arguments\n\neigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD\n\n\n\n\n\ncontinuation(\n prob,\n alg,\n contParams;\n linear_algo,\n plot,\n normC,\n finalise_solution,\n callback_newton,\n kind,\n verbosity,\n kwargs...\n)\n\n\nArguments\n\nprob::BifurcationProblem\nalg:: ANM continuation algorithm. See ANM.\ncontParams see BK.ContinuationPar\n\n\n\n\n\n","category":"function"},{"location":"library/#Continuation-algorithms","page":"Library","title":"Continuation algorithms","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"Natural","category":"page"},{"location":"library/#BifurcationKit.Natural","page":"Library","title":"BifurcationKit.Natural","text":"Natural continuation algorithm.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Secant","category":"page"},{"location":"library/#BifurcationKit.Secant","page":"Library","title":"BifurcationKit.Secant","text":"Secant Tangent predictor\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Bordered","category":"page"},{"location":"library/#BifurcationKit.Bordered","page":"Library","title":"BifurcationKit.Bordered","text":"Bordered Tangent predictor\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Polynomial","category":"page"},{"location":"library/#BifurcationKit.Polynomial","page":"Library","title":"BifurcationKit.Polynomial","text":"Polynomial Tangent predictor\n\nn::Int64: Order of the polynomial\nk::Int64: Length of the last solutions vector used for the polynomial fit\nA::Matrix{T} where T<:Real: Matrix for the interpolation\ntangent::BifurcationKit.AbstractTangentComputation: Algo for tangent when polynomial predictor is not possible\nsolutions::DataStructures.CircularBuffer: Vector of solutions\nparameters::DataStructures.CircularBuffer{T} where T<:Real: Vector of parameters\narclengths::DataStructures.CircularBuffer{T} where T<:Real: Vector of arclengths\ncoeffsSol::Vector: Coefficients for the polynomials for the solution\ncoeffsPar::Vector{T} where T<:Real: Coefficients for the polynomials for the parameter\nupdate::Bool: Update the predictor by adding the last point (x, p)? This can be disabled in order to just use the polynomial prediction. It is useful when the predictor is called mutiple times during bifurcation detection using bisection.\n\nConstructor(s)\n\nPolynomial(pred, n, k, v0)\n\nPolynomial(n, k, v0)\n\nn order of the polynomial\nk length of the last solutions vector used for the polynomial fit\nv0 example of solution to be stored. It is only used to get the eltype of the tangent!!\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Multiple","category":"page"},{"location":"library/#BifurcationKit.Multiple","page":"Library","title":"BifurcationKit.Multiple","text":"Multiple Tangent continuation algorithm.\n\nalg::PALC: Tangent predictor used Default: PALC()\nτ::Any: Save the current tangent\nα::Real: Damping in Newton iterations, 0 < α < 1\nnb::Int64: Number of predictors\ncurrentind::Int64: Index of the largest converged predictor Default: 0\npmimax::Int64: Index for lookup in residual history Default: 1\nimax::Int64: Maximum index for lookup in residual history Default: 4\ndsfact::Real: Factor to increase ds upon successful step Default: 1.5\n\nConstructor(s)\n\nMultiple(alg, x0, α, n)\n\nMultiple(pred, x0, α, n)\n\nMultiple(x0, α, n)\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"PALC","category":"page"},{"location":"library/#BifurcationKit.PALC","page":"Library","title":"BifurcationKit.PALC","text":"struct PALC{Ttang<:BifurcationKit.AbstractTangentComputation, Tbls<:BifurcationKit.AbstractLinearSolver, T, Tdot} <: BifurcationKit.AbstractContinuationAlgorithm\n\nPseudo-arclength continuation algorithm.\n\nAdditional information is available on the website.\n\nFields\n\ntangent::BifurcationKit.AbstractTangentComputation: Tangent predictor, must be a subtype of AbstractTangentComputation. For example Secant() or Bordered(), Default: Secant()\nθ::Any: θ is a parameter in the arclength constraint. It is very important to tune it. It should be tuned for the continuation to work properly especially in the case of large problems where the < x - x0, dx0 > component in the constraint equation might be favoured too much. Also, large thetas favour p as the corresponding term in N involves the term 1-theta. Default: 0.5\n_bothside::Bool: [internal], Default: false\nbls::BifurcationKit.AbstractLinearSolver: Bordered linear solver used to invert the jacobian of the newton bordered problem. It is also used to compute the tangent for the predictor Bordered(), Default: MatrixBLS()\ndoArcLengthScaling::Bool: Unused for now, Default: false\ngGoal::Any: Unused for now, Default: 0.5\ngMax::Any: Unused for now, Default: 0.8\nθMin::Any: Unused for now, Default: 0.001\ndotθ::Any: dotθ = DotTheta(), this sets up a dot product (x, y) -> dot(x, y) / length(x) used to define the weighted dot product (resp. norm) (x p)^2_theta in the constraint N(x p) (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...) Default: DotTheta()\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"MoorePenrose","category":"page"},{"location":"library/#BifurcationKit.MoorePenrose","page":"Library","title":"BifurcationKit.MoorePenrose","text":"Moore-Penrose predictor / corrector\n\nMoore-Penrose continuation algorithm.\n\nAdditional information is available on the website.\n\nConstructors\n\nalg = MoorePenrose()\n\nalg = MoorePenrose(tangent = PALC())\n\nFields\n\ntangent::Any: Tangent predictor, example PALC()\nmethod::MoorePenroseLS: Use a direct linear solver. Can be BifurcationKit.direct, BifurcationKit.pInv or BifurcationKit.iterative\nls::BifurcationKit.AbstractLinearSolver: (Bordered) linear solver\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.DefCont","category":"page"},{"location":"library/#BifurcationKit.DefCont","page":"Library","title":"BifurcationKit.DefCont","text":"struct DefCont{Tdo, Talg, Tps, Tas, Tud, Tk} <: BifurcationKit.AbstractContinuationAlgorithm\n\nStructure which holds the parameters specific to Deflated continuation.\n\nFields\n\ndeflation_operator::Any: Deflation operator, ::DeflationOperator Default: nothing\nalg::Any: Used as a predictor, ::AbstractContinuationAlgorithm. For example PALC(), Natural(),... Default: PALC()\nmax_branches::Int64: maximum number of (active) branches to be computed Default: 100\nseek_every_step::Int64: whether to seek new (deflated) solution at every step Default: 1\nmax_iter_defop::Int64: maximum number of deflated Newton iterations Default: 5\nperturb_solution::Any: perturb function Default: _perturbSolution\naccept_solution::Any: accept (solution) function Default: _acceptSolution\nupdate_deflation_op::Any: function to update the deflation operator, ie pushing new solutions Default: _updateDeflationOp\njacobian::Any: jacobian for deflated newton. Can be DeflatedProblemCustomLS(), or Val(:autodiff), Val(:fullIterative) Default: DeflatedProblemCustomLS()\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"AsymptoticNumericalMethod.ANM","category":"page"},{"location":"library/#AsymptoticNumericalMethod.ANM","page":"Library","title":"AsymptoticNumericalMethod.ANM","text":"Continuation algorithm based on Asymptotic Numerical Method. It can be used from the package https://github.com/bifurcationkit/AsymptoticNumericalMethod.jl\n\nFields\n\norder::Int64: order of the polynomial approximation\ntol::Any: tolerance which is used to estimate the neighbourhood on which the polynomial approximation is valid\n\nReferences\n\nCharpentier, Isabelle, Bruno Cochelin, and Komlanvi Lampoh. “Diamanlab - An Interactive Taylor-Based Continuation Tool in MATLAB,” n.d., 12.\nRubbert, Lennart, Isabelle Charpentier, Simon Henein, and Pierre Renaud. “Higher-Order Continuation Method for the Rigid-Body Kinematic Design of Compliant Mechanisms”, n.d., 18.\n\n\n\n\n\n","category":"type"},{"location":"library/#Events","page":"Library","title":"Events","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.DiscreteEvent","category":"page"},{"location":"library/#BifurcationKit.DiscreteEvent","page":"Library","title":"BifurcationKit.DiscreteEvent","text":"struct DiscreteEvent{Tcb, Tl} <: BifurcationKit.AbstractDiscreteEvent\n\nStructure to pass a DiscreteEvent function to the continuation algorithm. A discrete call back returns a discrete value and we seek when it changes.\n\nnb::Int64: number of events, ie the length of the result returned by the callback function\ncondition::Any: = (iter, state) -> NTuple{nb, Int64} callback function which at each continuation state, returns a tuple. For example, to detect a value change.\ncomputeEigenElements::Bool: whether the event requires to compute eigen elements\nlabels::Any: Labels used to display information. For example labels[1] is used to qualify an event occurring in the first component. You can use labels = (\"hopf\",) or labels = (\"hopf\", \"fold\"). You must have labels::Union{Nothing, NTuple{N, String}}.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.ContinuousEvent","category":"page"},{"location":"library/#BifurcationKit.ContinuousEvent","page":"Library","title":"BifurcationKit.ContinuousEvent","text":"struct ContinuousEvent{Tcb, Tl, T} <: BifurcationKit.AbstractContinuousEvent\n\nStructure to pass a ContinuousEvent function to the continuation algorithm. A continuous call back returns a tuple/scalar value and we seek its zeros.\n\nnb::Int64: number of events, ie the length of the result returned by the callback function\ncondition::Any: , (iter, state) -> NTuple{nb, T} callback function which, at each continuation state, returns a tuple. For example, to detect crossing 1.0 and -2.0, you can pass (iter, state) -> (getp(state)+2, getx(state)[1]-1)),. Note that the type T should match the one of the parameter specified by the ::Lens in continuation.\ncomputeEigenElements::Bool: whether the event requires to compute eigen elements\nlabels::Any: Labels used to display information. For example labels[1] is used to qualify an event of the type (0,1.3213,3.434). You can use labels = (\"hopf\",) or labels = (\"hopf\", \"fold\"). You must have labels::Union{Nothing, NTuple{N, String}}.\ntol::Any: Tolerance on event value to declare it as true event.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.SetOfEvents","category":"page"},{"location":"library/#BifurcationKit.SetOfEvents","page":"Library","title":"BifurcationKit.SetOfEvents","text":"struct SetOfEvents{Tc<:Tuple, Td<:Tuple} <: BifurcationKit.AbstractEvent\n\nMultiple events can be chained together to form a SetOfEvents. A SetOfEvents is constructed by passing to the constructor ContinuousEvent, DiscreteEvent or other SetOfEvents instances:\n\nSetOfEvents(cb1, cb2, cb3)\n\nExample\n\n BifurcationKit.SetOfEvents(BK.FoldDetectCB, BK.BifDetectCB)\n\nYou can pass as many events as you like.\n\neventC::Tuple: Continuous event\neventD::Tuple: Discrete event\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.PairOfEvents","category":"page"},{"location":"library/#BifurcationKit.PairOfEvents","page":"Library","title":"BifurcationKit.PairOfEvents","text":"struct PairOfEvents{Tc<:BifurcationKit.AbstractContinuousEvent, Td<:BifurcationKit.AbstractDiscreteEvent} <: BifurcationKit.AbstractEvent\n\nStructure to pass a PairOfEvents function to the continuation algorithm. It is composed of a pair ContinuousEvent / DiscreteEvent. A PairOfEvents is constructed by passing to the constructor a ContinuousEvent and a DiscreteEvent:\n\nPairOfEvents(contEvent, discreteEvent)\n\nFields\n\neventC::BifurcationKit.AbstractContinuousEvent: Continuous event\neventD::BifurcationKit.AbstractDiscreteEvent: Discrete event\n\n\n\n\n\n","category":"type"},{"location":"library/#Branch-switching-(branch-point)","page":"Library","title":"Branch switching (branch point)","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar ; kwargs...)","category":"page"},{"location":"library/#Branch-switching-(Hopf-point)","page":"Library","title":"Branch switching (Hopf point)","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int, _contParams::ContinuationPar, prob::BifurcationKit.AbstractPeriodicOrbitProblem ; kwargs...)","category":"page"},{"location":"library/#BifurcationKit.continuation-Tuple{BifurcationKit.AbstractBranchResult, Int64, ContinuationPar, BifurcationKit.AbstractPeriodicOrbitProblem}","page":"Library","title":"BifurcationKit.continuation","text":"continuation(\n br,\n ind_bif,\n _contParams,\n probPO;\n alg,\n δp,\n ampfactor,\n usedeflation,\n nev,\n kwargs...\n)\n\n\nPerform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.\n\nArguments\n\nbr branch result from a call to continuation\nind_hopf index of the bifurcation point in br\ncontParams parameters for the call to continuation\nprobPO problem used to specify the way the periodic orbit is computed. It can be PeriodicOrbitTrapProblem, ShootingProblem or PoincareShootingProblem .\n\nOptional arguments\n\nalg = br.alg continuation algorithm\nδp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.\nampfactor = 1 factor which alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\nusedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch\nnev number of eigenvalues to be computed to get the right eigenvector\nall kwargs from continuation\n\nA modified version of prob is passed to plot_solution and finalise_solution.\n\nnote: Linear solver\nYou have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.\n\n\n\n\n\n","category":"method"},{"location":"library/#Bifurcation-diagram","page":"Library","title":"Bifurcation diagram","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"bifurcationdiagram","category":"page"},{"location":"library/#BifurcationKit.bifurcationdiagram","page":"Library","title":"BifurcationKit.bifurcationdiagram","text":"bifurcationdiagram(prob, alg, level, options; kwargs...)\n\n\nCompute the bifurcation diagram associated with the problem F(x, p) = 0 recursively.\n\nArguments\n\nprob::AbstractBifurcationProblem bifurcation problem\nalg continuation algorithm\nlevel maximum branching (or recursion) level for computing the bifurcation diagram\noptions = (x, p, level) -> contparams this function allows to change the continuation options depending on the branching level. The argument x, p denotes the current solution to F(x, p)=0.\nkwargs optional arguments. Look at bifurcationdiagram! for more details.\n\nSimplified call:\n\nWe also provide the method\n\nbifurcationdiagram(prob, br::ContResult, level::Int, options; kwargs...)\n\nwhere br is a branch computed after a call to continuation from which we want to compute the bifurcating branches recursively.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"bifurcationdiagram!","category":"page"},{"location":"library/#BifurcationKit.bifurcationdiagram!","page":"Library","title":"BifurcationKit.bifurcationdiagram!","text":"bifurcationdiagram!(\n prob,\n node,\n maxlevel,\n options;\n code,\n usedeflation,\n halfbranch,\n verbosediagram,\n kwargs...\n)\n\n\nSimilar to bifurcationdiagram but you pass a previously computed node from which you want to further compute the bifurcated branches. It is usually used with node = get_branch(diagram, code) from a previously computed bifurcation diagram.\n\nArguments\n\nnode::BifDiagNode a node in the bifurcation diagram\nmaxlevel = 1 required maximal level of recursion.\noptions = (x, p, level) -> contparams this function allows to change the continuation options depending on the branching level. The argument x, p denotes the current solution to F(x, p)=0.\n\nOptional arguments\n\ncode = \"0\" code used to display iterations\nusedeflation = false\nhalfbranch = false for Pitchfork / Transcritical bifurcations, compute only half of the branch. Can be useful when there are symmetries.\nverbosediagram verbose specific to bifurcation diagram. Print information about the branches as they are being computed.\nkwargs optional arguments as for continuation but also for the different versions listed in Continuation.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"get_branch","category":"page"},{"location":"library/#BifurcationKit.get_branch","page":"Library","title":"BifurcationKit.get_branch","text":"get_branch(tree, code)\n\n\nReturn the part of the tree (bifurcation diagram) by recursively descending down the tree using the Int valued tuple code. For example get_branch(tree, (1,2,3,)) returns tree.child[1].child[2].child[3].\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"get_branches_from_BP","category":"page"},{"location":"library/#BifurcationKit.get_branches_from_BP","page":"Library","title":"BifurcationKit.get_branches_from_BP","text":"get_branches_from_BP(tree, indbif)\n\n\nReturn the part of the tree corresponding to the indbif-th bifurcation point on the root branch.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.SpecialPoint","category":"page"},{"location":"library/#BifurcationKit.SpecialPoint","page":"Library","title":"BifurcationKit.SpecialPoint","text":"struct SpecialPoint{T, Tp, Tv, Tvτ} <: BifurcationKit.AbstractBifurcationPoint\n\nStructure to record special points on a curve. There are two types of special points that are recorded in this structure: bifurcation points and events (see https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/EventCallback/).\n\ntype::Symbol: Description of the special points. In case of Events, this field records the user passed named to the event, or the default :userD, :userC. In case of bifurcation points, it can be one of the following:\n- :bp Bifurcation point, simple eigenvalue crossing the imaginary axis\n- :fold Fold point\n- :hopf Hopf point\n- :nd not documented bifurcation point. Detected by multiple eigenvalues crossing. Generally occurs in problems with symmetries or in cases where the continuation step size is too large and merge two different bifurcation points.\n- :cusp Cusp point\n- :gh Generalized Hopf point (also called Bautin point)\n- :bt Bogdanov-Takens point\n- :zh Zero-Hopf point\n- :hh Hopf-Hopf point\n- :ns Neimark-Sacker point\n- :pd Period-doubling point\n- :R1 Strong resonance 1:1 of periodic orbits\n- :R2 Strong resonance 1:2 of periodic orbits\n- :R3 Strong resonance 1:3 of periodic orbits\n- :R4 Strong resonance 1:4 of periodic orbits\n- :foldFlip Fold / Flip of periodic orbits\n- :foldNS Fold / Neimark-Sacker of periodic orbits\n- :pdNS Period-Doubling / Neimark-Sacker of periodic orbits\n- :gpd Generalized Period-Doubling of periodic orbits\n- :nsns Double Neimark-Sacker of periodic orbits\n- :ch Chenciner bifurcation of periodic orbits\n Default: :none\nidx::Int64: Index in br.branch or br.eig (see ContResult) for which the bifurcation occurs. Default: 0\nparam::Any: Parameter value at the special point (this is an estimate). Default: 0.0\nnorm::Any: Norm of the equilibrium at the special point Default: 0.0\nprintsol::Any: printsol = record_from_solution(x, param) where record_from_solution is one of the arguments to continuation Default: 0.0\nx::Any: Equilibrium at the special point Default: Vector{T}(undef, 0)\nτ::BorderedArray{Tvτ, T} where {T, Tvτ}: Tangent along the branch at the special point Default: BorderedArray(x, T(0))\nind_ev::Int64: Eigenvalue index responsible for detecting the special point (if applicable) Default: 0\nstep::Int64: Continuation step at which the special occurs Default: 0\nstatus::Symbol: status ∈ {:converged, :guess, :guessL} indicates whether the bisection algorithm was successful in detecting the special (bifurcation) point. If status == :guess, the bissection algorithm failed to meet the requirements given in ::ContinuationPar. Same for status == :guessL but the bissection algorithm stopped on the left of the bifurcation point. Default: :guess\nδ::Tuple{Int64, Int64}: δ = (δr, δi) where δr indicates the change in the number of unstable eigenvalues and δi indicates the change in the number of unstable eigenvalues with nonzero imaginary part. abs(δr) is thus an estimate of the dimension of the kernel of the Jacobian at the special (bifurcation) point. Default: (0, 0)\nprecision::Any: Precision in the location of the special point Default: -1\ninterval::Tuple{T, T} where T: Interval parameter containing the special point Default: (0, 0)\n\n\n\n\n\n","category":"type"},{"location":"library/#Utils-for-periodic-orbits","page":"Library","title":"Utils for periodic orbits","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"getperiod","category":"page"},{"location":"library/#BifurcationKit.getperiod","page":"Library","title":"BifurcationKit.getperiod","text":"getperiod(, x)\ngetperiod(, x, par)\n\n\nCompute the period of the periodic orbit associated to x.\n\n\n\n\n\ngetperiod(prob, x, p)\n\n\nCompute the period of the periodic orbit associated to x.\n\n\n\n\n\ngetperiod(psh, x_bar, par)\n\n\nCompute the period of the periodic orbit associated to x_bar.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"getamplitude","category":"page"},{"location":"library/#BifurcationKit.getamplitude","page":"Library","title":"BifurcationKit.getamplitude","text":"getamplitude(prob, x, p; ratio)\n\n\nCompute the amplitude of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = 1 + ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\ngetamplitude(prob, x, p; ratio)\n\n\nCompute the amplitude of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"getmaximum","category":"page"},{"location":"library/#BifurcationKit.getmaximum","page":"Library","title":"BifurcationKit.getmaximum","text":"getmaximum(prob, x, p; ratio)\n\n\nCompute the maximum of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = 1 + ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\ngetmaximum(prob, x, p)\n\n\nCompute the maximum of the periodic orbit associated to x.\n\n\n\n\n\ngetmaximum(prob, x, p; ratio)\n\n\nCompute the maximum of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"SectionSS","category":"page"},{"location":"library/#BifurcationKit.SectionSS","page":"Library","title":"BifurcationKit.SectionSS","text":"struct SectionSS{Tn, Tc} <: BifurcationKit.AbstractSection\n\nThis composite type (named for Section Standard Shooting) encodes a type of section implemented by a single hyperplane. It can be used in conjunction with ShootingProblem. The hyperplane is defined by a point center and a normal.\n\nnormal::Any: Normal to define hyperplane\ncenter::Any: Representative point on hyperplane\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"SectionPS","category":"page"},{"location":"library/#BifurcationKit.SectionPS","page":"Library","title":"BifurcationKit.SectionPS","text":"struct SectionPS{Tn, Tc, Tnb, Tcb, Tr} <: BifurcationKit.AbstractSection\n\nThis composite type (named for SectionPoincaréShooting) encodes a type of Poincaré sections implemented by hyperplanes. It can be used in conjunction with PoincareShootingProblem. Each hyperplane is defined par a point (one example in centers) and a normal (one example in normals).\n\nM::Int64\nnormals::Any\ncenters::Any\nindices::Vector{Int64}\nnormals_bar::Any\ncenters_bar::Any\nradius::Any\n\nConstructor(s)\n\nSectionPS(normals::Vector{Tv}, centers::Vector{Tv})\n\n\n\n\n\n","category":"type"},{"location":"library/#Misc.","page":"Library","title":"Misc.","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"PrecPartialSchurKrylovKit","category":"page"},{"location":"library/#BifurcationKit.PrecPartialSchurKrylovKit","page":"Library","title":"BifurcationKit.PrecPartialSchurKrylovKit","text":"PrecPartialSchurKrylovKit(J, x0, nev, which = :LM; krylovdim = max(2nev, 20), verbosity = 0)\n\nBuilds a preconditioner based on deflation of nev eigenvalues chosen according to which. A partial Schur decomposition is computed (Matrix-Free), using the package KrylovKit.jl, from which a projection is built. The options are similar to the ones of EigKrylovKit().\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"PrecPartialSchurArnoldiMethod","category":"page"},{"location":"library/#BifurcationKit.PrecPartialSchurArnoldiMethod","page":"Library","title":"BifurcationKit.PrecPartialSchurArnoldiMethod","text":"PrecPartialSchurArnoldiMethod(J, N, nev, which = LM(); tol = 1e-9, kwargs...)\n\nBuilds a preconditioner based on deflation of nev eigenvalues chosen according to which. A partial Schur decomposition is computed (Matrix-Free), using the package ArnoldiMethod.jl, from which a projection is built. See the package ArnoldiMethod.jl for how to pass the proper options.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"Flow","category":"page"},{"location":"library/#BifurcationKit.Flow","page":"Library","title":"BifurcationKit.Flow","text":"struct Flow{TF, Tf, Tts, Tff, Td, Tad, Tse, Tprob, TprobMono, Tfs, Tcb, Tδ} <: BifurcationKit.AbstractFlow\n\nF::Any: The vector field (x, p) -> F(x, p) associated to a Cauchy problem. Used for the differential of the shooting problem. Default: nothing\nflow::Any: The flow (or semigroup) (x, p, t) -> flow(x, p, t) associated to the Cauchy problem. Only the last time point must be returned in the form (u = ...) Default: nothing\nflowTimeSol::Any: Flow which returns the tuple (t, u(t)). Optional, mainly used for plotting on the user side. Default: nothing\nflowFull::Any: [Optional] The flow (or semigroup) associated to the Cauchy problem (x, p, t) -> flow(x, p, t). The whole solution on the time interval [0,t] must be returned. It is not strictly necessary to provide this, it is mainly used for plotting on the user side. Please use nothing as default. Default: nothing\njvp::Any: The differential dflow of the flow w.r.t. x, (x, p, dx, t) -> dflow(x, p, dx, t). One important thing is that we require dflow(x, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = dflow(x, p, dx, t)), the last component being the value of the derivative of the flow. Default: nothing\nvjp::Any: The adjoint differential vjpflow of the flow w.r.t. x, (x, p, dx, t) -> vjpflow(x, p, dx, t). One important thing is that we require vjpflow(x, p, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = vjpflow(x, p, dx, t)), the last component being the value of the derivative of the flow. Default: nothing\njvpSerial::Any: [Optional] Serial version of dflow. Used internally when using parallel multiple shooting. Please use nothing as default. Default: nothing\nprob::Any: [Internal] store the ODEProblem associated to the flow of the Cauchy problem Default: nothing\nprobMono::Any: [Internal] store the ODEProblem associated to the flow of the variational problem Default: nothing\nflowSerial::Any: [Internal] Serial version of the flow Default: nothing\ncallback::Any: [Internal] Store possible callback Default: nothing\ndelta::Any: [Internal] Default: 1.0e-8\n\nSimplified constructor(s)\n\nWe provide a simple constructor where you only pass the vector field F, the flow ϕ and its differential dϕ:\n\nfl = Flow(F, ϕ, dϕ)\n\nSimplified constructors for DifferentialEquations.jl\n\nThese are some simple constructors for which you only have to pass a prob::ODEProblem or prob::EnsembleProblem (for parallel computation) from DifferentialEquations.jl and an ODE time stepper like Tsit5(). Hence, you can do for example\n\nfl = Flow(prob, Tsit5(); kwargs...)\n\nwhere kwargs is passed to SciMLBase::solve. If your vector field depends on parameters p, you can define a Flow using\n\nfl = Flow(prob, Tsit5(); kwargs...)\n\nFinally, you can pass two ODEProblem where the second one is used to compute the variational equation:\n\nfl = Flow(prob1::ODEProblem, alg1, prob2::ODEProblem, alg2; kwargs...)\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"FloquetQaD","category":"page"},{"location":"library/#BifurcationKit.FloquetQaD","page":"Library","title":"BifurcationKit.FloquetQaD","text":"floquet = FloquetQaD(eigsolver::AbstractEigenSolver)\n\nThis composite type implements the computation of the eigenvalues of the monodromy matrix in the case of periodic orbits problems (based on the Shooting method or Finite Differences (Trapeze method)), also called the Floquet multipliers. The method, dubbed Quick and Dirty (QaD), is not numerically very precise for large / small Floquet exponents when the number of time sections is large because of many matrix products. It allows, nevertheless, to detect bifurcations. The arguments are as follows:\n\neigsolver::AbstractEigenSolver solver used to compute the eigenvalues.\n\nIf eigsolver == DefaultEig(), then the monodromy matrix is formed and its eigenvalues are computed. Otherwise, a Matrix-Free version of the monodromy is used.\n\ndanger: Floquet multipliers computation\nThe computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver eigsolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of eigsolver. Nevertheless, note that for most implemented eigensolvers in the current Package, the proper option is set.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"guess_from_hopf(br, ind_hopf, eigsolver::AbstractEigenSolver, M, amplitude; phase = 0)","category":"page"},{"location":"library/#BifurcationKit.guess_from_hopf-Tuple{Any, Any, AbstractEigenSolver, Any, Any}","page":"Library","title":"BifurcationKit.guess_from_hopf","text":"guess_from_hopf(\n br,\n ind_hopf,\n eigsolver,\n M,\n amplitude;\n phase\n)\n\n\nThis function returns several useful quantities regarding a Hopf bifurcation point. More precisely, it returns:\n\nthe parameter value at which a Hopf bifurcation occurs\nthe period of the bifurcated periodic orbit\na guess for the bifurcated periodic orbit\nthe equilibrium at the Hopf bifurcation point\nthe eigenvector at the Hopf bifurcation point.\n\nThe arguments are\n\nbr: the continuation branch which lists the Hopf bifurcation points\nind_hopf: index of the bifurcation branch, as in br.specialpoint\neigsolver: the eigen solver used to find the eigenvectors\nM number of time slices in the periodic orbit guess\namplitude: amplitude of the periodic orbit guess\n\n\n\n\n\n","category":"method"},{"location":"library/","page":"Library","title":"Library","text":"get_normal_form","category":"page"},{"location":"library/#BifurcationKit.get_normal_form","page":"Library","title":"BifurcationKit.get_normal_form","text":"get_normal_form(\n prob,\n br,\n id_bif;\n nev,\n verbose,\n ζs,\n lens,\n Teigvec,\n scaleζ,\n detailed,\n autodiff,\n bls\n)\n\n\nCompute the normal form of the bifurcation point located at br.specialpoint[ind_bif].\n\nArguments\n\nprob::AbstractBifurcationProblem\nbr result from a call to continuation\nind_bif index of the bifurcation point in br.specialpoint\n\nOptional arguments\n\nnev number of eigenvalues used to compute the spectral projection. This number has to be adjusted when used with iterative methods.\nverbose whether to display information\nζs list of vectors spanning the kernel of dF at the bifurcation point. Useful to enforce the basis for the normal form.\nlens::Lens specify which parameter to take the partial derivative ∂pF\nscaleζ function to normalise the kernel basis. Indeed, when used with large vectors and norm, it results in ζs and the normal form coefficient being super small.\nautodiff = true whether to use ForwardDiff for the differentiations w.r.t the parameters that are required to compute the normal form. Used for example for Bogdanov-Takens point. You can set to autodiff = false if you wish.\ndetailed = true whether to compute only a simplified normal form. Used for example for Bogdanov-Takens point.\nbls = MatrixBLS() specify Bordered linear solver. Used for example for Bogdanov-Takens point.\n\nAvailable method\n\nYou can directly call \n\nget_normal_form(br, ind_bif ; kwargs...)\n\nwhich is a shortcut for get_normal_form(getProb(br), br, ind_bif ; kwargs...).\n\nOnce the normal form nf has been computed, you can call predictor(nf, δp) to obtain an estimate of the bifurcating branch.\n\n\n\n\n\nget_normal_form(\n prob,\n br,\n id_bif;\n nev,\n verbose,\n ζs,\n lens,\n Teigvec,\n scaleζ,\n prm,\n δ,\n detailed\n)\n\n\nCompute the normal form of periodic orbits. Same arguments as the function get_normal_form for equilibria. We detail the additional keyword arguments specific to periodic orbits\n\nOptional arguments\n\nprm = true compute the normal form using Poincaré return map. For collocation, there will be another way to compute the normal form in the future.\n\n\n\n\n\n","category":"function"},{"location":"newton/#Krylov-Newton-algorithm","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"BifurcationKit is built upon the newton algorithm for solving (large-dimensional) nonlinear equations ","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"F(x)=0inmathbb R^nquad xinmathbb R^n","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Writing J(x)inmathcal L(mathbb R^n) the jacobian, the algorithm reads","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"x_n+1 = x_n - J(x_n)^-1F(x_n)","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"with initial guess x_0.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"The crux of the algorithm is to solve the linear system in y:","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"J(x_n)cdot y = F(x_n)","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"To this end, we never form J^-1 like with pinv(J) but solve the linear system directly. ","category":"page"},{"location":"newton/#Space-of-solutions","page":"Krylov-Newton algorithm","title":"Space of solutions","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"For the algorithm to be defined, a certain number of operations on x need to be available. If you pass x::AbstractArray, you should not have any problem. Otherwise, your x must comply with the requirements listed in Requested methods for Custom State.","category":"page"},{"location":"newton/#Different-Jacobians","page":"Krylov-Newton algorithm","title":"Different Jacobians","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"There are basically two ways to specify the jacobian:","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Matrix based\nMatrix-free.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"In case you pass a matrix (in effect an AbstractMatrix like a sparse one,...), you can use the default linear solver from LinearAlgebra termed the backslash operator \\. This is a direct method. This is the case 1 above.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Another possibility is to pass a function J(dx) and to use iterative linear solvers. In this case, this is termed a Krylov-Newton method. This is the case 2 above. In comparison to the Matrix-based case, there is no restriction to the number of unknowns n.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"The available linear solvers are explained in the section Linear solvers (LS).","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"One can find a full description of the Krylov-Newton method in the API. ","category":"page"},{"location":"newton/#Simple-example","page":"Krylov-Newton algorithm","title":"Simple example","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Here is a quick example to show how the basics work. In particular, the problem generates a matrix based jacobian using automatic differentiation.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"using BifurcationKit\nF(x, p) = x.^3 .- 1\nx0 = rand(10)\nprob = BifurcationProblem(F, x0, nothing)\nsol = newton(prob, NewtonPar(verbose = true))","category":"page"},{"location":"newton/#Example","page":"Krylov-Newton algorithm","title":"Example","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"The (basic) tutorial Temperature model presents all cases (direct and iterative ones).","category":"page"},{"location":"tutorials/Langmuir/#langmuir","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"In this tutorial, we try to replicate some of the results of the amazing paper [Köpf]. This example is quite a marvel in the realm of bifurcation analysis, featuring a harp-like bifurcation diagram. The equations of the thin film are as follows:","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"partial_t c=-partial_x^2leftpartial_x^2 c-c^3+c-mu zeta(x)right-V partial_x c","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"with boundary conditions","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"c(0)=c_0 quad partial_x x c(0)=partial_x c(L)=partial_x x c(L)=0","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"and where","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"zeta(x)=-frac12left1+tanh left(fracx-x_sl_sright)right","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"As can be seen in the reference above, the bifurcation diagram is significantly more involved as L increases. So we set up for the \"simple\" case L=50.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"using Revise\nusing Parameters, Setfield, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, ForwardDiff\nconst BK = BifurcationKit\n\n# norms\nnormL2(x; r = sqrt(par.Δx / L)) = norm(x, 2) * r\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"Let us define the parameters of the model","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# domain size\nL = 50.0\n\n# number of unknowns\nN = 390*3/2 |> Int\nΔx = L/(N+1)\nX = ((1:N) |> collect) .* Δx\n\n# define the (laplacian of) g function\nxs = 10.0; ls = 2.0\nΔg = @. tanh((X - xs)/ls) * (1 - tanh((X - xs)/ls)^2)/ls^2\n\n# define the parameters of the model\npar = (N = N, Δx = Δx, c0 = -0.9, σ = 1.0, μ = 0.5, ν = 0.08, Δg = Δg)\n\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/#Encoding-the-PDE","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Encoding the PDE","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# function to enforce the boundary condition\nfunction putBC!(c, c0, N)\n\t# we put boundary conditions using ghost points\n\t# this boundary condition u''(0) = 0 = c1 -2c0 + c-1 gives c-1:\n\tc[1] = 2c0-c[3]\n\t# c(0) = c0, we would like to write x[0]\n\tc[2] = c0\n\t# the boundary conditions u'(L) = u''(L) = 0 imply the ghost points values.\n\t# c'(L) = 0 = cN+2 - cN and c''(L) = 0 = cN+2 -2cN+1 + cN\n\tc[N+3] = c[N+2]\n\tc[N+4] = c[N+2]\n\treturn c\nend\n\n# implementation of the right hand side of the PDE\nfunction Flgvf!(out, x, p, t = 0.)\n\t@unpack c0, N, Δx, σ, μ, Δg, ν = p\n\tdx4 = Δx^4\n\tdx2 = Δx^2\n\t# we declare the residual\n\t# we enforce the BC\n\tc = similar(x, length(x) + 4)\n\tc[3:N+2] .= x\n\tputBC!(c, c0, N)\n\n\tfor i=3:N+2\n\t\tout[i-2] = -(σ * (c[i-2] - 4c[i-1] + 6c[i] - 4c[i+1] + c[i+2]) / dx4 +\n\t\t\t\t\t(c[i-1] - 2c[i] + c[i+1]) / (dx2) -\n\t\t\t\t\t(c[i-1]^3 - 2c[i]^3 + c[i+1]^3) / (dx2) -\n\t\t\t\t\tΔg[i-2] * μ +\n\t\t\t\t\tν * (c[i+1] - c[i-1]) / (2Δx)\n\t\t\t\t\t)\n\tend\n\treturn out\nend\nFlgvf(x, p, t = 0) = Flgvf!(similar(x), x, p, t)\n\n# compute the jacobian of the PDE at position x\n@views function JanaSP(x, p)\n\t# 63.446 μs (61 allocations: 137.97 KiB) pour N = 400\n\t# 62.807 μs (44 allocations: 168.58 KiB) pour sparse(Jana(x, p))\n\t@unpack N, Δx, σ, ν = p\n\td0 = @. (-6σ/ Δx^4 + 2/ Δx^2*(1-3x^2))\n\td0[1] += σ/ Δx^4\n\td0[end] = -(3σ/ Δx^4 - 1/ Δx^2*(1-3x[N]^2) + ν/ (2Δx))\n\td1 = @. (4σ/ Δx^4 - 1/ Δx^2*(1-3x[2:N]^2) - ν/ (2Δx))\n\tdm1 = @. (4σ/ Δx^4 - 1/ Δx^2*(1-3x[1:N-1]^2) + ν/ (2Δx))\n\td1[end] -= σ/ Δx^4\n\td2 = @. (-σ/ Δx^4) * ones(N-2)\n\tJ = spdiagm( 0 => d0,\n\t\t\t\t 1 => d1,\n\t\t\t\t -1 => dm1,\n\t\t\t\t 2 => d2,\n\t\t\t\t -2 => d2)\n\treturn J\nend\n\n# we thus define a bifurcation problem\nprob = BifurcationProblem(Flgvf, 0X .-0.9, par, (@lens _.ν );\n\t\tJ = JanaSP,\n\t\trecord_from_solution = (x, p) -> normL2(x),\n\t\tplot_solution = (x, p; kwargs...) -> plot!(X, x, subplot = 3, xlabel = \"Nx = $(length(x))\", label = \"\"))\n\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/#Continuation-of-stationary-states","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Continuation of stationary states","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We call the Krylov-Newton method to find a stationary solution. Note that for this to work, the guess has to satisfy the boundary conditions approximately.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# newton iterations to refine the guess\nopt_new = NewtonPar(tol = 1e-9, verbose = true, max_iterations = 10)\nout = newton(prob, opt_new)\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"scene = plot(X, out.u)","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We then continue the previous guess and find this very nice folded structure with many Hopf bifurcation points.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# careful here, in order to use Arpack.eig, you need rather big space\n# or compute ~100 eigenvalues\nopts_cont = ContinuationPar(\n\tp_min = -0.01, p_max = 10.1,\n\tdsmin = 1e-5, dsmax = 0.04, ds= -0.001,\n\ta = 0.75, max_steps = 600,\n\tnewton_options = setproperties(opt_new; verbose = false),\n\tnev = 10, save_eigenvectors = true, tol_stability = 1e-5, detect_bifurcation = 3,\n\tdsmin_bisection = 1e-8, max_bisection_steps = 15, n_inversion = 6, tol_bisection_eigenvalue = 1e-9, save_sol_every_step = 50)\n\n# we opt for a fast Shift-Invert eigen solver\n@set! opts_cont.newton_options.eigsolver = EigArpack(0.1, :LM)\n\nbr = @time continuation(\n\tre_make(prob, params = (@set par.ν = 0.06), u0 = out.u),\n\t# we form a sparse matrix for the bordered linear problem\n\t# and we adjust θ so that the continuation steps are larger\n\tPALC(θ = 0.4, bls = MatrixBLS()), opts_cont,\n\tplot = true, verbosity = 2,\n\tnormC = normL2)\n\nscene = plot(br, title=\"N=$N\")\t\t","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"plot(layout = grid(4, 3))\nfor (ii, s) in pairs(br.sol)\n\tplot!(X, s.x, xlabel = \"ν = $(round(s.p,digits=3))\", subplot = ii, label=\"\",tickfont = (7, :black), ylims=(-1,1.5))\nend\ntitle!(\"\")","category":"page"},{"location":"tutorials/Langmuir/#Continuation-of-Hopf-and-Fold-points","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Continuation of Hopf and Fold points","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"Let us study the continuation of Hopf and Fold points and show that they merge at a Bogdanov-Takens bifurcation point:","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# compute branch of Fold points from 7th bifurcation point on br\nsn_codim2 = continuation(br, 7, (@lens _.Δx),\n\tContinuationPar(opts_cont, p_min = -2, p_max = 0.12, ds = -0.01, dsmax = 0.01, tol_stability = 1e-8, max_steps = 325, nev=23) ;\n\t# start the problem with information from eigen elements\n\tstart_with_eigen = true,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# compute both sides of the initial condition\n\tbothside = true,\n\t# we invert the Fold linear problem using Min. Aug.\n\tjacobian_ma = :minaug,\n\t)\n\n# compute branch of Hopf points from 5th bifurcation point on br\nhp_codim2 = continuation(br, 5, (@lens _.Δx), ContinuationPar(opts_cont, p_max = 0.1, ds = -0.01, dsmax = 0.01, max_steps = 230, tol_stability = 1e-8) ;\n\t# start the problem with information from eigen elements\n\tstart_with_eigen = true,\n\t# we update the Hopf problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we invert the Hopf linear problem using Min. Aug.\n\tjacobian_ma = :minaug,\n\t)\n\n# plot the branches\nplot(sn_codim2, vars = (:Δx, :ν), branchlabel = \"Fold\")\n\nplot!(hp_codim2, vars = (:Δx, :ν), branchlabel = \"Hopf\", plotcirclesbif=true, legend = :bottomright, color = :green)","category":"page"},{"location":"tutorials/Langmuir/#Continuation-of-periodic-orbits-(FD)","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Continuation of periodic orbits (FD)","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We would like to compute the branches of periodic solutions from the Hopf points. We do this automatic branch switching as follows","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# parameters for newton\nopt_po = NewtonPar(tol = 1e-10, verbose = true, max_iterations = 50)\n\n# parameters for continuation\nopts_po_cont = ContinuationPar(dsmin = 1e-5, dsmax = 0.35, ds= -0.001,\n\tp_max = 1.0, max_steps = 3, detect_bifurcation = 0,\n\tnewton_options = setproperties(opt_po; max_iterations = 15, tol = 1e-6), plot_every_step = 1)\n\n# spatio-temporal norm\nnormL2T(x; r = sqrt(par.Δx / L), M = 1) = norm(x, 2) * r * sqrt(1/M)\n\nM = 100 # number of time sections\nbr_potrap = continuation(\n\t# arguments for branch switching\n\tbr, 5,\n\t# arguments for continuation\n\topts_po_cont, PeriodicOrbitTrapProblem(M = M, jacobian = :FullSparseInplace, update_section_every_step = 1);\n\t# parameter value used for branching\n\tδp = 1e-5,\n\t# use deflated Newton to find non-trivial solutions\n\tusedeflation = true,\n\t# algorithm to solve linear associated with periodic orbit problem\n\t# tangent algorithm along the branch, linear algo specific to PALC\n\talg = PALC(tangent = Bordered(), bls = BorderingBLS(solver = DefaultLS(), check_precision = false)),\n\tverbosity = 3, plot = true,\n\trecord_from_solution = (x, p) -> normL2T(x[1:end-1], M = M),\n\tplotSolution = (x, p; kwargs...) -> begin\n\t\t\theatmap!(reshape(x[1:end-1], N, M)'; ylabel=\"T=$(round(x[end]))\", color=:viridis, kwargs...)\n\t\t\tplot!(br, subplot=1, label=\"\")\n\t\tend,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"and we obtain the following graph. It is interesting to note that the periodic solutions converge to an homoclinic orbit here with a very large period. (Image: )","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We can do this for the other Hopf points as well. Note that, we have to increase the number of time sections M to improve the convergence to the homoclinic orbits.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"(Image: )","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"Here are some examples of periodic solutions.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"(Image: )","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"[Köpf]: Köpf and Thiele, Emergence of the Bifurcation Structure of a Langmuir–Blodgett Transfer Model., 2014","category":"page"},{"location":"faq/#FAQ","page":"Frequently asked questions","title":"FAQ","text":"","category":"section"},{"location":"faq/#How-can-I-save-a-solution-every-n-steps,-or-at-specific-parameter-values?","page":"Frequently asked questions","title":"How can I save a solution every n steps, or at specific parameter values?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can use the callback finalise_solution in the function call continuation. For example, you can use something like this to save all steps","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"function mySave(u, tau, step, contResult, personaldata)\n\tpush!(personaldata, u)\nend","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"and pass it like continuation(prob, alg, opts; finalise_solution = (z, tau, step, contResult; k...) -> mySave(z, tau, step, contResult, myData))","category":"page"},{"location":"faq/#The-Fold-/-Hopf-Continuation-does-not-work,-why?","page":"Frequently asked questions","title":"The Fold / Hopf Continuation does not work, why?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"This requires some precise computations. Have you tried passing the expression of the Jacobian instead of relying on finite differences.","category":"page"},{"location":"faq/#What-is-the-parameter-theta-about-in-ContinuationPar?","page":"Frequently asked questions","title":"What is the parameter theta about in ContinuationPar?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"See the description of continuation on the page Library.","category":"page"},{"location":"faq/#How-can-I-change-the-preconditioner-during-computations?","page":"Frequently asked questions","title":"How can I change the preconditioner during computations?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"The easiest way to achieve this is by using the callbacks provided by newton and continuation. See the documentation about these two methods. See also the example 2d Ginzburg-Landau equation","category":"page"},{"location":"faq/#How-can-I-implement-my-own-bifurcation-detection-method?","page":"Frequently asked questions","title":"How can I implement my own bifurcation detection method?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can use the callback finalise_solution but the best way is probably to use the Iterator Interface to inject your code anywhere in the continuation procedure.","category":"page"},{"location":"faq/#How-do-I-dissociate-the-computation-of-eigenvalues-from-the-jacobian-that-I-passed?","page":"Frequently asked questions","title":"How do I dissociate the computation of eigenvalues from the jacobian that I passed?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Sometimes, for example when implementing boundary conditions, you pass a jacobian J but the eigenvalues, and the bifurcation points are not simply related to J. One way to bypass this issue is to define a new eigensolver <: AbstractEigenSolver and pass it to the NewtonPar field eigsolver. This is done for example in example/SH2d-fronts-cuda.jl.","category":"page"},{"location":"faq/#How-can-I-print-the-eigenvalues-during-continuation?","page":"Frequently asked questions","title":"How can I print the eigenvalues during continuation?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can print the eigenvalues using the following callback:","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"finalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\tBK.haseigenvalues(contResult) && Base.display(contResult.eig[end].eigenvals)\n\t\treturn true\n\tend,","category":"page"},{"location":"faq/#How-can-I-reject-a-Newton-Step?","page":"Frequently asked questions","title":"How can I reject a Newton Step?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can reject a newton step by passing to continuation the argument callback_newton","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"function mycallback((x, f, J, res, iteration, itlinear, options); kwargs...)\n\t# stop Newton algo if residual too large\n\tif res > 1e2\n\t\t@warn \"Reject Newton step!!\"\n\t\treturn false\n\tend\n\treturn true\nend","category":"page"},{"location":"faq/#How-do-I-stop-continuation?","page":"Frequently asked questions","title":"How do I stop continuation?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Using the argument finalise_solution in continuation. Simply make this function finalise_solution return false.","category":"page"},{"location":"faq/#How-do-I-compute-both-sides-of-a-branch?","page":"Frequently asked questions","title":"How do I compute both sides of a branch?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Instead of using two calls to continuation, you can pass the keyword bothside=true to continuation","category":"page"},{"location":"faq/#How-do-I-compute-period-orbits-for-non-autonomous-problems","page":"Frequently asked questions","title":"How do I compute period orbits for non-autonomous problems","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"The package does not yet allow to compute periodic orbits solutions of non-autonomous Cauchy problems like","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"fracdudt = F(u par t)","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"On certain cases, one can still go away with the following trick. Say one is interested (dummy example!) to study","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"dot u = cos(u) + cos(omega cdot t)","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Then one can use the following autonomous vector field","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"function vectorField(U, par)\n\tu, x, y = U\n\tout = similar(U)\n\tout[1] = cos(u) + x\n\tx2 = x^2+y^2\n\tout[2] = x + par.ω * y - x * x2\n\tout[3] = y - par.ω * x - y * x2\n\tout\nend","category":"page"},{"location":"faq/#Arpack-is-slow-in-computing-eigenvalues","page":"Frequently asked questions","title":"Arpack is slow in computing eigenvalues","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"This is probably due to iterative refinement conducted by SuiteSparse as explained in this blog post. You can disable this using","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"using SuiteSparse\nSuiteSparse.UMFPACK.umf_ctrl[8] = 0","category":"page"},{"location":"faq/#Should-I-use-CVODE_BDF?","page":"Frequently asked questions","title":"Should I use CVODE_BDF?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"SciML is now able to match the performance of the Sundials solver CVODE_BDF. Check the news for more information.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/#sh1d","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"","category":"section"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Pages = [\"Swift-Hohenberg1d.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"In this tutorial, we will see how to compute automatically the bifurcation diagram of the 1d Swift-Hohenberg equation. This example is treated in pde2path.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"-(I+Delta)^2 u+lambdacdot u +nu u^3-u^5 = 0tagE","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"with Dirichlet boundary conditions. We use a Sparse Matrix to express the operator L_1=(I+Delta)^2. We start by loading the packages:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"using Revise\nusing SparseArrays, LinearAlgebra, DiffEqOperators, Setfield, Parameters\nusing BifurcationKit\nusing Plots\nconst BK = BifurcationKit","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We then define a discretization of the problem","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"# discretisation\nN = 200\nl = 6.\nX = -l .+ 2l/N*(0:N-1) |> collect\nh = X[2]-X[1]\n\n# define a norm\nconst _weight = rand(N)\nnormweighted(x) = norm(_weight .* x)\n\n# boundary condition\nQ = Dirichlet0BC(h |> typeof)\nΔ = sparse(CenteredDifference(2, 2, h, N) * Q)[1]\nL1 = -(I + Δ)^2\n\n# functional of the problem\nfunction R_SH(u, par)\n\t@unpack λ, ν, L1 = par\n\tout = similar(u)\n\tout .= L1 * u .+ λ .* u .+ ν .* u.^3 - u.^5\nend\n\n# jacobian\nJac_sp(u, par) = par.L1 + spdiagm(0 => par.λ .+ 3 .* par.ν .* u.^2 .- 5 .* u.^4)\n\n# second derivative\nd2R(u,p,dx1,dx2) = @. p.ν * 6u*dx1*dx2 - 5*4u^3*dx1*dx2\n\n# third derivative\nd3R(u,p,dx1,dx2,dx3) = @. p.ν * 6dx3*dx1*dx2 - 5*4*3u^2*dx1*dx2*dx3\n\n# parameters associated with the equation\nparSH = (λ = -0.7, ν = 2., L1 = L1)\n\n# initial condition\nsol0 = zeros(N)\n\n# Bifurcation Problem\nprob = BifurcationProblem(R_SH, sol0, parSH, (@lens _.λ); J = Jac_sp,\n\trecord_from_solution = (x, p) -> (n2 = norm(x), nw = normweighted(x), s = sum(x), s2 = x[end ÷ 2], s4 = x[end ÷ 4], s5 = x[end ÷ 5]),\n\tplot_solution = (x, p;kwargs...)->(plot!(X, x; ylabel=\"solution\", label=\"\", kwargs...)))","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We then choose the parameters for continuation with precise detection of bifurcation points by bisection:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"optnew = NewtonPar(verbose = false, tol = 1e-12)\nopts = ContinuationPar(dsmin = 0.0001, dsmax = 0.01, ds = 0.01, p_max = 1.,\n\tnewton_options = setproperties(optnew; max_iterations = 30, tol = 1e-8),\n\tmax_steps = 300, plot_every_step = 40,\n\tdetect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-17, dsmin_bisection = 1e-7)","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Before we continue, it is useful to define a callback (see continuation) for newton to avoid spurious branch switching. It is not strictly necessary for what follows.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"function cb(state; kwargs...)\n\t_x = get(kwargs, :z0, nothing)\n\tfromNewton = get(kwargs, :fromNewton, false)\n\tif ~fromNewton\n\t\t# if the residual is too large or if the parameter jump\n\t\t# is too big, abort continuation step\n\t\treturn norm(_x.u - state.x) < 20.5 && abs(_x.p - state.p) < 0.05\n\tend\n\ttrue\nend","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Next, we specify the arguments to be used during continuation, such as plotting function, tangent predictors, callbacks...","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"args = (verbosity = 0,\n\tplot = true,\n\tcallback_newton = cb, halfbranch = true,\n\t)","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Depending on the level of recursion in the bifurcation diagram, we change a bit the options as follows","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"function optrec(x, p, l; opt = opts)\n\tlevel = l\n\tif level <= 2\n\t\treturn setproperties(opt; max_steps = 300, detect_bifurcation = 3,\n\t\t\tnev = N, detect_loop = false)\n\telse\n\t\treturn setproperties(opt; max_steps = 250, detect_bifurcation = 3,\n\t\t\tnev = N, detect_loop = true)\n\tend\nend","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"tip: Tuning\nThe function optrec modifies the continuation options opts as function of the branching level. It can be used to alter the continuation parameters inside the bifurcation diagram.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We are now in position to compute the bifurcation diagram","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"diagram = @time bifurcationdiagram(re_make(prob, params = @set parSH.λ = -0.1),\n\tPALC(),\n\t# here we specify a maximum branching level of 4\n\t4, optrec; args...)","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"After ~700s, you can plot the result ","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"plot(diagram; plotfold = false, \n\tmarkersize = 2, putspecialptlegend = false, xlims=(-1,1))\ntitle!(\"#branches = $(size(diagram))\")","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Et voilà!","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/#Exploration-of-the-diagram","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"Exploration of the diagram","text":"","category":"section"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"The bifurcation diagram diagram is stored as tree:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"julia> diagram\n[Bifurcation diagram]\n ┌─ From 0-th bifurcation point.\n ├─ Children number: 5\n └─ Root (recursion level 1)\n ┌─ Number of points: 82\n ├─ Branch of EquilibriumCont\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter l starts at -0.1, ends at 1.0\n ├─ Algo: PALC\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, bp at λ ≈ +0.00739184 ∈ (+0.00694990, +0.00739184), |δp|=4e-04, [converged], δ = ( 1, 0), step = 8, eigenelements in eig[ 9], ind_ev = 1\n- # 2, bp at λ ≈ +0.15163058 ∈ (+0.15157533, +0.15163058), |δp|=6e-05, [converged], δ = ( 1, 0), step = 19, eigenelements in eig[ 20], ind_ev = 2\n- # 3, bp at λ ≈ +0.48386330 ∈ (+0.48386287, +0.48386330), |δp|=4e-07, [converged], δ = ( 1, 0), step = 43, eigenelements in eig[ 44], ind_ev = 3\n- # 4, bp at λ ≈ +0.53115107 ∈ (+0.53070912, +0.53115107), |δp|=4e-04, [converged], δ = ( 1, 0), step = 47, eigenelements in eig[ 48], ind_ev = 4\n- # 5, bp at λ ≈ +0.86889123 ∈ (+0.86887742, +0.86889123), |δp|=1e-05, [converged], δ = ( 1, 0), step = 71, eigenelements in eig[ 72], ind_ev = 5\n- # 6, endpoint at λ ≈ +1.00000000, step = 81","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We can access the different branches with BK.getBranch(diagram, (1,)). Alternatively, you can plot a specific branch:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"plot(diagram; code = (1,), plotfold = false, markersize = 2, putspecialptlegend = false, xlims=(-1,1))","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/#References","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"References","text":"","category":"section"},{"location":"simplehopf/#Simple-Hopf-point","page":"Simple Hopf","title":"Simple Hopf point","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"At a Hopf branch point (x_0p_0) for the problem F(xp)=0, the spectrum of the linear operator dF(x_0p_0) contains two purely imaginary pm iomega omega 0 which are simple. At such point, we can compute the normal form to transform the initial Cauchy problem","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"dot x = mathbfF(xp)","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"in large dimensions to a complex polynomial vector field (delta pequiv p-p_0):","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"dot z = zleft(a cdotdelta p + iomega + l_1z^2right)quadtext(E)","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"whose solutions give access to the solutions of the Cauchy problem in a neighborhood of (xp).","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"More precisely, if mathbfJ equiv dmathbfF(x_0p_0), then we have mathbfJzeta = iomegazeta and mathbfJbarzeta = -iomegabarzeta for some complex eigenvector zeta. It can be shown that x(t) approx x_0 + 2Re(z(t)zeta) when p=p_0+delta p.","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"tip: Coefficient $l_1$\nThe coefficient l_1 above is called the Lyapunov coefficient","category":"page"},{"location":"simplehopf/#Expression-of-the-coefficients","page":"Simple Hopf","title":"Expression of the coefficients","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"The coefficients ab above are computed as follows[Haragus]:","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"a=leftlanglemathbfF_11(zeta)+2 mathbfF_20left(zeta Psi_001right) zeta^*rightrangle","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"l_1=leftlangle 2 mathbfF_20left(zeta Psi_110right)+2 mathbfF_20left(barzeta Psi_200right)+3 mathbfF_30(zeta zeta barzeta) zeta^*rightrangle","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"where","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"beginaligned\n-mathbfJ Psi_001 =mathbfF_01 \n(2 i omega-mathbfJ) Psi_200 =mathbfF_20(zeta zeta) \n-mathbfJ Psi_110 =2 mathbfF_20(zeta barzeta)\nendaligned","category":"page"},{"location":"simplehopf/#Normal-form-computation","page":"Simple Hopf","title":"Normal form computation","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"The normal form (E) is automatically computed as follows","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"get_normal_form(br::ContResult, ind_bif::Int ;\n\tverbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The above call returns an object of type Hopf.","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"simplehopf/#References","page":"Simple Hopf","title":"References","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"[Haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"detectionBifurcationPO/#Detection-of-bifurcation-points-of-periodic-orbits","page":"Bifurcation detection (1 param)","title":"Detection of bifurcation points of periodic orbits","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"contParams.detect_bifurcation = 2","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The Floquet exponent λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint. ","category":"page"},{"location":"detectionBifurcationPO/#Precise-detection-of-bifurcation-points-using-Bisection","page":"Bifurcation detection (1 param)","title":"Precise detection of bifurcation points using Bisection","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"n_inversion: number of sign inversions in the bisection algorithm\nmax_bisection_steps maximum number of bisection steps\ntol_bisection_eigenvalue tolerance on real part of Floquet exponent to detect bifurcation points in the bisection steps","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"tip: Bisection mode\nDuring the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.","category":"page"},{"location":"detectionBifurcationPO/#Large-scale-computations","page":"Bifurcation detection (1 param)","title":"Large scale computations","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"[1]: In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation. ","category":"page"},{"location":"detectionBifurcationPO/#List-of-detected-bifurcation-points","page":"Bifurcation detection (1 param)","title":"List of detected bifurcation points","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Bifurcation index used\nBifurcation point (single eigenvalue stability change, Fold or branch point) bp\nNeimark-Sacker ns\nPeriod doubling pd\nNot documented nd","category":"page"},{"location":"detectionBifurcationPO/#Eigensolver","page":"Bifurcation detection (1 param)","title":"Eigensolver","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"danger: Floquet multipliers computation\nThe computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of the eigensolver. Nevertheless, note that for most implemented eigensolvers in BifurcationKit, the proper option is automatically set. ","category":"page"},{"location":"detectionBifurcationPO/#Generic-bifurcation","page":"Bifurcation detection (1 param)","title":"Generic bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. ","category":"page"},{"location":"detectionBifurcationPO/#Fold-bifurcation","page":"Bifurcation detection (1 param)","title":"Fold bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Fold point is done by monitoring the monotonicity of the parameter.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.","category":"page"},{"location":"detectionBifurcationPO/#Neimark-Sacker-bifurcation","page":"Bifurcation detection (1 param)","title":"Neimark-Sacker bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Neimark-Sacker point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Neimark-Sacker point is detected, a point is added to br.specialpoint.","category":"page"},{"location":"detectionBifurcationPO/#Period-doubling-bifurcation","page":"Bifurcation detection (1 param)","title":"Period-doubling bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Period-doubling point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Period-doubling point is detected, a point is added to br.specialpoint.","category":"page"},{"location":"abs-from-hopf/#From-Hopf-/-PD-/-Branch-point-to-periodic-orbits","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf / PD / Branch point to periodic orbits","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"Pages = [\"abs-from-hopf.md\"]\nDepth = 3","category":"page"},{"location":"abs-from-hopf/#From-Hopf-point-to-periodic-orbits","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf point to periodic orbits","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"In order to compute the bifurcated branch of periodic solutions at a Hopf bifurcation point, you need to choose a method to compute periodic orbits among:","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"Periodic orbits based on Trapezoidal rule\nPeriodic orbits based on orthogonal collocation\nPeriodic orbits based on the shooting method","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"Once you have decided which method to use, you can call the following:","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"continuation(br::ContResult, ind_HOPF::Int, _contParams::ContinuationPar,\n\tprob::AbstractPeriodicOrbitProblem ;\n\tδp = nothing, ampfactor = 1, kwargs...)","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We refer to continuation for more information about the arguments. Here, we just say a few words about how we can specify prob::AbstractPeriodicOrbitProblem.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"For Periodic orbits based on Trapezoidal rule, you can pass PeriodicOrbitTrapProblem(M = 51) where M is the number of times slices in the periodic orbit.\nFor Periodic orbits based on orthogonal collocation, you can pass PeriodicOrbitOCollProblem(M, m) where M is the number of times slices in the periodic orbit and m is the degree of the collocation polynomials.\nFor Periodic orbits based on the shooting method, you need more parameters. For example, you can pass ShootingProblem(M, odeprob, Euler()) or PoincareShootingProblem(M, odeprob, Euler()) where odeprob::ODEProblem (see DifferentialEquations.jl) is an ODE problem to specify the Cauchy problem amd M is the number of sections.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"The simplest example is from the getting-started section. Several examples are provided in example ODE. In case of PDE, you can have a look at Brusselator or 2d Ginzburg-Landau equation.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"See Branch switching (Hopf point) for the precise method definition","category":"page"},{"location":"abs-from-hopf/#Algorithm","page":"From Hopf/PD/Branch to periodic orbits","title":"Algorithm","text":"","category":"section"},{"location":"abs-from-hopf/#From-Branch-/-Period-doubling-point-to-curve-of-periodic-orbits","page":"From Hopf/PD/Branch to periodic orbits","title":"From Branch / Period-doubling point to curve of periodic orbits","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We do not provide (for now) the automatic branching procedure for these bifurcations of periodic orbits. As a consequence, the user is asked to provide the amplitude of the bifurcated solution.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We provide the branching method for the following methods to compute periodic orbits: PeriodicOrbitTrapProblem, PeriodicOrbitOCollProblem, ShootingProblem and PoincareShootingProblem. The call is as follows. Please note that a deflation is included in this method to simplify branch switching.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"An example of use is provided in Lur'e problem.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"continuation(br::AbstractBranchResult, ind_PD::Int, contParams::ContinuationPar;\n\tδp = 0.1, ampfactor = 1, usedeflation = false, kwargs...)","category":"page"},{"location":"tutorials/tutorials/#Tutorials","page":"Tutorials","title":"Tutorials","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"tutorials.md\"]\nDepth = 2","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"The tutorials are rated by the following scale of difficulty","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"🟢 basic knowledge of (numerical) bifurcation theory (following equilibria / periodic orbits)\n🟡 advanced knowledge of (numerical) bifurcation theory (codim 2 bifurcations of equilibria)\n🟠 high level of knowledge of (numerical) bifurcation theory (codim 2 bifurcations of periodic orbits, tweaking the methods)\n🟤 very advanced tutorial, research level","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"There are three levels of automatization of the computation in these tutorials:","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"fully automatic bifurcation diagram (aBD) computation (only for equilibria): one uses bifurcationdiagram and let it compute the diagram fully automatically. Another possibility is to use deflated continuation.\nsemi-automatic bifurcation diagram computation: one uses automatic branch switching (aBS) to compute branches at specified bifurcation points\nmanual bifurcation diagram computation: one does not use automatic branch switching. This has only educational purposes or for complex problems where aBS fails.","category":"page"},{"location":"tutorials/tutorials/#ODE-examples","page":"Tutorials","title":"ODE examples","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"These examples are specific to ODEs. ","category":"page"},{"location":"tutorials/tutorials/#Computation-of-equilibria","page":"Tutorials","title":"Computation of equilibria","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsBasic1.md\", \"ode/tutorials1.md\", \"ode/tutorialPP2.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Codimension-2-bifurcations-of-equilibria","page":"Tutorials","title":"Codimension 2 bifurcations of equilibria","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialCO.md\",\"ode/lorenz84.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Periodic-orbits","page":"Tutorials","title":"Periodic orbits","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"We provide some examples focused on the computation of periodic orbits. Here is one where we present the different ways to compute periodic orbits. ","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsODE.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Here is one for aBS from period-doubling bifurcations of periodic orbits","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsODE-PD.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"In the next tutorial, we show how to refine a periodic orbit guess obtained from numerical simulation. We also show how to perform continuation of PD/NS points using Shooting or Collocation. ","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsCodim2PO.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"In the next tutorial, we showcase the detection of Chenciner bifurcations. This is a relatively advanced tutorial, so we don't give much explanations. The reader should get first familiar with the above simpler examples.","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/steinmetz.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"In the next tutorial, we showcase aBS from Bautin/HH to curve of Fold/NS of periodic orbits.","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/lorenz84-PO.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Homoclinic-orbits","page":"Tutorials","title":"Homoclinic orbits","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Based on the package HclinicBifurcationKit.jl and its docs.","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"🟡 Autonomous electronic circuit (aBS from BT)\n🟡 Nonlinear laser model","category":"page"},{"location":"tutorials/tutorials/#DAE-examples","page":"Tutorials","title":"DAE examples","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/Colpitts.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#DDE-examples","page":"Tutorials","title":"DDE examples","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"See the tutorials of DDEBifurcationKit.jl.","category":"page"},{"location":"tutorials/tutorials/#Examples-based-on-ModelingToolkit","page":"Tutorials","title":"Examples based on ModelingToolkit","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/NME-MTK.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs:-bifurcations-of-equilibria","page":"Tutorials","title":"PDEs: bifurcations of equilibria","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"tutorials1.md\", \"tutorials1b.md\", \"tutorials2.md\", \"mittelmann.md\", \"tutorials2b.md\", \"tutorialsSH3d.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs:-automatic-bifurcation-diagram","page":"Tutorials","title":"PDEs: automatic bifurcation diagram","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"Swift-Hohenberg1d.md\", \"tutorialCarrier.md\", \"ks1d.md\", \"mittelmannAuto.md\", \"ks2d.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs:-bifurcations-of-periodic-orbits","page":"Tutorials","title":"PDEs: bifurcations of periodic orbits","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"tutorials3.md\",\"tutorials3b.md\", \"BrusselatorFF.md\", \"tutorialsPD.md\", \"tutorialsCGL.md\", \"tutorialsCGLShoot.md\",\"Langmuir.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs-based-on-FEM-with-[Gridap.jl](https://github.com/gridap/Gridap.jl)","page":"Tutorials","title":"PDEs based on FEM with Gridap.jl","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"mittelmannGridap.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Symmetries,-freezing,-waves,-fronts","page":"Tutorials","title":"Symmetries, freezing, waves, fronts","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"autocatalyticAuto.md\", \"autocatalytic.md\", \"cgl1dwave.md\", \"detonationEngine.md\"]\nDepth = 1","category":"page"},{"location":"PDContinuationPO/#Continuation-of-Period-doubling-(PD)-bifurcations-of-periodic-orbits","page":"Period-Doubling continuation (2 params)","title":"Continuation of Period-doubling (PD) bifurcations of periodic orbits","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"Pages = [\"PDContinuationPO.md\"]\nDepth = 2","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"warning: Work in progress\nContinuation of PD of POs is a recent addition. It has not been thoroughly tested. ","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In this page, we explain how to perform continuation of PD points of periodic orbits and detect the following codim 2 bifurcations.","category":"page"},{"location":"PDContinuationPO/#List-of-detected-codim-2-bifurcation-points","page":"Period-Doubling continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"Bifurcation symbol used\nStrong resonance 1:2 bifurcation R2\nFold / Flip foldFlip\nPeriod-Doubling / Neimark-Sacker pdNS\nGeneralized Period-Doubling gpd","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"PDContinuationPO/#PD-continuation","page":"Period-Doubling continuation (2 params)","title":"PD continuation","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"The continuation of PD bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation), except the Trapezoid one, for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.","category":"page"},{"location":"PDContinuationPO/#Detection-of-codim-2-bifurcation-points","page":"Period-Doubling continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the option detect_codim2_bifurcation in the method continuation ","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"the detection of Generalised Period-Doubling bifurcation is done by computing the PD normal form\nthe detection the above bifurcation points is done by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"PDContinuationPO/#Setting-the-jacobian","page":"Period-Doubling continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In order to apply the newton algorithm to the PD functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the PD functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"For the case jacobian_ma = :minaug, when the shooting method is employed, the adjoint of the flow is required. This can usually be computed with ReverseDiff.jl.","category":"page"},{"location":"PDContinuationPO/#Codim-2-continuation","page":"Period-Doubling continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"To compute the codim 2 curve of PD points of periodic orbits, one can call continuation with the following options","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_pd::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"PDContinuationPO/#Algorithmic-details","page":"Period-Doubling continuation (2 params)","title":"Algorithmic details","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"The continuation of PD points is based on the formulation","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"G(upomega) = (F_po(up) sigma(up))inmathbb R^n+1quadquad (mathcal F_pd)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"where F_po is the functional for locating periodic orbits and the test function sigma is solution of","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"leftbeginarraycc\nN(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(up)\nendarrayright=leftbeginarrayc\n0_n \n1\nendarrayright","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In the case of Multiple Standard Shooting, the matrix N is based on the monodromy M(x_iT_i)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"N=left(beginarraycccccc\nM_1 -I 0 cdots 0 \n0 M_2 -I cdots 0 \nvdots cdots ddots ddots vdots \n0 cdots cdots ddots -I \nI cdots cdots 0 M_m \nendarrayright)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"The jacobian of the PD functional to use for the Newton algorithm","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"leftbeginarraycc\npartial_uF_po partial_pF_po \npartial_usigma partial_psigma\nendarrayright","category":"page"},{"location":"PDContinuationPO/#References","page":"Period-Doubling continuation (2 params)","title":"References","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"tutorials/ks1d/#1d-Kuramoto–Sivashinsky-Equation","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"","category":"section"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"Pages = [\"ks1d.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"warning: Warning\nThis is work in progress... In particular, there is a combinatorial explosion that I need to address.","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"unknown: References\nThe following example is exposed in Evstigneev, Nikolay M., and Oleg I. Ryabkov. Bifurcation Diagram of Stationary Solutions of the 2D Kuramoto-Sivashinsky Equation in Periodic Domains. Journal of Physics: Conference Series 1730, no. 1 2021","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"We study the 1d Kuramoto–Sivashinsky equation with Dirichlet boundary conditions:","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"left(2 u u+ uright)+2lambda u^(4)=0 u(0)=u(pi)=0","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"We discretize the problem by using u(x)=sum_k=1^infty u_k sin (k x) which gives","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"left(2lambda k^4-k^2right) u_k+frack2left(sum_l=1^infty u_k+l u_k-frac12 sum_l+m=k u_l u_mright)=0","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"This is a good example for the use of automatic bifurcation diagram as we shall see. Let us first encode our problem","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"using Revise, LinearAlgebra, Plots\nusing Parameters, Setfield, ForwardDiff\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# we use this library for plotting\nusing ApproxFun\n\nfunction generateLinear(n)\n\tΔ = [-k^2 for k = 1:n]\n\treturn Δ, Δ.^2\nend\n\nfunction Fks1d(a, p)\n\t@unpack Δ, Δ2, λ, N = p\n\tout = (2λ) .* (Δ2 .* a)\n\tout .+= (Δ .* a)\n\tfor l=1:N\n\t\tfor m=1:N\n\t\t\tif 0 < l+m <= N\n\t\t\t\tout[l+m] += l*a[l]*a[m]\n\t\t\tend\n\t\t\tif 0 < m-l <= N\n\t\t\t\tout[m-l] += l*a[l]*a[m]\n\t\t\tend\n\n\t\t\tif 0 < -(m-l) <= N\n\t\t\t\tout[l-m] -= l*a[l]*a[m]\n\t\t\tend\n\t\tend\n\tend\n\n\tout .*= -1\n\treturn out\nend","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"Having defined the model, we chose parameters:","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"N = 50\nΔ, Δ2 = generateLinear(N)\npar_ks = (Δ = Δ, Δ2 = Δ2, λ = 0.75, N = N)\n\n# we define a Bifurcation Problem\nprob = BifurcationProblem(Fks1d, zeros(N), par_ks, (@lens _.λ),\n record_from_solution = (x, p) -> (s = sum(x), u2 = x[3], nrm = norm(x)),\n plot_solution = (x, p; kwargs...) -> plot!(Fun(SinSpace(), x) ; kwargs...),)","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"and continuation options","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"optn = NewtonPar(verbose = false, tol = 1e-9, max_iterations = 15)\n\toptc = ContinuationPar(p_min = 1/150., p_max = 1., max_steps = 700, newton_options = optn,\n\tdsmax = 0.01, dsmin = 1e-4, ds = -0.001, detect_bifurcation = 3, nev = N, n_inversion = 8,\n\tmax_bisection_steps = 30, dsmin_bisection = 1e-10, plot_every_step = 50)\n\nkwargscont = (verbosity = 2, plot = true, normC = norm)","category":"page"},{"location":"tutorials/ks1d/#Computation-of-the-bifurcation-diagram","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"Computation of the bifurcation diagram","text":"","category":"section"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"# function to adapt continuation option to recursion level\nfunction optrec(x, p, l; opt = optc)\n\tlevel = l\n\tif level <= 2\n\t\treturn setproperties(opt; dsmax = 0.005, max_steps = 2000,\n\t\tdetect_bifurcation = 3, detect_loop = true, n_inversion = 6)\n\telse\n\t\treturn setproperties(opt; dsmax = 0.005, max_steps = 2000,\n\t\tdetect_bifurcation = 3, detect_loop = true, n_inversion = 6)\n\tend\nend\n\n# we now compute the bifurcation diagram\n# that is the connected component of (0,0)\ndiagram = @time bifurcationdiagram(prob, PALC(), 4, optrec;\n\t\tkwargscont..., verbosity = 0,\n\t\t)","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"Plotting the result can be done using","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"plot(diagram; code = (), plotfold = false, markersize = 3, putspecialptlegend = false,\n\t plotcirclesbif = true, applytoX = x->2/x, vars = (:param, :nrm),\n\t xlim = (0,150), ylim=(0,8))\ntitle!(\"#branches = $(size(diagram))\")","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"(Image: )","category":"page"},{"location":"detectionBifurcation/#Detection-of-bifurcation-points-of-Equilibria","page":"Bifurcation detection (1 param)","title":"Detection of bifurcation points of Equilibria","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"contParams.detect_bifurcation = 2","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The eigenvalue λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint. ","category":"page"},{"location":"detectionBifurcation/#Precise-detection-of-bifurcation-points-using-Bisection","page":"Bifurcation detection (1 param)","title":"Precise detection of bifurcation points using Bisection","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"n_inversion: number of sign inversions in the bisection algorithm\nmax_bisection_steps maximum number of bisection steps\ntol_bisection_eigenvalue tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"If this is still not enough, you can use a Newton solver to locate them very precisely. See Fold / Hopf Continuation.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"tip: Bisection mode\nDuring the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.","category":"page"},{"location":"detectionBifurcation/#Large-scale-computations","page":"Bifurcation detection (1 param)","title":"Large scale computations","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"[1]: In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation. ","category":"page"},{"location":"detectionBifurcation/#List-of-detected-bifurcation-points","page":"Bifurcation detection (1 param)","title":"List of detected bifurcation points","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Bifurcation index used\nFold fold\nHopf hopf\nBifurcation point (single eigenvalue stability change, Fold or branch point) bp\nNot documented nd","category":"page"},{"location":"detectionBifurcation/#Eigensolver","page":"Bifurcation detection (1 param)","title":"Eigensolver","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.","category":"page"},{"location":"detectionBifurcation/#Generic-bifurcation","page":"Bifurcation detection (1 param)","title":"Generic bifurcation","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. ","category":"page"},{"location":"detectionBifurcation/#Fold-bifurcation","page":"Bifurcation detection (1 param)","title":"Fold bifurcation","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Fold point is done by monitoring the monotonicity of the parameter.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.","category":"page"},{"location":"detectionBifurcation/#Hopf-bifurcation","page":"Bifurcation detection (1 param)","title":"Hopf bifurcation","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Hopf point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Hopf point is detected, a point is added to br.specialpoint allowing for later refinement using the function newton_hopf.","category":"page"},{"location":"intro_wave/#Freezing-problems,-symmetries-and-waves","page":"Introduction","title":"Freezing problems, symmetries and waves","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"This section is dedicated to the study of an equation (in x) F(x,p)=0 where one wishes to freeze a continuous symmetry. When the equation F(x p) = 0 has a continuous symmetry described by a Lie group G and action gcdot x for gin G, one can reduce the symmetry of the problem by considering the constrained problem[Beyn]:","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"left\nbeginarrayltagW\nF(x p) - scdot Tcdot x=0 \nlangle Tcdot x_refx-x_refrangle=0\nendarrayright","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"where T is a generator of the Lie algebra associated to G, x_ref is a reference solution and s is the speed. This is known as the freezing method.","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Similarly, one can reduce several symmetries by considering","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"left\nbeginarrayl\nF(x p) - sumlimits_i=1^N_g s_icdot T_icdot x=0 \nlangle T_icdot x_refx-x_refrangle=0quad i=1cdotsN_g\nendarrayright","category":"page"},{"location":"intro_wave/#Wave-stability","page":"Introduction","title":"Wave stability","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"There are several ways to compute the stability of a wave (x^ws^w). From [Sandstede], this requires to compute the spectrum of","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"d_1F(xp)- sumlimits_i=1^N_g s_icdot T_itagEV","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"However, there is (potentially) the zero eigenvalue associated to the eigenvectors T_icdot x^w. In practice, because the symmetry is discrete numerically, we find a small eigenvalue.","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Another way to compute the same spectrum is to proceed as follows. Using (W) as a definition for the functional G((xs)p)inmathbb R^N+1, the eigenproblem for computing the stability of a wave (x^ws^w) is","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"A x = σ BxtagGEV","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"where B = diag(1cdots10) and A=dG. An advantage of (GEV) over (EV) is that the trivial eigenvalues are removed but it comes at an increased cost. We can improved this situation as follows.","category":"page"},{"location":"intro_wave/#Case-N_g1","page":"Introduction","title":"Case N_g=1","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Let us have a look at (GEV) more closely. We need to solve for the eigenvalues sigma and the eigenvectors (x_1c_1) solutions of","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"left\nbeginarrayltagW\nJ x_1+c_1A_12 = sigma x_1 \nlangle A_21x_1rangle + A_22c_1=0\nendarrayright","category":"page"},{"location":"intro_wave/#Case-A_{22}\\neq-0","page":"Introduction","title":"Case A_22neq 0","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"If A_22neq 0, the eigen problem is equivalent to","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Jx_1 - c_1fraclangle A_21x_1rangleA_22 A_12= sigma x_1","category":"page"},{"location":"intro_wave/#Case-A_{22}-0","page":"Introduction","title":"Case A_22 = 0","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"If A_22 = 0, the eigen problem is equivalent to x_1=α A_21 + x_1^bot with langle A_21x_1^botrangle=0. Hence, I find langle A_21Jx_1^botrangle+c_1langle A_21A_12rangle=0","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Jx_1^bot-fraclangle A_21Jx_1^botranglelangle A_21A_12rangleA_21=σ x_1^","category":"page"},{"location":"intro_wave/#Encoding-of-the-functional-for-the-freezed-problem","page":"Introduction","title":"Encoding of the functional for the freezed problem","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"The freezing method is encoded in the composite type TWProblem which we loosely refer to as a Travelling Wave (TW) problem. ","category":"page"},{"location":"intro_wave/#Computation-with-newton","page":"Introduction","title":"Computation with newton","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"We provide a simplified call to newton to locate the freezed solution","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"newton(prob::TWProblem, orbitguess, options::NewtonPar; kwargs...)","category":"page"},{"location":"intro_wave/#Continuation","page":"Introduction","title":"Continuation","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"We also provide a simplified call to continuation to continue the freezed solution as function of a parameter:","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"continuation(prob::TWProblem, orbitguess, lens::Lens, contParams::ContinuationPar; jacobian = :MatrixFree, kwargs...)","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Note that in this case, the eigen solver passed in contParams is converted into an appropriate generalized eigensolver.","category":"page"},{"location":"intro_wave/#References","page":"Introduction","title":"References","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"[Sandstede]: Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.","category":"page"},{"location":"abs-from-codim2-eq/#From-codim-2-to-equilibria","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Pages = [\"abs-from-codim2-eq.md\"]\nDepth = 2","category":"page"},{"location":"abs-from-codim2-eq/#From-Bogdanov-Takens-(BT)-point-to-Fold-/-Hopf-curve","page":"From codim 2 to equilibria","title":"From Bogdanov-Takens (BT) point to Fold / Hopf curve","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"We provide an automatic branch switching method in this case (see for example Extended Lorenz-84 model or 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)). Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"continuation(br::ContResult, ind_BT::Int,\n\toptions_cont::ContinuationPar = br.contparams;\n\tnev = options_cont.nev,\n\tdetect_codim2_bifurcation::Int = 0,\n\tstart_with_eigen = false,\n\tautodiff = false,\n\tTeigvec = getvectortype(br),\n\tscaleζ = norm,\n\tkwargs...)","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"where ind_BT is the index of the BT point in br. Note that the BT has been detected during Fold or Hopf continuation. Calling the above method thus switches from Fold continuation to Hopf continuation (and vice-versa) automatically with the same parameter axis.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.","category":"page"},{"location":"abs-from-codim2-eq/#From-Zero-Hopf-(ZH)-point-to-Fold-/-Hopf-curve","page":"From codim 2 to equilibria","title":"From Zero-Hopf (ZH) point to Fold / Hopf curve","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"We provide an automatic branch switching method in this case (see for example Extended Lorenz-84 model or 2d Ginzburg-Landau). Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"continuation(br::ContResult, ind_ZH::Int,\n\toptions_cont::ContinuationPar = br.contparams;\n\tnev = options_cont.nev,\n\tdetect_codim2_bifurcation::Int = 0,\n\tstart_with_eigen = false,\n\tautodiff = false,\n\tTeigvec = getvectortype(br),\n\tscaleζ = norm,\n\tkwargs...)","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"where ind_ZH is the index of the ZH point in br. Note that the ZH has been detected during Fold or Hopf continuation. Calling the above method thus switches from Fold continuation to Hopf continuation (and vice-versa) automatically with the same parameter axis.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.","category":"page"},{"location":"abs-from-codim2-eq/#From-Hopf-Hopf-(HH)-point-to-Fold-/-Hopf-curve","page":"From codim 2 to equilibria","title":"From Hopf-Hopf (HH) point to Fold / Hopf curve","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"We provide an automatic branch switching method in this case (see for example Extended Lorenz-84 model or 2d Ginzburg-Landau equation). Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"continuation(br::ContResult, ind_HH::Int,\n\toptions_cont::ContinuationPar = br.contparams;\n\tδp = nothing, ampfactor::Real = 1,\n\tnev = options_cont.nev,\n\tdetect_codim2_bifurcation::Int = 0,\n\tstart_with_eigen = false,\n\tautodiff = false,\n\tTeigvec = getvectortype(br),\n\tscaleζ = norm,\n\tkwargs...)","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"where ind_HH is the index of the HH point in br. Note that the HH has been detected during Hopf continuation. Calling the above method thus switches from Hopf continuation to another Hopf branch automatically with the same parameter axis.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"","category":"page"},{"location":"simplebp/#Simple-bifurcation-branch-point","page":"Simple branch point","title":"Simple bifurcation branch point","text":"","category":"section"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"unknown: References\nThe general method is exposed in Golubitsky, Martin, David G Schaeffer, and Ian Stewart. Singularities and Groups in Bifurcation Theory. New York: Springer-Verlag, 1985, VI.1.d page 295","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"A simple branch point (x_0p_0) for the problem F(xp)=0 satisfies dim ker dF(x_0p_0) = 1. At such point, we can apply Lyapunov-Schmidt reduction to transform the initial problem in large dimensions to a scalar polynomial (delta p equiv p-p_0): ","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"adelta p + zleft(b_1delta p + fracb_22z + fracb_36z^2right) = 0 tagE","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"whose solutions give access to all solutions in a neighborhood of (xp).","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"More precisely, if ker dF(x_0p_0) = mathbb Rzeta, one can show that x_0+zzeta is close to a solution on a new branch, thus satisfying F(x_0+zzetap_0+delta p)approx 0.","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"In the above scalar equation,","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"if aneq 0, this is a Saddle-Node bifurcation\nif a=0b_2neq 0, the bifurcation point is a Transcritical one where the bifurcated branch exists on each side of p.\nif a=0b_2=0 b_3neq 0, the bifurcation point is a Pitchfork one where the bifurcated branch only exists on one side of p. If it exists at smaller values then p, this is a subcritical Pitchfork bifurcation. In the other case, this is a supercritical Pitchfork bifurcation.","category":"page"},{"location":"simplebp/#Normal-form-computation","page":"Simple branch point","title":"Normal form computation","text":"","category":"section"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"The reduced equation (E) can be automatically computed as follows","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"get_normal_form(br::ContResult, ind_bif::Int ;\n\tverbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"where prob is the bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BranchPoint.","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"IntroContinuation/#Continuation-methods:-introduction","page":"Introduction","title":"Continuation methods: introduction","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"Pages = [\"IntroContinuation.md\"]\nDepth = 3","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"The goal of these methods[Kuz],[Govaerts],[Rabinowitz],[Mei],[Keller] is to find solutions xinmathbb R^n to nonlinear equations","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"mathbb R^nni F(xp) = 0 quadtagE","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"as function of a real parameter p. Given a known solution (x_0p_0), we can, under reasonable assumptions, continue it by computing a 1d curve of solutions gamma = (x(s)p(s))_sin I passing through (x_0p_0).","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"For the sequel, it is convenient to use the following formalism [Kuz]","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"prediction of the next point\ncorrection\nstep size control.","category":"page"},{"location":"IntroContinuation/#Natural-continuation","page":"Introduction","title":"Natural continuation","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"More information is available at Predictors - Correctors","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"We just use this simple continuation method to give a trivial example of the formalism. Knowing (x_0 p_0), we form the predictor (x_0 p_0+ds) for some ds and use it as a guess for a Newton corrector applied to xto F(x p_0+ds). The corrector is thus the newton algorithm.","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"This continuation method is continuation(prob, Natural(), options).","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"danger: Usage\nYou should almost never use this predictor for computations. It fails at turning points, is not adaptive, ... ","category":"page"},{"location":"IntroContinuation/#Step-size-control","page":"Introduction","title":"Step size control","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"Each time the corrector phase failed, the step size ds is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size can be controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.","category":"page"},{"location":"IntroContinuation/#References","page":"Introduction","title":"References","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Kuz]: Kuznetsov, Elements of Applied Bifurcation Theory.","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Govaerts]: Govaerts, Numerical Methods for Bifurcations of Dynamical Equilibria; Allgower and Georg, Numerical Continuation Methods","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Rabinowitz]: Rabinowitz, Applications of Bifurcation Theory; Dankowicz and Schilder, Recipes for Continuation","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Mei]: Mei, Numerical Bifurcation Analysis for Reaction-Diffusion Equations","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Keller]: Keller, Lectures on Numerical Methods in Bifurcation Problems","category":"page"},{"location":"BifurcationDiagram/#Automatic-Bifurcation-diagram-computation","page":"Bifurcation diagram","title":"Automatic Bifurcation diagram computation","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"Thanks to the functionality presented in this part, we can compute the bifurcation diagram of a system recursively and fully automatically. More precisely, the function bifurcationdiagram allows to:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"compute a branch gamma of equilibria\ndetect all bifurcations on the branch\nrecursively compute the branches emanating from branch points on gamma.","category":"page"},{"location":"BifurcationDiagram/#Pitfalls","page":"Bifurcation diagram","title":"Pitfalls","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"For now, there is no way to decide if two branches gamma_1gamma_2 are the same. As a consequence:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"there is no loop detection. Hence, if the branch gamma has a component akin to a circle, you may experience a large number of branches\nif the bifurcation diagram itself has loops (see example below), you may experience a large number of branches","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"warning: Memory\nThe whole diagram is stored in RAM and you might be careful computing it on GPU. We'll add a file system for this in the future. ","category":"page"},{"location":"BifurcationDiagram/#Basic-example-with-simple-branch-points","page":"Bifurcation diagram","title":"Basic example with simple branch points","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using Revise, Plots\nusing BifurcationKit, Setfield\n\nFbp(u, p) = @. -u * (p + u * (2-5u)) * (p -.15 - u * (2+20u))\n\n# bifurcation problem\nprob = BifurcationProblem(Fbp, [0.0], -0.2, \n\t# specify the continuation parameter\n\t(@lens _);\n\trecord_from_solution = (x, p) -> x[1])\n\n# options for newton\n# we reduce a bit the tolerances to ease automatic branching\nopt_newton = NewtonPar(tol = 1e-9)\n\n# options for continuation\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.005, ds = 0.001,\n\tnewton_options = opt_newton,\n\tnev = 1,\n\t# parameter interval\n\tp_min = -1.0, p_max = .3,\n\t# detect bifurcations with bisection method\n\t# we increase here the precision for the detection of\n\t# bifurcation points\n\tn_inversion = 8)\n\ndiagram = bifurcationdiagram(prob, PALC(),\n\t# very important parameter. This specifies the maximum amount of recursion\n\t# when computing the bifurcation diagram. It means we allow computing branches of branches \n\t# at most in the present case.\n\t2,\n\t(args...) -> opts_br,\n)\n\t\n# You can plot the diagram like \nplot(diagram; putspecialptlegend=false, markersize=2, plotfold=false, title = \"#branches = $(size(diagram))\")","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"This gives","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"diagram","category":"page"},{"location":"BifurcationDiagram/#Example-with-nonsimple-branch-points","page":"Bifurcation diagram","title":"Example with nonsimple branch points","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"To show the ability of the branch switching method to cope with non simple branch points, we look at the normal form of the Pitchfork with D6 symmetry which occurs frequently in problems with hexagonal symmetry. You may want to look at Bratu–Gelfand problem for a non trivial example of use.","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using Revise, Plots\nusing BifurcationKit, Setfield, LinearAlgebra\nconst BK = BifurcationKit\n\nfunction FbpD6(x, p)\n\treturn [ p.μ * x[1] + (p.a * x[2] * x[3] - p.b * x[1]^3 - p.c*(x[2]^2 + x[3]^2) * x[1]),\n\t\tp.μ * x[2] + (p.a * x[1] * x[3] - p.b * x[2]^3 - p.c*(x[3]^2 + x[1]^2) * x[2]),\n\t\tp.μ * x[3] + (p.a * x[1] * x[2] - p.b * x[3]^3 - p.c*(x[2]^2 + x[1]^2) * x[3])]\nend\n\n# model parameters\npard6 = (μ = -0.2, a = 0.3, b = 1.5, c = 2.9)\n\n# problem\nprob = BifurcationProblem(FbpD6, zeros(3), pard6, (@lens _.μ);\n\t\trecord_from_solution = (x, p) -> (n = norminf(x)))\n\n# newton options\nopt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)\n\n# continuation options\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01, \n\t# parameter interval\n\tp_max = 0.4, p_min = -0.5, \n\tnev = 3, \n\tnewton_options = opt_newton, \n\tmax_steps = 1000, \n\tn_inversion = 4)\n\nbdiag = bifurcationdiagram(prob, PALC(), 3,\n\t(args...) -> setproperties(opts_br; p_min = -0.250, p_max = .4, ds = 0.001, dsmax = 0.005, n_inversion = 4, detect_bifurcation = 3, max_bisection_steps=20, newton_options = opt_newton);\n\tnormC = norminf)","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"We can now plot the result:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"plot(bdiag; putspecialptlegend =false, markersize=2, plotfold=false, title=\"#branch = $(size(bdiag))\")","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"(Image: )","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"We can access the different branches with BK.getBranch(bdiag, (1,)). Alternatively, you can plot a specific branch:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"(Image: )","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"Finally, you can resume the computation of the bifurcation diagram if not complete by using the syntax","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":" bifurcationdiagram!(\n\t# this resume the computation of the diagram from the 2nd node\n\t# bdiag is written inplace\n\tget_branch(bdiag, (2,)), (current = 3, maxlevel = 6), \n\t(args...) -> setproperties(opts_br; p_min = -0.250, p_max = .4, ds = 0.001, dsmax = 0.005, n_inversion = 4, detect_bifurcation = 3, dsmin_bisection =1e-18, tol_bisection_eigenvalue=1e-11, max_bisection_steps=20, newton_options = (@set opt_newton.verbose = false)))","category":"page"},{"location":"BifurcationDiagram/#Printing-the-structure-of-the-diagram","page":"Bifurcation diagram","title":"Printing the structure of the diagram","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"It is sometimes useful to have a global representation of the bifurcation diagram. Here, we provide a text representation","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using AbstractTrees\n\nAbstractTrees.children(node::BK.BifDiagNode) = node.child\n\n## Things that make printing prettier\nAbstractTrees.printnode(io::IO, node::BifDiagNode) = print(io, \"$(node.code) [ $(node.level)]\")\n\nprint_tree(bdiag)","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"which should return","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"\njulia> print_tree(bdiag)\n0 [ 1]\n├─ 1 [ 2]\n│ ├─ 2 [ 3]\n│ ├─ 2 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ └─ 4 [ 3]\n└─ 1 [ 2]\n ├─ 2 [ 3]\n └─ 2 [ 3]","category":"page"},{"location":"BifurcationDiagram/#Plotting-the-structure-of-the-diagram","page":"Bifurcation diagram","title":"Plotting the structure of the diagram","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"We can also use GraphPlot to plot the tree underlying the bifurcation diagram:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using LightGraphs, MetaGraphs, GraphPlot\n\nfunction graphFromDiagram!(_graph, diagram, indp)\n\t# ind is the index of the parent node\n\t# add vertex and associated information\n\tadd_vertex!(_graph)\n\tset_props!(_graph, nv(_graph), Dict(:code => diagram.code, :level => diagram.level))\n\tif nv(_graph) > 1\n\t\tadd_edge!(_graph, indp, nv(_graph))\n\tend\n\tif length(diagram.child) > 0\n\t\t# we now run through the children\n\t\tnew_indp = nv(_graph)\n\t\tfor diag in diagram.child\n\t\t\tgraphFromDiagram!(_graph, diag, new_indp)\n\t\tend\n\tend\nend\n\nfunction graphFromDiagram(diagram) \n\t_g = MetaGraph()\n\tgraphFromDiagram!(_g, diagram, 1)\n\treturn _g\nend\n\n_g = graphFromDiagram(bdiag)\n\ngplot(_g, nodelabel = [props(_g, ve)[:code] for ve in vertices(_g)])","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"which gives the following picture. The node label represent the index of the bifurcation point from which the branch branches.","category":"page"},{"location":"BifurcationDiagram/#Using-GraphRecipes","page":"Bifurcation diagram","title":"Using GraphRecipes","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"Another solution is to use GraphRecipes and ","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using GraphRecipes\n\ngraphplot(_g, \n\tnode_weights = ones(nv(_g)).*10, \n\tnames=[props(_g, ve)[:code] for ve in vertices(_g)], \n\tcurvature_scalar=0.)","category":"page"},{"location":"periodicOrbitTrapeze/#Periodic-orbits-based-on-Trapezoidal-rule","page":"Trapezoid","title":"Periodic orbits based on Trapezoidal rule","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The Trapezoid method allows to compute periodic orbits by discretizing time using Finite Differences based on a trapezoidal rule\t. The method is implemented in the structure PeriodicOrbitTrapProblem. The general method is very well exposed in [Uecker],[Lust] and we adopt the notations of the first reference.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We look for periodic orbits as solutions (x(0)T) of","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"M_adot x = Tcdot F(x) x(0)=x(1)inmathbb R^ntag1","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"where M_a is a mass matrix (default is the identity one).","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"In order to have a unique solution, we need to remove the phase freedom. This is done by imposing a phase condition","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"frac1Tint_0^Tlangle x(s)-x_pi(s) phi(s)rangle dsapprox frac1msumlimits_i=1^mlangle x_i - x_pii phi_irangle = 0","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"for some x_piphi which are chosen (wisely).","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We note m the number of time slices of the periodic orbit. By discretizing the above problem, we obtain","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"beginarrayl\n\t\t0= M_aleft(x_j-x_j-1right)-frach2 left(Fleft(x_jright)+Fleft(x_j-1right)right)equiv G_j(x)quad j=1cdotsm-1 \n0= x_m-x_1 equiv G_m(x) \n0=sumlimits_i=1^mlangle x_i - x_pii phi_irangle=0\nendarray","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"where x_0=x_m and h=Tm. In view of the Newton method, we study the jacobian of the above system. The Jacobian w.r.t. (x_0T) is given by","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"mathcalJ=left(beginarrayccA_1 partial_TG star dendarrayright)tag2","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"where","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A_gamma=left(beginarrayccccccc\nM_1 0 0 0 cdots -H_1 0 \n-H_2 M_2 0 0 cdots 0 0 \n0 -H_3 M_3 0 cdots 0 0 \nvdots cdots ddots ddots ddots vdots vdots \n0 cdots cdots ddots ddots 0 0 \n0 cdots cdots 0 -H_m-1 M_m-1 0 \n-gamma I 0 cdots cdots cdots 0 I\nendarrayright)","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"with M_i = M_a-\tfrac h2dF(x_i) and H_i = M_a+frac h2dF(x_i-1).","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We solve the linear equation mathcal Jcdot sol = rhs with a bordering strategy (i.e. the linear solver is a subtype of <: AbstractBorderedLinearSolver) which in turn requires to solve A_gamma z=b where z=(xx_m). We also solve this equation with a bordering strategy but this time, it can be simplified as follows. If we write b=(fg), one gets J_c x=f and x_m=g+gamma x_1 where x_1 is the first time slice of x and J_c is the following cyclic matrix:","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"J_c=left(beginarrayccccccc\nM_1 0 0 0 cdots -H_1 \n-H_2 M_2 0 0 cdots 0 \n0 -H_3 M_3 0 cdots 0 \nvdots cdots ddots ddots ddots vdots \n0 cdots cdots ddots ddots 0 \n0 cdots cdots 0 -H_m-1 M_m-1 \nendarrayright)","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Our code thus provides methods to invert J_c and A_gamma using a sparse solver or a Matrix-Free one. A preconditioner can be used.","category":"page"},{"location":"periodicOrbitTrapeze/#Encoding-of-the-functional","page":"Trapezoid","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The functional is encoded in the composite type PeriodicOrbitTrapProblem. See the link for more information, in particular on how to access the underlying functional, its jacobian and other matrices related to it like A_gamma J_c...","category":"page"},{"location":"periodicOrbitTrapeze/#Preconditioning","page":"Trapezoid","title":"Preconditioning","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We strongly advise you to use a preconditioner to deal with the above linear problem. See 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS) for an example.","category":"page"},{"location":"periodicOrbitTrapeze/#Linear-solvers","page":"Trapezoid","title":"Linear solvers","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We provide many different linear solvers to take advantage of the formulations. These solvers are available through the argument jacobian in the constructor of PeriodicOrbitTrapProblem. For example, you can pass jacobian = :FullLU. Note that all the internal solvers and jacobian are set up automatically, you don't need to do anything. However, for the sake of explanation, we detail how this works.\t","category":"page"},{"location":"periodicOrbitTrapeze/#.-FullLU","page":"Trapezoid","title":"1. FullLU","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"When using jacobianPO = :FullLU, this triggers the computation of mathcal J as in (2) at each step of newton/continuation. The jacobian matrix mathcal J is stored a SparseArray. This can be quite costly flow large n (see (1)). This jacobian is often used with the the linear solver DefaultLS().","category":"page"},{"location":"periodicOrbitTrapeze/#.-FullSparseInplace","page":"Trapezoid","title":"2. FullSparseInplace","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Same as :FullLU but the jacobian is allocated only once and updated inplace. This is much faster than :FullLU but the sparsity pattern of dF must be constant.","category":"page"},{"location":"periodicOrbitTrapeze/#.-Dense","page":"Trapezoid","title":"3. Dense","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Same as : FullSparseInplace above but the matrix dG is dense. It is also updated inplace. This is useful to study ODE of small dimension.","category":"page"},{"location":"periodicOrbitTrapeze/#.-FullMatrixFree","page":"Trapezoid","title":"4. FullMatrixFree","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A matrix free linear solver is used for mathcal J: note that a preconditioner is very likely required here because of the cyclic shape of mathcal J which affects negatively the convergence properties of iterative solvers. Note that mathcal J is never formed in this case.","category":"page"},{"location":"periodicOrbitTrapeze/#.-BorderedLU","page":"Trapezoid","title":"5. BorderedLU","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"For :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver. More precisely, the bordered structure of mathcal J is stored using the internal structure POTrapJacobianBordered. Then, mathcal J is inverted using the custom bordered linear solver PeriodicOrbitTrapBLS which is based on the bordering strategy (see Bordered linear solvers (BLS)). This particular solver is based on an explicit formula which only requires to invert A_gamma: this is done by the linear solver AγLinearSolver. In a nutshell, we have:","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"PeriodicOrbitTrapBLS = BorderingBLS(solver = AγLinearSolver(), check_precision = false)","category":"page"},{"location":"periodicOrbitTrapeze/#.-BorderedSparseInplace","page":"Trapezoid","title":"6. BorderedSparseInplace","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Same as :BorderedLU but the jacobian is allocated only once and updated inplace. This is much faster than :BorderedLU but the sparsity pattern of dF must be constant.","category":"page"},{"location":"periodicOrbitTrapeze/#.-BorderedMatrixFree","page":"Trapezoid","title":"7. BorderedMatrixFree","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A matrix free linear solver is used but for mathcal J_c only: it means that options.linsolver is used to invert mathcal J_c. ","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"info: Matrix-Free\nThese two Matrix-Free options, :FullMatrixFree and :BorderedMatrixFree, thus expose different part of the jacobian mathcal J in order to use specific preconditioners. For example, an ILU preconditioner on mathcal J_c could remove the constraints in mathcal J and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely be required.","category":"page"},{"location":"periodicOrbitTrapeze/#Floquet-multipliers-computation","page":"Trapezoid","title":"Floquet multipliers computation","text":"","category":"section"},{"location":"periodicOrbitTrapeze/#Default-method","page":"Trapezoid","title":"Default method","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A not very precise algorithm for computing the Floquet multipliers is provided in the package. The method, dubbed Quick and Dirty (QaD), is not numerically very precise for large / small Floquet exponents because it relies on constructing the monodromy matrix. ","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Note that the computation of the eigenvalues can be iterative or direct based on the eigensolver passed in arguments.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"It amounts to computing the eigenvalues of the monodromy matrix","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"mathcalM=M_1^-1 H_1 M_m-1^-1 H_m-1 cdots M_2^-1 H_2","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The method allows, nevertheless, to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. For more information, have a look at FloquetQaD.","category":"page"},{"location":"periodicOrbitTrapeze/#Most-precise-method","page":"Trapezoid","title":"Most precise method","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbitTrapeze/#Computation-with-newton","page":"Trapezoid","title":"Computation with newton","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We provide a simplified call to newton to locate the periodic orbits. Compared to the regular newton function, there is an additional option linearalgo to select one of the many ways to deal with the above linear problem. The default solver linearalgo is :BorderedLU.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Have a look at the Periodic orbits based on Trapezoidal rule example for the Brusselator for a basic example and at 2d Ginzburg-Landau equation for a more advanced one.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The docs for this specific newton are located at newton.","category":"page"},{"location":"periodicOrbitTrapeze/#Computation-with-newton-and-deflation","page":"Trapezoid","title":"Computation with newton and deflation","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We also provide a simplified call to newton to locate the periodic orbit with a deflation operator.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"newton(probPO::PeriodicOrbitTrapProblem,\n\t\torbitguess::vectype,\n\t\tdefOp::DeflationOperator{Tp, Tdot, T, vectype},\n\t\toptions::NewtonPar;\n\t\tkwargs...) where {Tp, Tdot, T, vectype}","category":"page"},{"location":"periodicOrbitTrapeze/#BifurcationKit.newton-Union{Tuple{vectype}, Tuple{T}, Tuple{Tdot}, Tuple{Tp}, Tuple{PeriodicOrbitTrapProblem, vectype, DeflationOperator{Tp, Tdot, T, vectype}, NewtonPar}} where {Tp, Tdot, T, vectype}","page":"Trapezoid","title":"BifurcationKit.newton","text":"newton(probPO, orbitguess, defOp, options; kwargs...)\n\n\nThis function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitTrapeze/#Continuation","page":"Trapezoid","title":"Continuation","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Have a look at the Periodic orbits based on Trapezoidal rule example for the Brusselator. We refer to continuation for more information regarding the arguments.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"continuation(prob::PeriodicOrbitTrapProblem,\n\t\t\t\torbitguess,\n\t\t\t\talg::BifurcationKit.AbstractContinuationAlgorithm,\n\t\t\t\t_contParams::ContinuationPar;\n\t\t\t\tkwargs...)","category":"page"},{"location":"periodicOrbitTrapeze/#BifurcationKit.continuation-Tuple{PeriodicOrbitTrapProblem, Any, BifurcationKit.AbstractContinuationAlgorithm, ContinuationPar}","page":"Trapezoid","title":"BifurcationKit.continuation","text":"continuation(\n prob,\n orbitguess,\n alg,\n _contParams;\n record_from_solution,\n linear_algo,\n kwargs...\n)\n\n\nThis is the continuation routine for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.\n\nArguments\n\nprob::PeriodicOrbitTrapProblem encodes the functional G\norbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It could be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.\nalg continuation algorithm\ncontParams same as for the regular continuation method\n\nKeyword arguments\n\nlinear_algo same as in continuation\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\nNote that by default, the method prints the period of the periodic orbit as function of the parameter. This can be changed by providing your record_from_solution argument.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitTrapeze/#References","page":"Trapezoid","title":"References","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"[Uecker]: Uecker, Hannes. Hopf Bifurcation and Time Periodic Orbits with Pde2path – Algorithms and Applications. Communications in Computational Physics 25, no. 3 (2019)","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"[Lust]: Lust, Kurt, Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, PhD thesis, 1997.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#pdlure","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"Pages = [\"tutorialsODE-PD.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"The following model is an adaptive control system of Lur’e type. It is an example from the MatCont library.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"leftbeginarrayl\ndotx=y \ndoty=z \ndotz=-alpha z-beta y-x+x^2\nendarrayright","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"The model is interesting because there is a period doubling bifurcation and we want to show the branch switching capabilities of BifurcationKit.jl in this case. We provide 3 different ways to compute this periodic orbits and highlight their pro / cons.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nrecordFromSolution(x, p) = (u1 = x[1], u2 = x[2])\n\nfunction lur!(dz, u, p, t = 0)\n\t@unpack α, β = p\n\tx, y, z = u\n\tdz[1] = y\n\tdz[2] =\tz\n\tdz[3] = -α * z - β * y - x + x^2\n\tdz\nend\n\n# parameters\npar_lur = (α = -1.0, β = 1.)\n\n# initial guess\nz0 = zeros(3)\n\n# bifurcation problem\nprob = BifurcationProblem(lur!, z0, par_lur, (@lens _.α);\n record_from_solution = recordFromSolution)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We first compute the branch of equilibria","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = -1.4, p_max = 1.8, ds = 0.01, dsmax = 0.01, plot_every_step = 20, max_steps = 1000)\n\n# computation of the branch\nbr = continuation(prob, PALC(), opts_br)\n\nscene = plot(br)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"br","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We note the Hopf bifurcation point which we shall investigate now.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#Branch-of-periodic-orbits-with-finite-differences","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"Branch of periodic orbits with finite differences","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We compute the branch of periodic orbits from the Hopf bifurcation point. We first define a plotting function and a record function which are used for all cases below:","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# plotting function\nfunction plotPO(x, p; k...)\n\txtt = get_periodic_orbit(p.prob, x, p.p)\n\tplot!(xtt.t, xtt[1,:]; markersize = 2, k...)\n\tplot!(xtt.t, xtt[2,:]; k...)\n\tplot!(xtt.t, xtt[3,:]; legend = false, k...)\nend\n\n# record function\nfunction recordPO(x, p)\n\txtt = get_periodic_orbit(p.prob, x, p.p)\n\tperiod = getperiod(p.prob, x, p.p)\n\treturn (max = maximum(xtt[1,:]), min = minimum(xtt[1,:]), period = period)\nend","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We use finite differences to discretize the problem for finding periodic orbits. We appeal to automatic branch switching as follows","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# newton parameters\noptn_po = NewtonPar(tol = 1e-8, max_iterations = 25)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.02, ds= 0.01, dsmin = 1e-4, p_max = 1.8, p_min=-1., max_steps = 80, newton_options = optn_po, tol_stability = 1e-4)\n\nMt = 120 # number of time sections\nbr_po = continuation(\n\tbr, 1, opts_po_cont,\n\tPeriodicOrbitTrapProblem(M = Mt);\n\tδp = 0.01,\n\trecord_from_solution = recordPO,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## plot previous branch\n\t\tplot!(br, subplot=1, putbifptlegend = false)\n\t\tend,\n\tnormC = norminf)\n\nscene = plot(br, br_po)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"Two period doubling bifurcations were detected. We shall now compute the branch of periodic orbits from these PD points. We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# aBS from PD\nbr_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40);\n\tverbosity = 3, plot = true,\n\tampfactor = .2, δp = -0.005,\n\tusedeflation = true,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## add previous branch\n\t\tplot!(br_po; legend=false, subplot=1)\n\tend,\n\trecord_from_solution = recordPO,\n\tnormC = norminf\n\t)\nScene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"plot(br, br_po, br_po_pd)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#Periodic-orbits-with-Parallel-Standard-Shooting","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"Periodic orbits with Parallel Standard Shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We use a different method to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl. This way of computing periodic orbits should be more precise than the previous one. We use a particular instance called multiple shooting which is computed in parallel. This is an additional advantage compared to the previous method. Finally, please note the close similarity to the code of the previous part. As before, we first rely on Hopf aBS.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"using DifferentialEquations\n\n# ODE problem for using DifferentialEquations\nprobsh = ODEProblem(lur!, copy(z0), (0., 1000.), par_lur; abstol = 1e-10, reltol = 1e-7)\n\n# newton parameters\noptn_po = NewtonPar(tol = 1e-7, max_iterations = 25)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.02, ds= -0.001, dsmin = 1e-4, max_steps = 130, newton_options = optn_po, tol_stability = 1e-5, detect_bifurcation = 3, plot_every_step = 10, n_inversion = 6, nev = 2)\n\nbr_po = continuation(\n\tbr, 1, opts_po_cont,\n\t# parallel shooting functional with 15 sections\n\tShootingProblem(15, probsh, Rodas5(); parallel = true);\n\t# first parameter value on the branch\n\tδp = 0.005,\n\tverbosity = 3, plot = true,\n\trecord_from_solution = recordPO,\n\tplot_solution = plotPO,\n\t# limit the residual, useful to help DifferentialEquations\n\tcallback_newton = BK.cbMaxNorm(10),\n\tnormC = norminf)\n\nscene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# aBS from PD\nbr_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40, dsmax = 0.01, plot_every_step = 10, ds = 0.01);\n\tverbosity = 3, plot = true,\n\tampfactor = .1, δp = -0.005,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## add previous branch\n\t\tplot!(br_po; subplot = 1)\n\tend,\n\trecord_from_solution = recordPO,\n\tnormC = norminf,\n\tcallback_newton = BK.cbMaxNorm(10),\n\t)\n\nscene = plot(br_po, br_po_pd)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#Periodic-orbits-with-orthogonal-collocation","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"Periodic orbits with orthogonal collocation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We now rely on a the state of the art method for computing periodic orbits of ODE: orthogonal collocation.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# newton parameters\noptn_po = NewtonPar(tol = 1e-10, max_iterations = 10)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(opts_br, dsmax = 0.03, ds= 0.01, dsmin = 1e-4, max_steps = 80, newton_options = optn_po, tol_stability = 1e-4, plot_every_step = 20, n_inversion = 6)\n\nbr_po = continuation(\n\tbr, 1, opts_po_cont,\n\tPeriodicOrbitOCollProblem(20, 4);\n\tampfactor = 1., δp = 0.01,\n\tverbosity = 2,\tplot = true,\n\trecord_from_solution = recordPO,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## plot previous branch\n\t\tplot!(br, subplot=1, putbifptlegend = false)\n\t\tend,\n\tnormC = norminf)\n\nscene = plot(br, br_po)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# aBS from PD\nbr_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40, ds = 0.01, dsmax = 0.05, plot_every_step = 10);\n\tverbosity = 3, plot = true,\n\tampfactor = .3, δp = -0.005,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## add previous branch\n\t\tplot!(br_po; subplot = 1)\n\tend,\n\trecord_from_solution = recordPO,\n\tnormC = norminf,\n\tcallback_newton = BK.cbMaxNorm(10),\n\t)\n\nscene = plot(br_po, br_po_pd)","category":"page"},{"location":"tutorials/tutorialCarrier/#carrier","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"","category":"section"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"unknown: References\nChapman, S. J., and P. E. Farrell. Analysis of Carrier’s Problem. ArXiv:1609.08842 [Math], September 28, 2016. http://arxiv.org/abs/1609.08842.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"In this example, we study the following singular perturbation problem:","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"epsilon^2 y^prime prime+2left(1-x^2right) y+y^2=1 quad y(-1)=y(1)=0tagE","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"It is a remarkably difficult problem which presents many disconnected branches which are not amenable to the classical continuation methods. We thus use the recently developed deflated continuation method which builds upon the Deflated Newton (see Deflated problems) techniques to find solutions which are different from a set of already known solutions.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We start with some import","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"using Revise\nusing LinearAlgebra, Parameters, Setfield, SparseArrays, BandedMatrices\n\nusing BifurcationKit, Plots\nconst BK = BifurcationKit","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"and a discretization of the problem","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"function F_carr(x, p)\n\t@unpack ϵ, X, dx = p\n\tf = similar(x)\n\tn = length(x)\n\tf[1] = x[1]\n\tf[n] = x[n]\n\tfor i=2:n-1\n\t\tf[i] = ϵ^2 * (x[i-1] - 2 * x[i] + x[i+1]) / dx^2 +\n\t\t\t2 * (1 - X[i]^2) * x[i] + x[i]^2-1\n\tend\n\treturn f\nend\n\nfunction Jac_carr(x, p)\n\t@unpack ϵ, X, dx = p\n\tn = length(x)\n\tJ = BandedMatrix{Float64}(undef, (n,n), (1,1))\n\tJ[band(-1)] .= ϵ^2/dx^2 \t\t\t\t\t\t\t\t\t# set the diagonal band\n\tJ[band(1)] .= ϵ^2/dx^2\t\t\t\t\t\t\t\t\t\t# set the super-diagonal band\n\tJ[band(0)] .= (-2ϵ^2 /dx^2) .+ 2 * (1 .- X.^2) .+ 2 .* x # set the second super-diagonal band\n\tJ[1, 1] = 1.0\n\tJ[n, n] = 1.0\n\tJ[1, 2] = 0.0\n\tJ[n, n-1] = 0.0\n\tJ\nend","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We can now use Newton to find solutions:","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"N = 200\nX = LinRange(-1,1,N)\ndx = X[2] - X[1]\npar_car = (ϵ = 0.7, X = X, dx = dx)\nsol0 = -(1 .- par_car.X.^2)\n\nrecordFromSolution(x, p) = (x[2]-x[1]) * sum(x->x^2, x)\n\nprob = BifurcationProblem(F_carr, zeros(N), par_car, (@lens _.ϵ); J = Jac_carr, record_from_solution = recordFromSolution)\n\noptnew = NewtonPar(tol = 1e-8, verbose = true)\n\tsol = @time newton(prob, optnew, normN = norminf)\nnothing #hide","category":"page"},{"location":"tutorials/tutorialCarrier/#First-try-with-automatic-bifurcation-diagram","page":"🟡 Deflated Continuation in the Carrier Problem","title":"First try with automatic bifurcation diagram","text":"","category":"section"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We can start by using our Automatic bifurcation method.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"\noptcont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= -0.01, p_min = 0.05, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, max_iterations = 20, verbose = true), max_steps = 300, detect_bifurcation = 3, nev = 40)\n\ndiagram = bifurcationdiagram(prob,\n # particular bordered linear solver to use\n\t# BandedMatrices.\n PALC(bls = BorderingBLS(solver = DefaultLS(), check_precision = false)),\n 2,\n\t(arg...) -> @set optcont.newton_options.verbose = false;\n\tplot = false)\n\nscene = plot(diagram)","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"However, this is a bit disappointing as we only find two branches.","category":"page"},{"location":"tutorials/tutorialCarrier/#Second-try-with-deflated-continuation","page":"🟡 Deflated Continuation in the Carrier Problem","title":"Second try with deflated continuation","text":"","category":"section"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"# deflation operator to hold solutions\ndeflationOp = DeflationOperator(2, dot, 1.0, [sol.u])\n\n# parameter values for the problem\npar_def = @set par_car.ϵ = 0.6\n\n# newton options\noptdef = setproperties(optnew; tol = 1e-7, max_iterations = 200)\n\n# function to encode a perturbation of the old solutions\nfunction perturbsol(sol, p, id)\n\t# we use this sol0 for the boundary conditions\n\tsol0 = @. exp(-.01/(1-par_car.X^2)^2)\n\tsolp = 0.02*rand(length(sol))\n\treturn sol .+ solp .* sol0\nend\n\n# encode the deflated continuation algo\nalg = DefCont(deflation_operator = deflationOp, perturb_solution = perturbsol, max_branches = 40)\n\n# call the deflated continuation method\nbr = @time continuation(\n\tre_make(prob; params = par_def), alg,\n\tsetproperties(optcont; ds = -0.00021, dsmin=1e-5, max_steps = 20000,\n\t\tp_max = 0.7, p_min = 0.05, detect_bifurcation = 0, plot_every_step = 40,\n\t\tnewton_options = setproperties(optnew; tol = 1e-9, max_iterations = 100, verbose = false));\n\tnormN = x -> norm(x, Inf),\n verbosity = 0,\n\t)\n\nplot(br...)","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We obtain the following result which is remarkable because it contains many more disconnected branches which we did not find in the first try.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"(Image: )","category":"page"},{"location":"hh/#Normal-form-of-the-Hopf-Hopf-bifurcation","page":"Hopf-Hopf","title":"Normal form of the Hopf-Hopf bifurcation","text":"","category":"section"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"We follow the paper[Kuznetsov],[Kuznetsov2] and consider a Cauchy problem","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"dot x=mathbf F(xp)","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"mathbf L q_1=i omega_1 q_1 quad mathbf L q_2=i omega_2 q_2","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"Under some conditions, x(t)approx x_0+2Re w_1(t)q_1+2Re w_2(t)q_2 where w_i satisfy the normal form:","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"leftbeginaligned\ndotw_1= i omega_1 w_1+frac12 G_2100 w_1leftw_1right^2+G_1011 w_1leftw_2right^2 \n +frac112 G_3200 w_1leftw_1right^4+frac12 G_2111 w_1leftw_1right^2leftw_2right^2+frac14 G_1022 w_1leftw_2right^4 \n +Oleft(leftleft(w_1 barw_1 w_2 barw_2right)right^6right) \ndotw_2= i omega_2 w_2+G_1110 w_2leftw_1right^2+frac12 G_0021 w_2leftw_2right^2 +frac14 G_2210 w_2leftw_1right^4+frac12 G_1121 w_2leftw_1right^2leftw_2right^2+frac112 G_0032 w_2leftw_2right^4 \n +Oleft(leftleft(w_1 barw_1 w_2 barw_2right)right^6right)\nendalignedrighttagE","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"This normal form is usually computed in order to branch from a Hopf-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the G_ijkl is returned.","category":"page"},{"location":"hh/#Normal-form-computation","page":"Hopf-Hopf","title":"Normal form computation","text":"","category":"section"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type HopfHopf.","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"hh/#References","page":"Hopf-Hopf","title":"References","text":"","category":"section"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"[Kuznetsov2]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.","category":"page"},{"location":"interfacePred/#Interface-for-Predictor-/-Corrector","page":"Predictor / corrector","title":"Interface for Predictor / Corrector","text":"","category":"section"},{"location":"interfacePred/","page":"Predictor / corrector","title":"Predictor / corrector","text":"Here is a description of the interface that is used to specify predictor / corrector for continuation methods. The type must be a subtype of the abstract type AbstractTangentPredictor.","category":"page"},{"location":"interfacePred/","page":"Predictor / corrector","title":"Predictor / corrector","text":"In the table below, we assume it::AbstractContinuationIterable and M = BorderedArray","category":"page"},{"location":"interfacePred/","page":"Predictor / corrector","title":"Predictor / corrector","text":"Required methods Brief description\ngetPredictor!(z_pred::M, z_old::M, τ::M, ds, pred::AbstractTangentPredictor, nrm = false) Write in z_pred a prediction for the new Newton guess given the current solution z_old, tangent τ and arc length ds.\ngetTangent!(τ::M, z_new::M, z_old::M, it, ds, θ, pred:: AbstractTangentPredictor, verbosity) Generate an estimate of the tangent to the branch of solutions at positions z_new, z_old\ncorrector(it, z_old::M, τ::M, z_pred::M, ds, θ, pred::AbstractTangentPredictor, linearalgo; normC = norm, callback = cbDefault, kwargs...) Correct the guess z_pred. Must return a tuple (sol, residuals, isconverged, it numbers, itlinear)\nOptional methods Brief description\nBase.empty!(pred::AbstractTangentPredictor) Reset the predictor","category":"page"},{"location":"modulated_wave_fd/#Modulated-waves-with-Trapezoid-method","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"","category":"section"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"This section is dedicated to the computation of modulated waves based on the Trapezoid method. Given a Cauchy problem fracdxdt = F(x)tagE we have reduced the symmetries by considering","category":"page"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"left\nbeginarrayl\nF(x p) - scdot Tcdot x=0 \nlangle Tcdot x_refx-x_refrangle=0\nendarrayrighttagFE","category":"page"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"This provides a travelling wave solution $","category":"page"},{"location":"modulated_wave_fd/#References","page":"Modulated waves with Trapezoid method","title":"References","text":"","category":"section"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"tutorials/tutorialsCGL/#cgl","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Pages = [\"tutorialsCGL.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"This example is also treated in the MATLAB library pde2path.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We look at the Ginzburg-Landau equations in 2d. The code is very similar to the Brusselator example except that some special care has to be taken in order to cope with the \"high\" dimensionality of the problem.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Note that we try to be pedagogical here. Hence, we may write \"bad\" code that we improve later. Finally, we could use all sort of tricks to take advantage of the specificity of the problem. Rather, we stay quite close to the example in the MATLAB library pde2path (and discussed in Hopf Bifurcation and Time Periodic Orbits with Pde2path – Algorithms and Applications., Uecker, Hannes, Communications in Computational Physics 25, no. 3 (2019)) for fair comparison.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"info: Goal\nWe do not use automatic branch switching here. The goal is to show our to use the internals of the package to squeeze most of the performances, use tailored options...","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The equations are as follows","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"partial_t u=Delta u+(r+mathrmi v) u-left(c_3+mathrmi muright)u^2 u-c_5u^4 u+gamma quad u=u(t x) in mathbbCquad gammainmathbb R","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"with Dirichlet boundary conditions. We discretize the square Omega = (0L_x)times(0L_y) with 2N_xN_y points. We start by writing the Laplacian:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\n\nnorminf(x) = norm(x, Inf)\n\nfunction Laplacian2D(Nx, Ny, lx, ly)\n\thx = 2lx/Nx; hy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Dirichlet0BC(typeof(hx))\n\tQy = Dirichlet0BC(typeof(hy))\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"It is then straightforward to write the vector field","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# this encodes the nonlinearity\nfunction NL(u, p)\n\t@unpack r, μ, ν, c3, c5, γ = p\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf = similar(u)\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@. f1 .= r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1 + γ\n\t@. f2 .= r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\n\treturn f\nend\n\nfunction Fcgl(u, p)\n\tf = similar(u)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and its jacobian:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"function Jcgl(u, p)\n\t@unpack r, μ, ν, c3, c5, Δ = p\n\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1u = zero(u1)\n\tf2u = zero(u1)\n\tf1v = zero(u1)\n\tf2v = zero(u1)\n\n\t@. f1u = r - 2 * u1 * (c3 * u1 - μ * u2) - c3 * ua - 4 * c5 * ua * u1^2 - c5 * ua^2\n\t@. f1v = -ν - 2 * u2 * (c3 * u1 - μ * u2) + μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2u = ν - 2 * u1 * (c3 * u2 + μ * u1) - μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2v = r - 2 * u2 * (c3 * u2 + μ * u1) - c3 * ua - 4 * c5 * ua * u2 ^2 - c5 * ua^2\n\n\tjacdiag = vcat(f1u, f2v)\n\n\tΔ + spdiagm(0 => jacdiag, n => f1v, -n => f2u)\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We now define the parameters and the stationary solution:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Nx = 41\nNy = 21\nn = Nx * Ny\nlx = pi\nly = pi/2\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)\npar_cgl = (r = 0.5, μ = 0.1, ν = 1.0, c3 = -1.0, c5 = 1.0, Δ = blockdiag(Δ, Δ), γ = 0.)\nsol0 = zeros(2Nx, Ny)\n\n# we make a problem\nprob = BK.BifurcationProblem(Fcgl, vec(sol0), par_cgl, (@lens _.r); J = Jcgl)\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and we continue it to find the Hopf bifurcation points. We use a Shift-Invert eigensolver.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# Shift-Invert eigensolver\neigls = EigArpack(1.0, :LM) # shift = 1.0\nopt_newton = NewtonPar(tol = 1e-10, verbose = true, eigsolver = eigls)\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.005, ds = 0.001, p_max = 2., detect_bifurcation = 3, nev = 5, plot_every_step = 50, newton_options = opt_newton, max_steps = 1060)\n\nbr = continuation(prob, PALC(), opts_br)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"scene = plot(br, ylims=(-0.1,0.1))","category":"page"},{"location":"tutorials/tutorialsCGL/#Normal-form-computation","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Normal form computation","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We compute the Hopf normal form of the first bifurcation point.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"hopfpt = get_normal_form(br, 1)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"So the Hopf branch is subcritical.","category":"page"},{"location":"tutorials/tutorialsCGL/#Codim-2-Hopf-continuation","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Codim 2 Hopf continuation","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Having detected 2 hopf bifurcation points, we now continue them in the plane (gamma r).","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Before we start the codim 2 continuation, we tell BifurcationKit.jl to use the spectral information start_with_eigen = true because the left eigenvector of the Jacobian is simply not the conjugate of the right one.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# we perform Hopf continuation of the first Hopf point in br\nind_hopf = 1\nbr_hopf = @time continuation(\n\tbr, ind_hopf, (@lens _.γ),\n\tContinuationPar(dsmin = 0.001, dsmax = 0.02, ds= 0.01, p_max = 6.5, p_min = -10., newton_options = opts_br.newton_options, detect_bifurcation = 1); plot = true,\n\tupdate_minaug_every_step = 1,\n\tnormC = norminf,\n\tdetect_codim2_bifurcation = 2,\n\tstart_with_eigen = true,\n\tjacobian_ma = :minaug, # specific to high dimensions\n\tbdlinsolver = BorderingBLS(solver = DefaultLS(), check_precision = false))\n\nplot(br_hopf, branchlabel = \"Hopf curve\", legend = :topleft)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"br_hopf","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now construct the curve of Fold points branching off the Bogdanov-Takens bifurcation we just detected.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# find the index of the BT point\nindbt = findfirst(x -> x.type == :bt, br_hopf.specialpoint)\n# branch from the BT point\nbrfold = continuation(br_hopf, indbt, setproperties(br_hopf.contparams; detect_bifurcation = 1, max_steps = 20);\n\tupdate_minaug_every_step = 1,\n\tdetect_codim2_bifurcation = 2,\n\tcallback_newton = BK.cbMaxNorm(1e5),\n\tbdlinsolver = BorderingBLS(solver = DefaultLS(), check_precision = false),\n\tjacobian_ma = :minaug, # specific to high dimensions\n\tbothside = true, normC = norminf)\n\nplot(br_hopf, branchlabel = \"Hopf\"); plot!(brfold, legend = :topleft, branchlabel = \"Fold\")","category":"page"},{"location":"tutorials/tutorialsCGL/#Periodic-orbits-continuation-with-stability","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Periodic orbits continuation with stability","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Having found two Hopf bifurcation points, we aim at computing the periodic orbits branching from them. Like for the Brusselator example, we need to find some educated guess for the periodic orbits in order to have a successful Newton call.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The following code is very close to the one explained in the tutorial 1d Brusselator (advanced user) so we won't give too much details here.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We focus on the first Hopf bifurcation point. Note that, we do not improve the guess for the Hopf bifurcation point, e.g. by calling newtonHopf, as this is not really needed.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# index of the Hopf point we want to branch from\nind_hopf = 1\n\n# number of time slices in the periodic orbit\nM = 30\n\n# periodic orbit initial guess from Hopf point\nr_hopf, Th, orbitguess2, hopfpt, eigvec = guess_from_hopf(br, ind_hopf, opt_newton.eigsolver,\n\t# we pass the number of time slices M, the amplitude 22*sqrt(0.1) and phase\n\tM, 22*sqrt(0.1); phase = 0.25)\n\n# flatten the initial guess\norbitguess_f2 = reduce(hcat, orbitguess2)\norbitguess_f = vcat(vec(orbitguess_f2), Th) |> vec","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We create a problem to hold the functional and compute Periodic orbits based on Trapezoidal rule","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"poTrap = PeriodicOrbitTrapProblem(\n# vector field and sparse Jacobian\n\tre_make(prob, params = (@set par_cgl.r = r_hopf - 0.01)),\n# parameters for the phase condition\n\treal.(eigvec),\n\thopfpt.u,\n# number of time slices\n\tM,\n# space dimension\n\t2n,\n# jacobian of the periodic orbit functional\n jacobian = :FullMatrixFree)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can use this (family) problem poTrap with newton on our periodic orbit guess to find a periodic orbit. Hence, one can be tempted to use","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"danger: Don't run this!!\nIt uses too much memoryopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.03, ds= 0.001, p_max = 2.5, max_steps = 250, plot_every_step = 3, newton_options = (@set opt_po.linsolver = DefaultLS()))\nbr_po = @time continuation(poTrap, vec(sol0), PALC(), opts_po_cont)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"However, the linear system associated to the newton iterations will be solved by forming the sparse jacobian of size (2N_xN_yM+1)^2 and the use of \\ (based on LU decomposition). It takes way too much time and memory.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Instead, we use a preconditioner. We build the jacobian once, compute its incomplete LU decomposition (ILU) and use it as a preconditioner.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using IncompleteLU\n\n# Sparse matrix representation of the jacobian of the periodic orbit functional\nJpo = poTrap(Val(:JacFullSparse), orbitguess_f, @set par_cgl.r = r_hopf - 0.01)\n\n# incomplete LU factorization with threshold\nPrecilu = @time ilu(Jpo, τ = 0.005);\n\n# we define the linear solver with left preconditioner Precilu\nls = GMRESIterativeSolvers(verbose = false, reltol = 1e-3, N = size(Jpo,1), restart = 40, maxiter = 50, Pl = Precilu, log=true)\n\n# we try the linear solver\nls(Jpo, rand(ls.N))","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"This converges in 7 iterations whereas, without the preconditioner, it does not converge after 100 iterations.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We set the parameters for the newton solve.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"opt_po = @set opt_newton.verbose = true\noutpo_f = @time newton(poTrap, orbitguess_f, (@set opt_po.linsolver = ls); normN = norminf)\nBK.converged(outpo_f) && printstyled(color=:red, \"--> T = \", outpo_f.u[end], \", amplitude = \", BK.amplitude(outpo_f.u, Nx*Ny, M; ratio = 2),\"\\n\")\nBK.plotPeriodicPOTrap(outpo_f.u, M, Nx, Ny; ratio = 2);","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.5432e-03 │ 0 │\n│ 1 │ 1.4372e-03 │ 8 │\n│ 2 │ 3.6731e-04 │ 8 │\n│ 3 │ 6.5658e-05 │ 9 │\n│ 4 │ 4.3028e-06 │ 10 │\n│ 5 │ 6.4509e-08 │ 11 │\n│ 6 │ 2.9713e-10 │ 12 │\n│ 7 │ 2.2181e-13 │ 14 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.780986 seconds (132.31 k allocations: 1.237 GiB, 12.13% gc time)\n--> T = 6.532023020978835, amplitude = 0.2684635643839235","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"At this point, we are still wasting a lot of resources, because the matrix-free version of the jacobian of the functional uses the jacobian of the vector field x -> Jcgl(x, p). Hence, it builds M sparse matrices for each evaluation!! Let us create a problem which is fully Matrix Free:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# computation of the first derivative using automatic differentiation\nd1Fcgl(x, p, dx) = ForwardDiff.derivative(t -> Fcgl(x .+ t .* dx, p), 0.)\n\n# linear solver for solving Jcgl*x = rhs. Needed for Floquet multipliers computation\nls0 = GMRESIterativeSolvers(N = 2Nx*Ny, reltol = 1e-9, Pl = lu(I + par_cgl.Δ))\n\npoTrapMF = PeriodicOrbitTrapProblem(\n# vector field and sparse Jacobian\n\tre_make(prob, params = (@set par_cgl.r = r_hopf - 0.01), J = (x, p) -> (dx -> d1Fcgl(x, p, dx))),\n# parameters for the phase condition\n\treal.(eigvec),\n\thopfpt.u,\n# number of time slices\n\tM,\n# space dimension\n\t2n,\n ls0,\n# jacobian of the periodic orbit functional\n jacobian = :FullMatrixFree)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now use newton","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"outpo_f = @time newton(poTrapMF, orbitguess_f, (@set opt_po.linsolver = ls); normN = norminf)\nBK.converged(outpo_f) && printstyled(color=:red, \"--> T = \", outpo_f.u[end], \", amplitude = \", BK.amplitude(outpo_f.u, Nx*Ny, M; ratio = 2),\"\\n\")","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.5432e-03 │ 0 │\n│ 1 │ 1.4372e-03 │ 8 │\n│ 2 │ 3.6731e-04 │ 8 │\n│ 3 │ 6.5658e-05 │ 9 │\n│ 4 │ 4.3028e-06 │ 10 │\n│ 5 │ 6.4509e-08 │ 11 │\n│ 6 │ 2.9713e-10 │ 12 │\n│ 7 │ 2.2188e-13 │ 14 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.322440 seconds (35.03 k allocations: 459.996 MiB, 7.63% gc time)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The speedup will increase a lot for larger N_x N_y. Also, for Floquet multipliers computation, the speedup will be substantial.","category":"page"},{"location":"tutorials/tutorialsCGL/#Removing-most-allocations-(Advanced-and-Experimental)","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Removing most allocations (Advanced and Experimental)","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We show here how to remove most allocations and speed up the computations. This is an experimental feature as the Floquet multipliers computation is not yet readily available in this case. To this end, we rewrite the functional using inplace formulation and trying to avoid allocations. This can be done as follows:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# compute just the nonlinearity\nfunction NL!(f, u, p, t = 0.)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1v = @view u[1:n]\n\tu2v = @view u[n+1:2n]\n\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@inbounds for ii = 1:n\n\t\tu1 = u1v[ii]\n\t\tu2 = u2v[ii]\n\t\tua = u1^2+u2^2\n\t\tf1[ii] = r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1\n\t\tf2[ii] = r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\tend\n\treturn f\nend\n\n# derivative of the nonlinearity\nfunction dNL!(f, u, p, du)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1v = @view u[1:n]\n\tu2v = @view u[n+1:2n]\n\n\tdu1v = @view du[1:n]\n\tdu2v = @view du[n+1:2n]\n\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@inbounds for ii = 1:n\n\t\tu1 = u1v[ii]\n\t\tu2 = u2v[ii]\n\t\tdu1 = du1v[ii]\n\t\tdu2 = du2v[ii]\n\t\tua = u1^2+u2^2\n\t\tf1[ii] = (-5*c5*u1^4 + (-6*c5*u2^2 - 3*c3)*u1^2 + 2*μ*u1*u2 - c5*u2^4 - c3*u2^2 + r) * du1 +\n\t\t(-4*c5*u2*u1^3 + μ*u1^2 + (-4*c5*u2^3 - 2*c3*u2)*u1 + 3*u2^2*μ - ν) * du2\n\n\t\tf2[ii] = (-4*c5*u2*u1^3 - 3*μ*u1^2 + (-4*c5*u2^3 - 2*c3*u2)*u1 - u2^2*μ + ν) * du1 + (-c5*u1^4 + (-6*c5*u2^2 - c3)*u1^2 - 2*μ*u1*u2 - 5*c5*u2^4 - 3*c3*u2^2 + r) * du2\n\tend\n\n\treturn f\nend\n\n# inplace vector field\nfunction Fcgl!(f, u, p, t = 0.)\n\tNL!(f, u, p)\n\tmul!(f, p.Δ, u, 1., 1.)\nend\n\n# inplace derivative of the vector field\nfunction dFcgl!(f, x, p, dx)\n\tdNL!(f, x, p, dx)\n\tmul!(f, p.Δ, dx, 1., 1.)\nend\n\n# we create a problem inplace\nprobInp = BifurcationProblem(Fcgl!, vec(sol0), (@set par_cgl.r = r_hopf - 0.01), (@lens _.r); J = dFcgl!, inplace = true)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now define an inplace functional","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"ls0 = GMRESIterativeSolvers(N = 2Nx*Ny, reltol = 1e-9)#, Pl = lu(I + par_cgl.Δ))\n\npoTrapMFi = PeriodicOrbitTrapProblem(\n# vector field and sparse Jacobian\n\tprobInp,\n# parameters for the phase condition\n\treal.(eigvec),\n\thopfpt.u,\n# number of time slices\n\tM,\n# space dimension\n\t2n,\n ls0,\n# jacobian of the periodic orbit functional\n jacobian = :FullMatrixFree)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and run the newton method:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"outpo_f = @time newton(poTrapMFi, orbitguess_f, (@set opt_po.linsolver = ls); normN = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"It gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.5432e-03 │ 0 │\n│ 1 │ 1.4372e-03 │ 8 │\n│ 2 │ 3.6731e-04 │ 8 │\n│ 3 │ 6.5658e-05 │ 9 │\n│ 4 │ 4.3028e-06 │ 10 │\n│ 5 │ 6.4509e-08 │ 11 │\n│ 6 │ 2.9713e-10 │ 12 │\n│ 7 │ 2.2143e-13 │ 14 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.179854 seconds (902 allocations: 151.500 MiB)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Notice the small speed boost but the reduced allocations. At this stage, further improvements could target the use of BlockBandedMatrices.jl for the Laplacian operator, etc.","category":"page"},{"location":"tutorials/tutorialsCGL/#Other-linear-formulation","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Other linear formulation","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We could use another way to \"invert\" jacobian of the functional based on bordered techniques. We try to use an ILU preconditioner on the cyclic matrix J_c (see Periodic orbits based on Trapezoidal rule) which has a smaller memory footprint:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Jpo2 = poTrap(Val(:JacCyclicSparse), orbitguess_f, @set par_cgl.r = r_hopf - 0.1)\nPrecilu = @time ilu(Jpo2, τ = 0.005)\nls2 = GMRESIterativeSolvers(verbose = false, reltol = 1e-3, N = size(Jpo2, 1), restart = 30, maxiter = 50, Pl = Precilu, log=true)\n\nopt_po = @set opt_newton.verbose = true\noutpo_f = @time newton((@set poTrapMF.jacobian = :BorderedMatrixFree),\torbitguess_f,\n\t(@set opt_po.linsolver = ls2), normN = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"but it gives:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 3.3298e-03 │ 0 │\n│ 1 │ 9.5088e-03 │ 34 │\n│ 2 │ 1.2807e-03 │ 26 │\n│ 3 │ 7.1393e-05 │ 29 │\n│ 4 │ 4.1625e-07 │ 36 │\n│ 5 │ 1.7924e-09 │ 44 │\n│ 6 │ 6.2725e-13 │ 60 │\n└─────────────┴──────────────────────┴────────────────┘\n 3.479920 seconds (62.64 k allocations: 1009.778 MiB, 5.19% gc time)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Hence, it seems better to use the previous preconditioner.","category":"page"},{"location":"tutorials/tutorialsCGL/#Continuation-of-periodic-solutions","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Continuation of periodic solutions","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now perform continuation of the newly found periodic orbit and compute the Floquet multipliers using Matrix-Free methods.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# set the eigensolver for the computation of the Floquet multipliers\nopt_po = @set opt_po.eigsolver = EigKrylovKit(tol = 1e-3, x₀ = rand(2n), verbose = 2, dim = 25)\n\n# parameters for the continuation\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.02, ds = 0.001, p_max = 2.2, max_steps = 250, plot_every_step = 3, newton_options = (@set opt_po.linsolver = ls),\n\tnev = 5, tol_stability = 1e-7, detect_bifurcation = 0)\n\nbr_po = @time continuation(poTrapMF, outpo_f.u, PALC(),\topts_po_cont;\n\tverbosity = 2,\tplot = true,\n\tlinear_algo = BorderingBLS(solver = ls, check_precision = false),\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_potrap(x, M, Nx, Ny; ratio = 2, kwargs...),\n\trecord_from_solution = (u, p) -> BK.getamplitude(poTrapMF, u, par_cgl; ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"This gives the following bifurcation diagram:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"tip: Improved performances\nAlthough it would be \"cheating\" for fair comparisons with existing packages, there is a trick to compute the bifurcation diagram without using preconditionners. We will not detail it here but it allows to handle the case Nx = 200; Ny = 110; M = 30 and above.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We did not change the preconditioner in the previous example as it does not seem needed. Let us show how to do this nevertheless:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# callback which will be sent to newton.\n# `iteration` in the arguments refers to newton iterations\nfunction callbackPO(state; linsolver = ls, prob = poTrap, p = par_cgl, kwargs...)\n\t@show ls.N keys(kwargs)\n\t# we update the preconditioner every 10 continuation steps\n\tif mod(kwargs[:iterationC], 10) == 9 && state.it == 1\n\t\t@info \"update Preconditioner\"\n\t\tJpo = poTrap(Val(:JacCyclicSparse), state.x, (@set p.r = state.p))\n\t\tPrecilu = @time ilu(Jpo, τ = 0.003)\n\t\tls.Pl = Precilu\n\tend\n\ttrue\nend\n\nbr_po = @time continuation(poTrapMF, outpo_f.u, PALC(),\topts_po_cont;\n\tverbosity = 2,\tplot = true,\n\tcallback_newton = callbackPO,\n\tlinear_algo = BorderingBLS(solver = ls, check_precision = false),\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_potrap(x, M, Nx, Ny; ratio = 2, kwargs...),\n\trecord_from_solution = (u, p) -> BK.getamplitude(poTrapMF, u, par_cgl; ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/#Continuation-of-Fold-of-periodic-orbits","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Continuation of Fold of periodic orbits","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We continue the Fold point of the first branch of the previous bifurcation diagram in the parameter plane (r c_5). To this end, we need to be able to compute the Hessian of the periodic orbit functional. This is not yet readily available so we turn to automatic differentiation.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using ForwardDiff\n\n# computation of the second derivative of a function f\nfunction d2Fcglpb(f, x, dx1, dx2)\n return ForwardDiff.derivative(t2 -> ForwardDiff.derivative( t1-> f(x .+ t1 .* dx1 .+ t2 .* dx2,), 0.), 0.)\nend","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We select the Fold point from the branch br_po and redefine our linear solver to get the ILU preconditioner tuned close to the Fold point.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"indfold = 2\nfoldpt = foldpoint(br_po, indfold)\n\nJpo = poTrap(Val(:JacFullSparse), orbitguess_f, (@set par_cgl.r = r_hopf - 0.1))\nPrecilu = @time ilu(Jpo, τ = 0.005);\nls = GMRESIterativeSolvers(verbose = false, reltol = 1e-4, N = size(Jpo, 1), restart = 40, maxiter = 60, Pl = Precilu);","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can then use our functional to call newtonFold unlike for a regular function (see Tutorial 1). Indeed, we specify the change the parameters too much to rely on a generic algorithm.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# define a bifurcation problem for the fold\n# this will be made automatic in the future\nprobFold = BifurcationProblem((x, p) -> poTrap(x, p), foldpt, getparams(br), getlens(br);\n\t\t\tJ = (x, p) -> poTrap(Val(:JacFullSparse), x, p),\n\t\t\td2F = (x, p, dx1, dx2) -> d2Fcglpb(z -> poTrap(z, p), x, dx1, dx2))\n\noutfold = @time BK.newton_fold(\n br_po, indfold; #index of the fold point\n prob = probFold,\n\t# we change the linear solver for the one we\n\t# defined above\n\toptions = (@set opt_po.linsolver = ls),\n\tbdlinsolver = BorderingBLS(solver = ls, check_precision = false))\nBK.converged(outfold) && printstyled(color=:red, \"--> We found a Fold Point at α = \", outfold.u.p,\" from \", br_po.specialpoint[indfold].param,\"\\n\")","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and this gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 4.5937e-01 │ 0 │\n│ 1 │ 5.6013e-01 │ 20 │\n│ 2 │ 3.1385e-02 │ 23 │\n│ 3 │ 6.0620e-05 │ 29 │\n│ 4 │ 2.7839e-08 │ 39 │\n│ 5 │ 8.1593e-12 │ 45 │\n└─────────────┴──────-───────────────┴────────────────┘\n 27.289005 seconds (1.07 M allocations: 24.444 GiB, 10.12% gc time)\n--> We found a Fold Point at α = 0.9470569704262517 from 0.9481896723164748","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Finally, one can perform continuation of the Fold bifurcation point as follows CA NE MARCHE PAS","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"optcontfold = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 40.1, p_min = -10., newton_options = (@set opt_po.linsolver = ls), max_steps = 20, detect_bifurcation = 0)\n\noutfoldco = BK.continuation_fold(probFold,\n\tbr_po, indfold, (@lens _.c5),\n\toptcontfold;\n\tjacobian_ma = :minaug,\n\tbdlinsolver = BorderingBLS(solver = ls, check_precision = false),\n\tplot = true, verbosity = 2)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which yields:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"There is still room for a lot of improvements here. Basically, the idea would be to use full Matrix-Free the jacobian functional and its transpose.","category":"page"},{"location":"tutorials/tutorialsCGL/#Continuation-of-periodic-orbits-on-the-GPU-(Advanced)","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Continuation of periodic orbits on the GPU (Advanced)","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"tip: \nThis is a very neat example all done on the GPU using the following ingredients: Matrix-Free computation of periodic orbits using preconditioners.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We now take advantage of the computing power of GPUs. The section is run on an NVIDIA Tesla V100. Given the small number of unknowns, we can (only) expect significant speedup in the application of the big preconditioner.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Note that we use the parameters Nx = 82; Ny = 42; M=30.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# computation of the first derivative\nd1Fcgl(x, p, dx) = ForwardDiff.derivative(t -> Fcgl(x .+ t .* dx, p), 0.)\n\nd1NL(x, p, dx) = ForwardDiff.derivative(t -> NL(x .+ t .* dx, p), 0.)\n\nfunction dFcgl(x, p, dx)\n\tf = similar(dx)\n\tmul!(f, p.Δ, dx)\n\tnl = d1NL(x, p, dx)\n\tf .= f .+ nl\nend","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We first load CuArrays","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using CUDA\nCUDA.allowscalar(false)\nimport LinearAlgebra: mul!, axpby!\nmul!(x::CuArray, y::CuArray, α::T) where {T <: Number} = (x .= α .* y)\nmul!(x::CuArray, α::T, y::CuArray) where {T <: Number} = (x .= α .* y)\naxpby!(a::T, X::CuArray, b::T, Y::CuArray) where {T <: Number} = (Y .= a .* X .+ b .* Y)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and update the parameters","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"par_cgl_gpu = @set par_cgl.Δ = CUDA.CUSPARSE.CuSparseMatrixCSC(par_cgl.Δ);","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Then, we precompute the preconditioner on the CPU:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Jpo = poTrap(Val(:JacFullSparse), orbitguess_f, @set par_cgl.r = r_hopf - 0.01)\nPrecilu = @time ilu(Jpo, τ = 0.003)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"To invert Precilu on the GPU, we need to define a few functions which are not in CuArrays and which are related to LU decomposition:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"struct LUperso\n\tL\n\tUt\t# transpose of U in LU decomposition\nend\n\nimport Base: ldiv!\nfunction LinearAlgebra.ldiv!(_lu::LUperso, rhs::CUDA.CuArray)\n\t_x = UpperTriangular(_lu.Ut) \\ (LowerTriangular(_lu.L) \\ rhs)\n\trhs .= vec(_x)\n\tCUDA.unsafe_free!(_x)\n\trhs\nend","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Finally, for the methods in PeriodicOrbitTrapProblem to work, we need to redefine the following method. Indeed, we disable the use of scalar on the GPU to increase the speed.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"import BifurcationKit: extractPeriodFDTrap\nextractPeriodFDTrap(x::CuArray) = x[end:end]","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now define our functional:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# we create a problem for the vector field on the GUP\nprobGPU = BifurcationProblem(Fcgl,\n vec(CuArrays(zeros((x, p) -> (dx -> dFcgl(x, p, dx))))),\n (@set par_cgl_gpu.r = r_hopf - 0.01),\n (@lens _.r);\n J = (x, p) -> (dx -> dFcgl(x, p, dx)))\n\n# matrix-free problem on the gpu\nls0gpu = GMRESKrylovKit(rtol = 1e-9)\npoTrapMFGPU = PeriodicOrbitTrapProblem(\n\tprobGPU,\n\tCuArray(real.(eigvec)),\n\tCuArray(hopfpt.u),\n\tM, 2n, ls0gpu;\n jacobian = :FullMatrixFree,\n\tongpu = true) # this is required to alter the way the constraint is handled","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Let us have a look at the linear solvers and compare the speed on CPU and GPU:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"ls = GMRESKrylovKit(verbose = 2, Pl = Precilu, rtol = 1e-3, dim = 20)\n # runs in \t2.990495 seconds (785 allocations: 31.564 MiB, 0.98% gc time)\n\touth, = @time ls((Jpo), orbitguess_f)\n\nPrecilu_gpu = LUperso(LowerTriangular(CUDA.CUSPARSE.CuSparseMatrixCSR(I+Precilu.L)), UpperTriangular(CUDA.CUSPARSE.CuSparseMatrixCSR(sparse(Precilu.U'))));\nlsgpu = GMRESKrylovKit(verbose = 2, Pl = Precilu_gpu, rtol = 1e-3, dim = 20)\n\tJpo_gpu = CUDA.CUSPARSE.CuSparseMatrixCSR(Jpo);\n\torbitguess_cu = CuArray(orbitguess_f)\n\t# runs in 1.751230 seconds (6.54 k allocations: 188.500 KiB, 0.43% gc time)\n\toutd, = @time lsgpu(Jpo_gpu, orbitguess_cu)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"So we can expect a pretty descent x2 speed up in computing the periodic orbits. We can thus call newton:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"opt_po = @set opt_newton.verbose = true\noutpo_f = @time newton(poTrapMFGPU, orbitguess_cu,\n\t\t(@set opt_po.linsolver = lsgpu);\n\t\tnormN = x->maximum(abs.(x)))","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The computing time is 6.914367 seconds (2.94 M allocations: 130.348 MiB, 1.10% gc time). The same computation on the CPU, runs in 13.972836 seconds (551.41 k allocations: 1.300 GiB, 1.05% gc time).","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"You can also perform continuation, here is a simple example:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"opts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.02, ds= 0.001, p_max = 2.2, max_steps = 250, plot_every_step = 3, newton_options = (@set opt_po.linsolver = lsgpu), detect_bifurcation = 0)\nbr_po = @time continuation(poTrapMFGPU, orbitguess_cu, PALC(),\n opts_po_cont;\n verbosity = 2,\n record_from_solution = (u, p) -> getAmplitude(poTrapMFGPU, u, par_cgl_gpu), normC = x->maximum(abs.(x)))","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"info: Preconditioner update\nFor now, the preconditioner has been precomputed on the CPU which forbids its (efficient) update during continuation of a branch of periodic orbits. This could be improved using ilu0! and friends in CuArrays.","category":"page"},{"location":"tutorials/mittelmannAuto/#gelfandauto","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Pages = [\"mittelmannAuto.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"unknown: References\nThe following example is exposed in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. The Computation of Disconnected Bifurcation Diagrams. ArXiv:1603.00809 [Math], March 2, 2016. . It is also treated in Michiel Wouters. Automatic Exploration Techniques for the Numerical Continuation of Large–Scale Nonlinear Systems, 2019.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We consider the problem of Mittelmann:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Delta u +NL(lambdau) = 0","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"with Neumann boundary condition on Omega = (01)^2 and where NL(lambdau)equiv-10(u-lambda e^u). This is a good example to show how automatic bifurcation diagram computation works.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We start with some imports:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\n\n# define the sup norm\nnorm2(x) = norm(x) / sqrt(length(x))\nnormbratu(x) = norm(x .* w) / sqrt(length(x)) # the weight w is defined below\n\n# some plotting functions to simplify our life\nplotsol!(x, nx = Nx, ny = Ny; kwargs...) = heatmap!(reshape(x, nx, ny); color = :viridis, kwargs...)\nplotsol(x, nx = Nx, ny = Ny; kwargs...) = (plot();plotsol!(x, nx, ny; kwargs...))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"and with the discretization of the problem","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function Laplacian2D(Nx, Ny, lx, ly, bc = :Neumann)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Neumann0BC(hx)\n\tQy = Neumann0BC(hy)\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A\nend\n\nϕ(u, λ) = -10(u-λ*exp(u))\ndϕ(u, λ) = -10(1-λ*exp(u))\n\nfunction NL!(dest, u, p)\n\t@unpack λ = p\n\tdest .= ϕ.(u, λ)\n\treturn dest\nend\n\nNL(u, p) = NL!(similar(u), u, p)\n\nfunction Fmit!(f, u, p)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\n\treturn f\nend\n\nFmit(u, p) = Fmit!(similar(u), u, p)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"It will also prove useful to have the jacobian of our functional and the other derivatives:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function JFmit(x,p)\n\tJ = p.Δ\n\tdg = dϕ.(x, p.λ)\n\treturn J + spdiagm(0 => dg)\nend","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We need to pass the parameters associated to this problem:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Nx = 30\nNy = 30\nlx = 0.5\nly = 0.5\n\n# weight for normbratu\nconst w = (lx .+ LinRange(-lx,lx,Nx)) * (LinRange(-ly,ly,Ny))' |> vec\nw .-= minimum(w)\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)\n\n# parameters associated with the PDE\npar_mit = (λ = .01, Δ = Δ)\n\n# initial condition\nsol0 = 0*ones(Nx, Ny) |> vec\n\n# Bifurcation Problem\nprob = BifurcationProblem(Fmit, sol0, par_mit, (@lens _.λ),; J = JFmit,\n record_from_solution = (x, p) -> (x = normbratu(x), n2 = norm(x), n∞ = norminf(x)),\n plot_solution = (x, p; k...) -> plotsol!(x ; k...))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"To compute the eigenvalues, we opt for the solver in KrylovKit.jl","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"# eigensolver\neigls = EigKrylovKit(dim = 70)\n\n# options for Newton solver\nopt_newton = NewtonPar(tol = 1e-8, verbose = true, eigsolver = eigls, max_iterations = 20)\n\n# options for continuation, we want to locate very precisely the\n# bifurcation points, so we tune the bisection accordingly\nopts_br = ContinuationPar(dsmin = 0.0001, dsmax = 0.04, ds = 0.005, p_max = 3.5, p_min = 0.01, detect_bifurcation = 3, nev = 50, plot_every_step = 10, newton_options = (@set opt_newton.verbose = false), max_steps = 251, tol_stability = 1e-6, n_inversion = 6, dsmin_bisection = 1e-7, max_bisection_steps = 25, tol_bisection_eigenvalue = 1e-19)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Note that we put the option detect_bifurcation = 3 to detect bifurcations precisely with a bisection method. Indeed, we need to locate these branch points precisely to be able to call automatic branch switching.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"In order to have an output like Auto07p, we provide the finaliser (see arguments of continuation)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function finSol(z, tau, step, br; k...)\n\tif length(br.specialpoint)>0\n\t\tif br.specialpoint[end].step == step\n\t\t\tBK._show(stdout, br.specialpoint[end], step)\n\t\tend\n\tend\n\treturn true\nend","category":"page"},{"location":"tutorials/mittelmannAuto/#Automatic-bifurcation-diagram","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"Automatic bifurcation diagram","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"In order to avoid spurious branch switching, we use a callback (see continuation) to reject specific continuation steps where the jump in parameters is too large or when the residual is too large:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function cb(state; kwargs...)\n\t_x = get(kwargs, :z0, nothing)\n\tfromNewton = get(kwargs, :fromNewton, false)\n\tif ~fromNewton\n\t\treturn (norm(_x.u - state.x) < 20.5 && abs(_x.p - state.p) < 0.05)\n\tend\n\ttrue\nend","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Finally, before calling the automatic bifurcationdiagram, we need to provide a function to adjust the continuation parameters as function of the branching level (Note that this function can be constant).","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function optionsCont(x,p,l; opt0 = opts_br)\n\tif l == 1\n\t\treturn opt0\n\telseif l==2\n\t\treturn setproperties(opt0 ;detect_bifurcation = 3,ds = 0.001, a = 0.75)\n\telse\n\t\treturn setproperties(opt0 ;detect_bifurcation = 3,ds = 0.00051, dsmax = 0.01)\n\tend\nend","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We are then ready to compute the bifurcation diagram. If we choose a level 5 of recursion like","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"diagram = @time bifurcationdiagram(prob, PALC(),\n\t# important argument: this is the maximal\n\t# recursion level\n\t5,\n\toptionsCont;\n\tverbosity = 0, plot = true,\n\tcallback_newton = cb,\n\tusedeflation = true,\n\tfinalise_solution = finSol,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"this gives using plot(diagram; plotfold = false, putspecialptlegend=false, markersize=2, title = \"#branches = $(size(diagram))\"):","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We can zoom in on the left part to get","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Actually, this plot is misleading because of the symmetries. If we chose a weighted norm which breaks those symmetries and use it to print the solution, we get","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"plot(diagram; plotfold = false, putspecialptlegend=false, markersize=2,\n\ttitle = \"#branches = $(size(diagram))\", vars = (:param, :nw))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We can make more sense of these spaghetti by only plotting the first two levels of recursion","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"plot(diagram; level = (1, 2), plotfold = false, putspecialptlegend=false, markersize=2, vars = (:param, :nw))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/#Interactive-exploration","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"Interactive exploration","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We can see that the non-simple 2d branch points (magenta points) have produced non trivial branches. For example, we can look at the second bifurcation point (the first is the fold) which is composed of 8 branches","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"plot(getBranchesFromBP(diagram, 2); plotfold = false, legend = false, vars = (:param, :nw))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/#Interactive-computation","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"Interactive computation","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Let's say you have been cautious and did not launch a deep bifurcation diagram computation by using a small recursion level 2:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"diagram = bifurcationdiagram(prob, PALC(),\n\t# here the recursion level is\n\t2,\n\toptionsCont;\n\tverbosity = 0, plot = true,\n\tcallback_newton = cb,\n\tusedeflation = true,\n\tfinalise_solution = finSol,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"You would end up with this diagram","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"How can we complete this diagram without recomputing it from scratch? It is easy! For example, let us complete the magenta branches as follow","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"bifurcationdiagram!(prob,\n\t# this improves the first branch on the violet curve. Note that\n\t# for symmetry reasons, the first bifurcation point\n\t# has 8 branches\n\tget_branch(diagram, (1,)), 6, optionsCont;\n\tverbosity = 0, plot = true,\n\tcallback_newton = cb,\n\tfinalise_solution = finSol,\n\tusedeflation = true,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"This gives the following diagram. Using this call, you can pinpoint the particular location where to refine the diagram.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"EventCallback/#Event-Handling","page":"Event handling and Callback","title":"Event Handling","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.jl allows the detection of events along the branch of solutions. Its main use consists in detecting bifurcation points but they can be used and combined together by the user too.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"The events are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flag(s):","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"contParams.detect_event = 1","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"The event points are located by looking at the function defining the event (see below). The located event points are then returned in br.specialpoint.","category":"page"},{"location":"EventCallback/#Precise-detection-of-event-points-using-Bisection","page":"Event handling and Callback","title":"Precise detection of event points using Bisection","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Note that the event points detected when detect_event = 1 are only approximate event points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) event point has been detected. Hence, we only have a rough idea of where the event is located, unless your ContinuationPar().dsmax is very small... This can be improved as follows.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"If you choose detect_event = 2, a bisection algorithm is used to locate the event points more precisely. It means that we recursively track down the event. Some options in ContinuationPar control this behavior:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"n_inversion: number of sign inversions in the bisection algorithm\nmax_bisection_steps maximum number of bisection steps\ntol_param_bisection_event tolerance on parameter to locate event","category":"page"},{"location":"EventCallback/#Different-event-types","page":"Event handling and Callback","title":"Different event types","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"The set of possible events DiscreteEvent, ContinuousEvent, SetOfEvents, PairOfEvents is detailed in the Library.","category":"page"},{"location":"EventCallback/#Built-in-events","page":"Event handling and Callback","title":"Built-in events","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.SaveAtEvent","category":"page"},{"location":"EventCallback/#BifurcationKit.SaveAtEvent","page":"Event handling and Callback","title":"BifurcationKit.SaveAtEvent","text":"`SaveAtEvent(positions::Tuple)`\n\nThis event implements the detection of when the parameter values, used during continuation, equals one of the values in positions. This state is then saved in the branch.\n\nFor example, you can use it like continuation(args...; event = SaveAtEvent((1., 2., -3.)))\n\n\n\n\n\n","category":"function"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.FoldDetectEvent","category":"page"},{"location":"EventCallback/#BifurcationKit.FoldDetectEvent","page":"Event handling and Callback","title":"BifurcationKit.FoldDetectEvent","text":"`FoldDetectEvent`\n\nThis event implements the detection of Fold points based on the p-component of the tangent vector to the continuation curve. It is designed to work with PALC(tangent=Bordered()) as continuation algorithm. To use it, pass event = FoldDetectEvent to continuation.\n\n\n\n\n\n","category":"constant"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.BifDetectEvent","category":"page"},{"location":"EventCallback/#BifurcationKit.BifDetectEvent","page":"Event handling and Callback","title":"BifurcationKit.BifDetectEvent","text":"`BifDetectEvent`\n\nThis event implements the detection of bifurcations points along a continuation curve. The detection is based on monitoring the number of unstable eigenvalues. More details are given at Detection of bifurcation points of Equilibria.\n\n\n\n\n\n","category":"constant"},{"location":"EventCallback/#Examples","page":"Event handling and Callback","title":"Examples","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"We show how to use the different events. We first set up a problem as usual.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"using Revise, BifurcationKit, Setfield, ForwardDiff\nusing Plots\nconst BK = BifurcationKit\n####################################################################################################\n# test vector field for event detection\nfunction Feve(X, p)\n\tp1, p2, k = p\n\tx, y = X\n\tout = similar(X)\n\tout[1] = p1 + x - y - x^k/k\n\tout[2] = p1 + y + x - 2y^k/k\n\tout\nend\n\n# parameters for the vector field\npar = (p1 = -3., p2=-3., k=3)\n\n# bifurcation problem\nprob = BifurcationProblem(Feve, -2ones(2), par, (@lens _.p1);\n\trecord_from_solution = (x,p) -> x[1])\n\n# parameters for the continuation\nopts = ContinuationPar(dsmax = 0.1, ds = 0.001, max_steps = 128, p_min = -3., p_max = 4.0, plot_every_step = 10,\n newton_options = NewtonPar(tol = 1e-10, verbose = false, max_iterations = 5),\n # parameters specific to event detection\n detect_bifurcation = 0, detect_event = 2, n_inversion = 6, dsmin_bisection = 1e-9,\n max_bisection_steps = 15, detect_fold=false)\n\n# arguments for continuation\nargs = (prob, PALC(bls = MatrixBLS()), opts)\nkwargs = (plot = false, verbosity = 0,)\nnothing #hide","category":"page"},{"location":"EventCallback/#Example-of-continuous-event","page":"Event handling and Callback","title":"Example of continuous event","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"In this first example, we build an event to detect when the parameter value is -2 or when the first component of the solution is 1.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br = continuation(args...; kwargs...,\n\tevent = BK.ContinuousEvent(2, \n\t\t(iter, state) -> (getp(state)+2, getx(state)[1]-1)),)\nnothing #hide\t\t","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"gives","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"This shows for example that the first component of the event was detected userC-1 first. This yields","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"plot(br)","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"You can also name the events as follows","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":" br = continuation(args...; kwargs...,\n \tevent = BK.ContinuousEvent(2, \n \t\t(iter, state) -> (getp(state)+2, getx(state)[1]-1),\n \t\t(\"event1\", \"event2\")))\nnothing #hide \t\t","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"And get:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"plot(br)","category":"page"},{"location":"EventCallback/#Example-of-discrete-event","page":"Event handling and Callback","title":"Example of discrete event","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"You can also use discrete events to detect a change. For example, the following detect when the parameter value equals -2:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br = continuation(args...; kwargs...,\n\tevent = BK.DiscreteEvent(1, \n\t\t(iter, state) -> getp(state)>-2))","category":"page"},{"location":"EventCallback/#Example-of-PairOfEvents-event","page":"Event handling and Callback","title":"Example of PairOfEvents event","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Let us be a bit more creative and combine a continuous event with a discrete one:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br = continuation(args...; kwargs...,\n\tevent = BK.PairOfEvents(\n\t\tBK.ContinuousEvent(1, (iter, state) -> getp(state)),\n\t\tBK.DiscreteEvent(1, (iter, state) -> getp(state)>-2)))","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Here userD-1 means that the first component of the discrete event was detected. Of course, you can name the event like done above.","category":"page"},{"location":"EventCallback/#Example-of-set-of-events","page":"Event handling and Callback","title":"Example of set of events","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"We can combine more events and chain them like we want using SetOfEvents. In this example, we show how to do bifurcation detection and event location altogether:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"ev1 = BK.ContinuousEvent(1, (iter, state) -> getp(state)-1)\nev2 = BK.ContinuousEvent(2, (iter, state) -> (getp(state)-2, getp(state)-2.5))\n# event to detect bifurcation\nev3 = BK.BifDetectEvent\n# we combine the events together\neve = BK.SetOfEvents(ev1, ev2, ev3)\n\nbr = continuation(args...; kwargs...,\n\t\tevent = eve)","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Which gives","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"plot(br)","category":"page"},{"location":"Borderedarrays/#Bordered-Arrays","page":"Bordered arrays","title":"Bordered Arrays","text":"","category":"section"},{"location":"Borderedarrays/","page":"Bordered arrays","title":"Bordered arrays","text":"Here are some informations on a composite type which is used all over the package to hold a couple (array, array) or (array, scalar) while implementing the methods described in Requested methods for Custom State. ","category":"page"},{"location":"Borderedarrays/","page":"Bordered arrays","title":"Bordered arrays","text":"BorderedArray","category":"page"},{"location":"Borderedarrays/#BifurcationKit.BorderedArray","page":"Bordered arrays","title":"BifurcationKit.BorderedArray","text":"x = BorderedArray(vec1, vec2)\n\nThis defines an array (although not <: AbstractArray) to hold two arrays or an array and a scalar. This is useful when one wants to add constraints (phase, ...) to a functional for example. It is used throughout the package for the Pseudo Arc Length Continuation, for the continuation of Fold / Hopf points, for periodic orbits... It is also used to define periodic orbits as (orbit, period). As such, it is a convenient alternative to cat, vcat and friends. We chose not to make it a subtype of AbstractArray as we wish to apply the current package to general \"arrays\", see Requested methods for Custom State. Finally, it proves useful for the GPU where the operation x[end] can be slow.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/autocatalytic/#Modulated-fronts-in-1d-autocatalytic-model-(Manual)","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Pages = [\"autocatalytic.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We consider the following model [Balmforth][Malham] which is also treated in [Beyn]","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"beginarrayl\nu_t=a u_x x-u f(v) quad a0 u v mathbbR rightarrow mathbbR \nv_t=v_x x+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"where f(u) = u^m 1_ugeq 0. We chose the boundary conditions","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"left(u_- v_-right)=(01)quad left(u_+ v_+right)=(10)tagBC","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"It is straightforward to implement this problem as follows:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"using Revise\nusing ForwardDiff, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\n# supremum norm\nnorminf(x) = norm(x, Inf)\nf(u) = u^9 # solutions are positive, so remove the heaviside\n\n# helper function to plot solutions\nfunction plotsol!(x; k...)\n\tu = @view x[1:end÷2]\n\tv = @view x[end÷2:end]\n\tplot!(u; label=\"u\", k...)\n\tplot!(v; label=\"v\", k...)\nend\nplotsol(x; k...) = (plot();plotsol!(x; k...))\n\n# encode the nonlinearity\n@views function NL!(dest, U, p, t = 0.)\n\tN = p.N\n\tu = U[1:N]\n\tv = U[N+1:2N]\n\tdest[1:N] .= -u .* f.(v)\n\tdest[N+1:2N] .= -dest[1:N]#u .* f.(v)\n\treturn dest\nend\n\n# function for the differential with specific boundary conditions\n# for fronts\n@views function applyD_add!(f, U, p, a)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tc1 = 1 / (2p.h)\n\tf[1] += a * (uL - u[2] ) * c1\n\tf[end] += a * (v[n-1] - vR ) * c1\n\n\tf[n] += a * (u[n-1] - uR ) * c1\n\tf[n+1] += a * ( vL - v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += a * (u[i-1] - u[i+1]) * c1\n\t\tf[n+i] += a * (v[i-1] - v[i+1]) * c1\n\tend\n\treturn f\nend\n\n# function which encodes the full PDE\n@views function Fcat!(f, U, p, t = 0)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\t# nonlinearity\n\tNL!(f, U, p)\n\n\t# Dirichlet boundary conditions\n\th2 = p.h * p.h\n\tc1 = 1 / h2\n\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tf[1] += p.a * (uL - 2u[1] + u[2] ) * c1\n\tf[end] += (v[n-1] - 2v[n] + vR ) * c1\n\n\tf[n] += p.a * (u[n-1] - 2u[n] + uR ) * c1\n\tf[n+1] += (vL - 2v[1] + v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += p.a * (u[i-1] - 2u[i] + u[i+1]) * c1\n\t\tf[n+i] += (v[i-1] - 2v[i] + v[i+1]) * c1\n\tend\n\treturn f\nend\nFcat(x, p, t = 0.) = Fcat!(similar(x), x, p, t)\nJcat(x,p) = sparse(ForwardDiff.jacobian(x -> Fcat(x, p), x))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We chose the following parameters:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"N = 200\nlx = 25.\nX = LinRange(-lx,lx, N)\npar_cat = (N = N, a = 0.18, h = 2lx/N)\n\nu0 = @. (tanh(2X)+1)/2\nU0 = vcat(u0, 1 .- u0)\n\n# we define a problem to hold the vector field\nprob = BifurcationProblem(Fcat, u0, par_cat, (@lens _.a); J = Jcat)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/#Freezing-method","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"Freezing method","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"The problem may feature fronts, that is solutions of the form u(xt) = tilde u(x-st) (same for v) for a fixed value of the profile tilde u and the speed s. The equation for the front profile is, up to an abuse of notations (we removed the tildes)","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"beginarrayl\n0=a u_xixi+scdot u_xi-u f(v)\n0=v_xixi+scdot v_xi+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"with unknowns uvs. The front is solution of these equations but it is not uniquely determined because of the phase invariance. Hence, we add the phase condition (see [Beyn])","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"0 = leftlangle (uv) partial_xi (u_0v_0) rightrangle","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"where U_0=(u_0v_0) is some fixed profile. This is easily coded in the following functional","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"@views function FcatWave!(out, x, p)\n\tN = p.N\n\tU = x[1:end-1]\n\tFcat!(out[1:2N], U, p)\n\tapplyD_add!(out[1:2N], U, p, x[end])\n\t# phase condition\n\tout[2N+1] = dot(U, p.Du0)\n\treturn out\nend\nFcatWave(x, p, t = 0) = FcatWave!(similar(x), x, p)\nJcatWave(u, p) = sparse(ForwardDiff.jacobian(z -> FcatWave(z,p), u))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We now define the U_0 profile","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"uold = vcat(u0, (1 .- u0))\nDuold = zero(uold); applyD_add!(Duold, uold, par_cat,1)\n\n# update problem parameters for front problem\npar_cat_wave = (par_cat..., u0Du0 = dot(uold, Duold), Du0 = Duold, uold = uold)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Let us find the front using newton","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"# we define a problem for solving for the wave\nprobtw = BifurcationProblem(FcatWave, vcat(U0, -1.), par_cat_wave, (@lens _.a);J = JcatWave, record_from_solution = (x,p) -> (s = x[end], nrm = norm(x[1:end-1])),\nplot_solution = (x, p; k...) -> plotsol!(x[1:end-1];k...))\n\nfront = newton(probtw, NewtonPar())\nprintln(\"front speed s = \", front.u[end], \", norm = \", front.u[1:end-1] |> norminf)","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"plotsol(front.u[1:end-1], title=\"front solution\")","category":"page"},{"location":"tutorials/autocatalytic/#Continuation-of-front-solutions","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"Continuation of front solutions","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Following [Malham], the modulated fronts are solutions of the following DAE","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"beginarrayltagDAE\nu_t=a u_x x+scdot u_x-u f(v)\nv_t=v_x x+scdot v_x+u f(v)\n0 = leftlangle U partial_xi U_0\trightrangle\nendarray","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"which can be written with a PDE M_aU_t = G(u) with mass matrix M_a = (Id Id 0). We have already written the vector field of (MF) in the function FcatWave.","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Having found a front U^f, we can continue it as function of the parameter a and detect instabilities. The stability of the front is linked to the eigenelements (lambda V) solution of the generalized eigenvalue problem:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"lambda M_acdot V = dG(U^f)cdot V","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"However BifurcationKit does not provide a generalized eigenvalue solver for now, so we devise one:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"# we need a specific eigensolver\nstruct EigenWave <: BK.AbstractEigenSolver end\n\n# implementation of the solver for the generalized Eigen problem\nfunction (eig::EigenWave)(Jac, nev; k...)\n\tN = size(Jac,1)\n\tB = diagm(vcat(ones(N-1),0))\n\tF = eigen(Array(Jac), B)\n\tI = sortperm(F.values, by = real, rev = true)\n\tnev2 = min(nev, length(I))\n\tJ = findall( abs.(F.values[I]) .< 100000)\n\treturn Complex.(F.values[I[J[1:nev2]]]), Complex.(F.vectors[:, I[J[1:nev2]]]), true, 1\nend\n\noptn = NewtonPar(tol = 1e-8, verbose = true, eigsolver = EigenWave())\nopt_cont_br = ContinuationPar(p_min = 0.05, p_max = 1., newton_options = optn, ds= -0.001, plot_every_step = 2, detect_bifurcation = 3, nev = 10, n_inversion = 6)\n\tbr = continuation(probtw, PALC(), opt_cont_br)\nplot(br)","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts. Let us try to compute them.","category":"page"},{"location":"tutorials/autocatalytic/#Branch-of-modulated-fronts","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"Branch of modulated fronts","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"To branch from the Hopf bifurcation point, we just have to pass the mass matrix as follows:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"# we compute the periodic solutions using Mt time steps and a Trapezoidal time stepper\n# note that we pass the parameter massmatrix which\n# allows to solver the DAE\nMt = 30\nprobTP = PeriodicOrbitTrapProblem(M = Mt ;\n\t\tmassmatrix = spdiagm(0 => vcat(ones(2N),0.)),\n\t\tupdate_section_every_step = 1,\n\t\t# linear solver for the periodic orbit problem\n\t\t# OPTIONAL, one could use the default\n\t\tjacobian = :BorderedLU)\n\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.01, ds= -0.001, p_min = 0.05, max_steps = 130, newton_options = optn, nev = 7, tol_stability = 1e-3, detect_bifurcation = 0, plot_every_step = 1)\n\topts_po_cont = @set opts_po_cont.newton_options.max_iterations = 10\n\topts_po_cont = @set opts_po_cont.newton_options.tol = 1e-6\n\nbr_po = continuation(\n\t# we want to compute the bifurcated branch from\n\t# the first Hopf point\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n\t# this is how we pass the method to compute the periodic\n\tprobTP ;\n\t# OPTIONAL parameters\n\t# we want to jump on the new branch at phopf + δp\n\tδp = 0.0025,\n\t# tangent predictor\n\talg = PALC(tangent = Secant(),\n\t\t\t# linear solver specific to PALC\n\t\t\tbls = BorderingBLS(solver = DefaultLS(), check_precision = false)),\n\t# regular parameters for the continuation\n\t# a few parameters saved during run\n\trecord_from_solution = (u, p) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, u, (@set par_cat_wave.a=p))\n\t\tm = maximum(outt.u[end,:])\n\t\treturn (s = m, period = u[end])\n\tend,\n\t# plotting of a section\n\tplot_solution = (x, p; k...) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, x, (@set par_cat_wave.a=p.p))\n\t\tplot!(outt.t, outt.u[end, :]; label = \"\", subplot=3)\n\t\tplot!(br, subplot=1)\n\tend,\n\t# print the Floquet exponent\n\tfinalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\ttrue\n\tend,\n\tplot = true,\n\tnormC = norminf)\n\nplot(br);plot!(br_po, label = \"modulated fronts\")","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Let us plot one modulated front:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"modfront = BK.get_periodic_orbit(br_po, length(br_po))\nplot(plot(modfront.t, modfront.u[end,:], xlabel = \"t\", ylabel = \"s\", label = \"\"),\n\tcontour(modfront.t, X, modfront.u[1:N,:], color = :viridis, xlabel = \"t\", title = \"u for a = $(round(br_po.sol[length(br_po)].p,digits=4))\", fill = true, ylims=(-10,10)))","category":"page"},{"location":"tutorials/autocatalytic/#References","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"References","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"[Balmforth]: N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"[Malham]: S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"[Beyn]: Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.","category":"page"},{"location":"tutorials/tutorials2b/#sh2dgpu","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Pages = [\"tutorials2b.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Here we give an example where the continuation can be done entirely on the GPU, e.g. on a single V100 NIVDIA.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"info: Why this example?\nThis is not the simplest GPU example because we need a preconditioned linear solver and shift-invert eigen solver for this problem. On the other hand, you will be shown how to set up your own linear/eigen solver.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We choose the 2d Swift-Hohenberg as an example and consider a larger grid. See 2d Swift-Hohenberg equation for more details. Solving the sparse linear problem in v","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"-(I+Delta)^2 v+(l +2nu u-3u^2)v = rhs","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"with a direct solver becomes prohibitive. Looking for an iterative method, the conditioning of the jacobian is not good enough to have fast convergence, mainly because of the Laplacian operator. However, the above problem is equivalent to:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"-v + L cdot (d cdot v) = Lcdot rhs","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"where","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"L = ((I+Delta)^2 + I)^-1","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"is very well conditioned and","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"d = l+1+2nu v-3v^2","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Hence, to solve the previous equation, only a few GMRES iterations are required.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"In effect, the preconditioned PDE is an example of nonlocal problem.","category":"page"},{"location":"tutorials/tutorials2b/#Linear-Algebra-on-the-GPU","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Linear Algebra on the GPU","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We plan to use KrylovKit on the GPU. We define the following types so it is easier to switch to Float32 for example:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"using Revise, CUDA\n\n# this disable slow operations but errors if you use one of them\nCUDA.allowscalar(false)\n\n# type used for the arrays, can be Float32 if GPU requires it\nTY = Float64\n\n# put the AF = Array{TY} instead to make the code on the CPU\nAF = CuArray{TY}","category":"page"},{"location":"tutorials/tutorials2b/#Computing-the-inverse-of-the-differential-operator","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Computing the inverse of the differential operator","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"The issue now is to compute L but this is easy using Fourier transforms.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Hence, that's why we slightly modify the previous Example by considering periodic boundary conditions. Let us now show how to compute L. Although the code looks quite technical, it is based on two facts. First, the Fourier transform symbol associated to L is","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"l_1 = 1+(1-k_x^2-k_y^2)^2","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"which is pre-computed in the composite type SHLinearOp. Then, the effect of L on u is as simple as real.(ifft( l1 .* fft(u) )) and the inverse L\\u is real.(ifft( fft(u) ./ l1 )). However, in order to save memory on the GPU, we use inplace FFTs to reduce temporaries which explains the following code.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"using AbstractFFTs, FFTW, KrylovKit, Setfield, Parameters\nusing BifurcationKit, LinearAlgebra, Plots\nconst BK = BifurcationKit\n\n# the following struct encodes the operator L1\n# Making the linear operator a subtype of BK.AbstractLinearSolver is handy as it will be used\n# in the Newton iterations.\nstruct SHLinearOp{Treal, Tcomp, Tl1, Tplan, Tiplan} <: BK.AbstractLinearSolver\n\ttmp_real::Treal # temporary\n\ttmp_complex::Tcomp # temporary\n\tl1::Tl1\n\tfftplan::Tplan\n\tifftplan::Tiplan\nend\n\n# this is a constructor for the above struct\nfunction SHLinearOp(Nx, lx, Ny, ly; AF = Array{TY})\n\t# AF is a type, it could be CuArray{TY} to run the following on GPU\n\tk1 = vcat(collect(0:Nx/2), collect(Nx/2+1:Nx-1) .- Nx)\n\tk2 = vcat(collect(0:Ny/2), collect(Ny/2+1:Ny-1) .- Ny)\n\td2 = [(1-(pi/lx * kx)^2 - (pi/ly * ky)^2)^2 + 1. for kx in k1, ky in k2]\n\ttmpc = Complex.(AF(zeros(Nx, Ny)))\n\treturn SHLinearOp(AF(zeros(Nx, Ny)), tmpc, AF(d2), plan_fft!(tmpc), plan_ifft!(tmpc))\nend\n\nimport Base: *, \\\n\n# generic function to apply operator op to u\nfunction apply(c::SHLinearOp, u, multiplier, op = *)\n\tc.tmp_complex .= Complex.(u)\n\tc.fftplan * c.tmp_complex\n\tc.tmp_complex .= op.(c.tmp_complex, multiplier)\n\tc.ifftplan * c.tmp_complex\n\tc.tmp_real .= real.(c.tmp_complex)\n\treturn copy(c.tmp_real)\nend\n\n# action of L\n*(c::SHLinearOp, u) = apply(c, u, c.l1)\n\n# inverse of L\n\\(c::SHLinearOp, u) = apply(c, u, c.l1, /)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Before applying a Newton solver, we need to tell how to solve the linear equation arising in the Newton Algorithm.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"# inverse of the jacobian of the PDE\nfunction (sh::SHLinearOp)(J, rhs; shift = 0., tol = 1e-9)\n\tu, l, ν = J\n\tudiag = l .+ 1 .+ 2ν .* u .- 3 .* u.^2 .- shift\n\tres, info = KrylovKit.linsolve( du -> -du .+ sh \\ (udiag .* du), sh \\ rhs,\n\ttol = tol, maxiter = 6)\n\treturn res, true, info.numops\nend","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Now that we have our operator L, we can encode our functional:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"function F_shfft(u, p)\n\t@unpack l, ν, L = p\n\treturn -(L * u) .+ ((l+1) .* u .+ ν .* u.^2 .- u.^3)\nend","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Let us now show how to build our operator L and an initial guess sol0 using the above defined structures.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"using LinearAlgebra, Plots\n\n# to simplify plotting of the solution\nplotsol(x; k...) = heatmap(reshape(Array(x), Nx, Ny)'; color=:viridis, k...)\nplotsol!(x; k...) = heatmap!(reshape(Array(x), Nx, Ny)'; color=:viridis, k...)\nnorminf(x) = maximum(abs.(x))\n\n# norm compatible with CUDA\nnorminf(x) = maximum(abs.(x))\n\nNx = 2^10\nNy = 2^10\nlx = 8pi * 2\nly = 2*2pi/sqrt(3) * 2\n\nX = -lx .+ 2lx/(Nx) * collect(0:Nx-1)\nY = -ly .+ 2ly/(Ny) * collect(0:Ny-1)\n\nsol0 = [(cos(x) .+ cos(x/2) * cos(sqrt(3) * y/2) ) for x in X, y in Y]\n\t\tsol0 .= sol0 .- minimum(vec(sol0))\n\t\tsol0 ./= maximum(vec(sol0))\n\t\tsol0 = sol0 .- 0.25\n\t\tsol0 .*= 1.7\n\nL = SHLinearOp(Nx, lx, Ny, ly, AF = AF)\nJ_shfft(u, p) = (u, p.l, p.ν)\n\n# parameters of the PDE\npar = (l = -0.15, ν = 1.3, L = L)\n\n# Bifurcation Problem\nprob = BK.BifurcationProblem(F_shfft, AF(sol0), par, (@lens _.l) ;\n\tJ = J_shfft,\n\tplot_solution = (x, p;kwargs...) -> plotsol!(x; color=:viridis, kwargs...),\n\trecord_from_solution = (x, p) -> norm(x))","category":"page"},{"location":"tutorials/tutorials2b/#Newton-iterations-and-deflation","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Newton iterations and deflation","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We are now ready to perform Newton iterations:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"opt_new = NewtonPar(verbose = true, tol = 1e-6, max_iterations = 100, linsolver = L)\nsol_hexa = @time newton(prob, opt_new, normN = norminf)\nprintln(\"--> norm(sol) = \", maximum(abs.(sol_hexa.u)))\nplotsol(sol_hexa.u)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"You should see this:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 3.3758e-01 │ 0 │\n│ 1 │ 8.0152e+01 │ 12 │\n│ 2 │ 2.3716e+01 │ 28 │\n│ 3 │ 6.7353e+00 │ 22 │\n│ 4 │ 1.9498e+00 │ 17 │\n│ 5 │ 5.5893e-01 │ 14 │\n│ 6 │ 1.0998e-01 │ 12 │\n│ 7 │ 1.1381e-02 │ 11 │\n│ 8 │ 1.6393e-04 │ 11 │\n│ 9 │ 7.3277e-08 │ 10 │\n└─────────────┴──────────────────────┴────────────────┘\n 0.317790 seconds (42.67 k allocations: 1.256 MiB)\n--> norm(sol) = 1.26017611779702","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Note that this is about the 10x faster than Example 2 but for a problem almost 100x larger! (On a V100 GPU)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"The solution is:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We can also use the deflation technique (see DeflationOperator and DeflatedProblem for more information) on the GPU as follows","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"deflationOp = DeflationOperator(2, dot, 1.0, [sol_hexa.u])\n\nopt_new = @set opt_new.max_iterations = 250\noutdef = @time newton(re_make(prob, u0 = AF(0.4 .* sol_hexa.u .* AF([exp(-1(x+0lx)^2/25) for x in X, y in Y]))),\n\t\tdeflationOp, opt_new, normN = x-> maximum(abs.(x)))\nprintln(\"--> norm(sol) = \", norm(outdef.u))\nplotsol(outdef.u) |> display\nBK.converged(outdef) && push!(deflationOp, outdef.u)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"and get:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2b/#Computation-of-the-branches","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Computation of the branches","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Finally, we can perform continuation of the branches on the GPU:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"opts_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.007, ds= -0.005,\n\tp_max = 0., p_min = -1.0, plot_every_step = 5, detect_bifurcation = 0,\n\tnewton_options = setproperties(opt_new; tol = 1e-6, max_iterations = 15), max_steps = 100)\n\nbr = @time continuation(re_make(prob, u0 = deflationOp[1]),\nPALC(bls = BorderingBLS(solver = L, check_precision = false)),\nopts_cont;\n\tplot = true, verbosity = 3,\n\tnormC = x -> maximum(abs.(x))\n\t)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We did not detail how to compute the eigenvalues on the GPU and detect the bifurcations. It is based on a simple Shift-Invert strategy, please look at examples/SH2d-fronts-cuda.jl.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We have the following information about the branch of hexagons","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"julia> br\nBranch number of points: 67\nBranch of Equilibrium\nBifurcation points:\n (ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`)\n- # 1, nd at p ≈ -0.21522461 ∈ (-0.21528614, -0.21522461), |δp|=6e-05, [converged], δ = ( 3, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3\n- # 2, nd at p ≈ -0.21469007 ∈ (-0.21479652, -0.21469007), |δp|=1e-04, [converged], δ = ( 2, 0), step = 25, eigenelements in eig[ 26], ind_ev = 5\n- # 3, nd at p ≈ -0.21216919 ∈ (-0.21264341, -0.21216919), |δp|=5e-04, [converged], δ = ( 2, 0), step = 27, eigenelements in eig[ 28], ind_ev = 7\n- # 4, nd at p ≈ -0.21052576 ∈ (-0.21110899, -0.21052576), |δp|=6e-04, [converged], δ = ( 2, 0), step = 28, eigenelements in eig[ 29], ind_ev = 9\n- # 5, nd at p ≈ -0.20630678 ∈ (-0.21052576, -0.20630678), |δp|=4e-03, [converged], δ = ( 8, 0), step = 29, eigenelements in eig[ 30], ind_ev = 17\n- # 6, nd at p ≈ -0.19896508 ∈ (-0.19897308, -0.19896508), |δp|=8e-06, [converged], δ = ( 6, 0), step = 30, eigenelements in eig[ 31], ind_ev = 23\n- # 7, nd at p ≈ -0.18621673 ∈ (-0.18748234, -0.18621673), |δp|=1e-03, [converged], δ = ( 2, 0), step = 33, eigenelements in eig[ 34], ind_ev = 25\n- # 8, nd at p ≈ -0.17258147 ∈ (-0.18096574, -0.17258147), |δp|=8e-03, [converged], δ = ( 4, 0), step = 35, eigenelements in eig[ 36], ind_ev = 29\n- # 9, nd at p ≈ -0.14951737 ∈ (-0.15113148, -0.14951737), |δp|=2e-03, [converged], δ = (-4, 0), step = 39, eigenelements in eig[ 40], ind_ev = 29\n- # 10, nd at p ≈ -0.14047758 ∈ (-0.14130979, -0.14047758), |δp|=8e-04, [converged], δ = (-2, 0), step = 41, eigenelements in eig[ 42], ind_ev = 25\n- # 11, nd at p ≈ -0.11304882 ∈ (-0.11315916, -0.11304882), |δp|=1e-04, [converged], δ = (-4, 0), step = 45, eigenelements in eig[ 46], ind_ev = 23\n- # 12, nd at p ≈ -0.09074623 ∈ (-0.09085968, -0.09074623), |δp|=1e-04, [converged], δ = (-6, 0), step = 49, eigenelements in eig[ 50], ind_ev = 19\n- # 13, nd at p ≈ -0.07062574 ∈ (-0.07246519, -0.07062574), |δp|=2e-03, [converged], δ = (-4, 0), step = 52, eigenelements in eig[ 53], ind_ev = 13\n- # 14, nd at p ≈ -0.06235903 ∈ (-0.06238787, -0.06235903), |δp|=3e-05, [converged], δ = (-2, 0), step = 54, eigenelements in eig[ 55], ind_ev = 9\n- # 15, nd at p ≈ -0.05358077 ∈ (-0.05404312, -0.05358077), |δp|=5e-04, [converged], δ = (-2, 0), step = 56, eigenelements in eig[ 57], ind_ev = 7\n- # 16, nd at p ≈ -0.02494422 ∈ (-0.02586444, -0.02494422), |δp|=9e-04, [converged], δ = (-2, 0), step = 60, eigenelements in eig[ 61], ind_ev = 5\n- # 17, nd at p ≈ -0.00484022 ∈ (-0.00665356, -0.00484022), |δp|=2e-03, [converged], δ = (-2, 0), step = 63, eigenelements in eig[ 64], ind_ev = 3\n- # 18, nd at p ≈ +0.00057801 ∈ (-0.00122418, +0.00057801), |δp|=2e-03, [converged], δ = ( 5, 0), step = 64, eigenelements in eig[ 65], ind_ev = 6\n- # 19, nd at p ≈ +0.00320921 ∈ (+0.00141327, +0.00320921), |δp|=2e-03, [converged], δ = (10, 0), step = 65, eigenelements in eig[ 66], ind_ev = 16\nFold points:\n- # 1, fold at p ≈ -0.21528694 ∈ (-0.21528694, -0.21528694), |δp|=-1e+00, [ guess], δ = ( 0, 0), step = 24, eigenelements in eig[ 24], ind_ev = 0","category":"page"},{"location":"abs-from-eq/#From-equilibria-to-equilibria","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"Pages = [\"abs-from-eq.md\"]\nDepth = 2","category":"page"},{"location":"abs-from-eq/#From-simple-branch-point-to-equilibria","page":"From equilibria to equilibria","title":"From simple branch point to equilibria","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"See Branch switching (branch point) for the precise method definition","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"You can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar; kwargs...)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"where br is a branch computed after a call to continuation with detection of bifurcation points enabled. This call computes the branch bifurcating from the ind_bifth bifurcation point in br. An example of use is provided in 2d Bratu–Gelfand problem.","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"See Branch switching (branch point) precise method definition","category":"page"},{"location":"abs-from-eq/#Simple-example","page":"From equilibria to equilibria","title":"Simple example","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"using BifurcationKit, Setfield, Plots\n\n# vector field of transcritical bifurcation\nF(x, p) = [x[1] * (p.μ - x[1])]\n\n# parameters of the vector field\npar = (μ = -0.2, )\n\n# problem (automatic differentiation)\nprob = BifurcationProblem(F, [0.], par, (@lens _.μ); record_from_solution = (x, p) -> x[1])\n\n# compute branch of trivial equilibria (=0) and detect a bifurcation point\nopts_br = ContinuationPar(detect_bifurcation = 3)\nbr = continuation(prob, PALC(), opts_br)\n\t\n# perform branch switching on one side of the bifurcation point\nbr1Top = continuation(br, 1, setproperties(opts_br; max_steps = 14) )\n\n# on the other side\nbr1Bottom = continuation(br, 1, setproperties(opts_br; ds = -opts_br.ds, max_steps = 14))\n\nscene = plot(br, br1Top, br1Bottom; branchlabel = [\"br\", \"br1Top\", \"br1Bottom\"], legend = :topleft)","category":"page"},{"location":"abs-from-eq/#Algorithms","page":"From equilibria to equilibria","title":"Algorithms","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"for the pitchfork bifurcation, the normal form is computed and non-trivial zeros are used to produce guesses for points on the bifurcated branch.","category":"page"},{"location":"abs-from-eq/#abs-simple-eq","page":"From equilibria to equilibria","title":"From non simple branch point to equilibria","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"We provide an automatic branch switching method in this case. The underlying method is to first compute the reduced equation (see Non-simple branch point) and use it to compute the nearby solutions. These solutions are then seeded as initial guess for continuation. Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar;\n\tkwargs...)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"An example of use is provided in 2d Bratu–Gelfand problem.\t","category":"page"},{"location":"linearsolver/#Linear-solvers-(LS)","page":"Linear solvers","title":"Linear solvers (LS)","text":"","category":"section"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"If you provide your own linear solver, it must be a subtype of AbstractLinearSolver otherwise BifurcationKit.jl will not recognize it. See example just below. ","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"The linear solvers provide a way of inverting the Jacobian J or solving J * x = rhs. Such linear solver linsolve will be called like sol, success, itnumber = linsolve(J, rhs; kwargs...) throughout the package.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Here is an example of the simplest one (see src/LinearSolver.jl for the true implementation) to give you an idea, the backslash operator:","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"struct DefaultLS <: AbstractLinearSolver end\n\nfunction (l::DefaultLS)(J, rhs; k...)\n\treturn J \\ rhs, true, 1\nend","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Note that for newton to work, the linear solver must return 3 arguments. The first one is the result, the second one is whether the computation was successful and the third is the number of iterations required to perform the computation.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"You can then call it as follows (and it will be called like this in newton)","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"ls = DefaultLS()\nJ = rand(2, 2) # example of linear operator\nls(J, rand(2))","category":"page"},{"location":"linearsolver/#List-of-implemented-linear-solvers","page":"Linear solvers","title":"List of implemented linear solvers","text":"","category":"section"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Default \\ solver based on LU or Cholesky depending on the type of the Jacobian. This works for sparse matrices as well. You can create one via linsolver = DefaultLS().\nGMRES from IterativeSolvers.jl. You can create one via linsolver = GMRESIterativeSolvers() and pass appropriate options.\nGMRES from KrylovKit.jl. You can create one via linsolver = GMRESKrylovKit() and pass appropriate options.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"tip: Different linear solvers\nBy tuning the options of GMRESKrylovKit, you can select CG, GMRES... see KrylovKit.jl.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"note: Other solvers\nIt is very straightforward to implement the Conjugate Gradients from IterativeSolvers.jl by copying the interface done for gmres. Same goes for minres,... Not needing them, I did not implement this.","category":"page"},{"location":"linearsolver/#Preconditioner","page":"Linear solvers","title":"Preconditioner","text":"","category":"section"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Preconditioners should be considered when using Matrix Free methods such as GMRES. GMRESIterativeSolvers provides a very simple interface for using them. For GMRESKrylovKit, we implemented a left preconditioner. Note that, for GMRESKrylovKit, you are not restricted to use Vectors anymore. Finally, here are some packages to use preconditioners","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"IncompleteLU.jl an ILU like preconditioner\nAlgebraicMultigrid.jl Algebraic Multigrid (AMG) preconditioners. This works especially well for symmetric positive definite matrices.\nPreconditioners.jl A convenient interface to conveniently called most of the above preconditioners using a single syntax.\nWe provide a preconditioner based on deflation of eigenvalues (also called preconditioner based on Leading Invariant Subspaces) using a partial Schur decomposition. There are two ways to define one i.e. PrecPartialSchurKrylovKit and PrecPartialSchurArnoldiMethod. ","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"tip: Using Preconditioners\nApart from setting a preconditioner for a linear solver, it can be advantageous to change the preconditioner during computations, e.g. during a call to continuation or newton. This can be achieved by taking advantage of the callbacks to these methods. See the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS).","category":"page"},{"location":"waveEigen/#Wave-stability","page":"Eigen Solvers","title":"Wave stability","text":"","category":"section"},{"location":"waveEigen/#References","page":"Eigen Solvers","title":"References","text":"","category":"section"},{"location":"waveEigen/","page":"Eigen Solvers","title":"Eigen Solvers","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"waveEigen/","page":"Eigen Solvers","title":"Eigen Solvers","text":"[Sandstede]: Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.","category":"page"},{"location":"FoldContinuationPO/#fold-po","page":"Fold continuation (2 params)","title":"Continuation of Fold of periodic orbits","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"warning: Work in progress\nContinuation of Fold of POs is a recent addition. It has not been thoroughly tested.","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"In this page, we explain how to perform continuation of Fold points and detect the associated codim 2 bifurcations.","category":"page"},{"location":"FoldContinuationPO/#List-of-detected-codim-2-bifurcation-points","page":"Fold continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"Bifurcation symbol used\nCusp cusp\nStrong resonance 1:1 bifurcation R1\nFold / Flip foldFlip\nFold / Neimark-Sacker foldNS","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"FoldContinuationPO/#Fold-continuation","page":"Fold continuation (2 params)","title":"Fold continuation","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"The continuation of Fold bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation) for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.","category":"page"},{"location":"FoldContinuationPO/#Detection-of-codim-2-bifurcation-points","page":"Fold continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the keyword argument detect_codim2_bifurcation in the method continuation ","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"the detection of Cusp (Cusp) is done by the detection of Fold bifurcation points along the curve of Folds by monitoring the parameter component of the tangent.\nthe detection the above bifurcation points is done by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"FoldContinuationPO/#Setting-the-jacobian","page":"Fold continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"In order to apply the newton algorithm to the Fold functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the Fold functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"FoldContinuationPO/#Codim-2-continuation","page":"Fold continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"To compute the codim 2 curve of Fold points of periodic orbits, one can call continuation with the following options","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"FoldContinuationPO/#BifurcationKit.continuation","page":"Fold continuation (2 params)","title":"BifurcationKit.continuation","text":"continuation(br, ind_bif, lens2)\ncontinuation(\n br,\n ind_bif,\n lens2,\n options_cont;\n prob,\n start_with_eigen,\n detect_codim2_bifurcation,\n kwargs...\n)\n\n\nCodimension 2 continuation of Fold / Hopf points. This function turns an initial guess for a Fold / Hopf point into a curve of Fold / Hopf points based on a Minimally Augmented formulation. The arguments are as follows\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\nlens2 second parameter used for the continuation, the first one is the one used to compute br, e.g. getlens(br)\noptions_cont = br.contparams arguments to be passed to the regular continuation\n\nOptional arguments:\n\nbdlinsolver bordered linear solver for the constraint equation\nupdate_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements\ndetect_codim2_bifurcation ∈ {0,1,2} whether to detect Bogdanov-Takens, Bautin and Cusp. If equals 1 non precise detection is used. If equals 2, a bisection method is used to locate the bifurcations.\nkwargs keywords arguments to be passed to the regular continuation\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br you want to refine.\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\ntip: start_with_eigen\nIt is recommended that you use the option start_with_eigen = true\n\n\n\n\n\n","category":"function"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"FoldContinuationPO/#References","page":"Fold continuation (2 params)","title":"References","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#[Lorenz-84-model,-take-2](@id-lorenz98-take2)","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"Pages = [\"lorenz84-PO.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"In this tutorial, we study the extended Lorenz-84 model which is also treated in MatCont [Kuznetsov]. We use this model to showcase the automatic branch switching procedure to","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"Fold of periodic orbits from Bautin bifurcation point\nNS of periodic orbits from ZH bifurcation point\nNS of periodic orbits from HH bifurcation point.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"As this model has been studied in this tutorial, we do not give much details and refer to the corresponding tutorial to get the 2 parameters curves of Hopf / Fold bifurcations. ","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"The model is as follows","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"leftbeginarrayl\ndotX=-Y^2-Z^2-alpha X+alpha F-gamma U^2 \ndotY=X Y-beta X Z-Y+G \ndotZ=beta X Y+X Z-Z \ndotU=-delta U+gamma U X+T\nendarrayrighttagE","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"We recall the problem setting:","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"using Revise, ForwardDiff, Parameters, Plots, LinearAlgebra\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# vector field\nfunction Lor(u, p, t = 0)\n\t@unpack α,β,γ,δ,G,F,T = p\n\tX,Y,Z,U = u\n\t[\n\t\t-Y^2 - Z^2 - α*X + α*F - γ*U^2,\n\t\tX*Y - β*X*Z - Y + G,\n\t\tβ*X*Y + X*Z - Z,\n\t\t-δ*U + γ*U*X + T\n\t]\nend\n\nparlor = (α = 1//4, β = 1., G = .25, δ = 1.04, γ = 0.987, F = 1.7620532879639, T = .0001265)\n\nz0 = [2.9787004394953343, -0.03868302503393752, 0.058232737694740085, -0.02105288273117459]\n\nrecordFromSolutionLor(x, p) = (u = BK.getVec(x);(X = u[1], Y = u[2], Z = u[3], U = u[4]))\nprob = BK.BifurcationProblem(Lor, z0, parlor, (@lens _.F);\n\trecord_from_solution = (x, p) -> (X = x[1], Y = x[2], Z = x[3], U = x[4]),)\n\nopts_br = ContinuationPar(p_min = -1.5, p_max = 3.0, ds = 0.002, dsmax = 0.05, n_inversion = 6, detect_bifurcation = 3, max_bisection_steps = 25, nev = 4, max_steps = 200, plot_every_step = 30)\n\t@set! opts_br.newton_options.verbose = false\n\t@set! opts_br.newton_options.tol = 1e-12\n\tbr = @time continuation(re_make(prob, params = setproperties(parlor;T=0.04,F=3.)),\n\t \tPALC(), opts_br;\n\t\tnormC = norminf, bothside = true)\n\nscene = plot(br, plotfold=false, markersize=4, legend=:topleft)","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#Two-parameters-curves-of-Fold-/-Hopf-bifurcation","page":"🟠 Lorenz-84 model, take 2","title":"Two parameters curves of Fold / Hopf bifurcation","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"We follow the Fold points in the parameter plane (TF). We tell the solver to consider br.specialpoint[5] and continue it.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"sn_codim2 = continuation(br, 5, (@lens _.T), ContinuationPar(opts_br, p_max = 3.2, p_min = -0.1, detect_bifurcation = 1, dsmin=1e-5, ds = -0.001, dsmax = 0.005, n_inversion = 10, save_sol_every_step = 1, max_steps = 130, max_bisection_steps = 55) ; plot = true,\n\tverbosity = 0,\n\tnormC = norminf,\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = false,\n\tbothside = false,\n\t)\n\nhp_codim2_1 = continuation(br, 3, (@lens _.T), ContinuationPar(opts_br, ds = -0.001, dsmax = 0.02, dsmin = 1e-4, n_inversion = 8, save_sol_every_step = 1, detect_bifurcation = 1) ; plot = false, verbosity = 0,\n\tnormC = norminf,\n\t# tangentAlgo = BorderedPred(),\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = true,\n\tbothside = true,\n\t)\n\nplot(sn_codim2, vars=(:F, :T), branchlabel = \"SN\")\nplot!(hp_codim2_1, vars=(:F, :T), branchlabel = \"Hopf1\", xlims = (1,2.7), ylims = (-0.06,0.06))","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#Fold-bifurcations-of-periodic-orbits-from-Bautin-bifurcation","page":"🟠 Lorenz-84 model, take 2","title":"Fold bifurcations of periodic orbits from Bautin bifurcation","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"We compute the branch of Fold of periodic orbits from the Bautin bifurcation (labelled :gh) in the previous figure. In this tutorial, we focus on orthogonal collocation but standard shooting would do too.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"opts_fold_po = ContinuationPar(hp_codim2_1.contparams, dsmax = 0.01, detect_bifurcation = 0, max_steps = 30, detect_event = 0, ds = 0.001, plot_every_step = 10, a = 0.8)\n@set! opts_fold_po.newton_options.verbose = false\n@set! opts_fold_po.newton_options.tol = 1e-8\nfold_po = continuation(hp_codim2_1, 3, opts_fold_po, \n\t\tPeriodicOrbitOCollProblem(20, 3, meshadapt = false);\n\t\tnormC = norminf,\n\t\tδp = 0.02,\n\t\tupdate_minaug_every_step = 0,\n\t\tjacobian_ma = :minaug,\n\t\tverbosity = 0, plot = false,\n\t)\nplot!(fold_po, vars=(:F, :T), branchlabel = \"Fold-PO\")","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#NS-bifurcations-of-periodic-orbits-from-Hopf-Hopf-bifurcation","page":"🟠 Lorenz-84 model, take 2","title":"NS bifurcations of periodic orbits from Hopf-Hopf bifurcation","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"When we computed the curve of Hopf points, we detected a Hopf-Hopf bifurcation. We can branch from it to get the curve of NS points. This is done as follows:","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"opts_ns_po = ContinuationPar(hp_codim2_1.contparams, dsmax = 0.02, detect_bifurcation = 1, max_steps = 20, ds = -0.001, detect_event = 0)\n@set! opts_ns_po.newton_options.verbose = false\n@set! opts_ns_po.newton_options.tol = 1e-9\n@set! opts_ns_po.newton_options.max_iterations = 10\nns_po1 = continuation(hp_codim2_1, 4, opts_ns_po, \n\t\tPeriodicOrbitOCollProblem(20, 3, update_section_every_step = 1);\n\t\tdetect_codim2_bifurcation = 0,\n\t\tnormC = norminf,\n\t\tδp = 0.02,\n\t\tupdate_minaug_every_step = 1,\n\t\t# which of the 2 NS curves should we compute?\n\t\twhichns = 1,\n\t\tjacobian_ma = :minaug,\n\t\tverbosity = 3,\n\t\t)\nplot!(ns_po1, vars=(:F, :T), branchlabel = \"NS1\")","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"ns_po2 = continuation(hp_codim2_1, 4, opts_ns_po, \n\t\tPeriodicOrbitOCollProblem(30, 3, update_section_every_step = 1);\n\t\tdetect_codim2_bifurcation = 0,\n\t\tnormC = norminf,\n\t\tδp = 0.02,\n\t\tupdate_minaug_every_step = 1,\n\t\t# which of the 2 NS curves should we compute?\n\t\twhichns = 2,\n\t\tjacobian_ma = :minaug,\n\t\t)\nplot!(ns_po2, vars=(:F, :T), branchlabel = \"NS2\")","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#References","page":"🟠 Lorenz-84 model, take 2","title":"References","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"[Kuznetsov]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.","category":"page"},{"location":"ModulatedTW/#Modulated-travelling-wave-(MTW),-N_g1","page":"Modulated Travelling waves","title":"Modulated travelling wave (MTW), N_g=1","text":"","category":"section"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"warning: \nThis is work in progress","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"A modulated travelling wave with period T satisfies q(xt+T) = q(x-s Tt). Equivalently, using a moving frame to freeze the wave xi=x-st, it holds that tilde q(xit+T) = tilde q(xit) where tilde q(xit)=q(xi+stt). Hence, tilde q is a periodic solution to","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"partial_ttilde q = -sTcdottilde q+F(tilde qp)tageqMWP","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"Stability of the MTW is determined by the spectrum of the linearized time-T map associated with (eqMWP). ","category":"page"},{"location":"ModulatedTW/#References","page":"Modulated Travelling waves","title":"References","text":"","category":"section"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"[Sandstede]: Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.","category":"page"},{"location":"plotting/#Plotting","page":"Plot functions","title":"Plotting","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Pages = [\"plotting.md\"]\nDepth = 3","category":"page"},{"location":"plotting/#Standard-plots-using-the-plot-recipe-from-Plots.jl","page":"Plot functions","title":"Standard plots using the plot recipe from Plots.jl","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Plotting is provided by calling recipes to Plots.jl. It means that to plot a branch br, you just need to call","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"#]add Plots # You need to install Plots.jl before your first time using it!\nusing Plots\nplot(br)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"where br is a branch computed after a call to br = continuation(...). Plots can be customized using all the keyword arguments provided by Plots.jl. For example, we can change the plotting backend to the GR package and put a title on the plot by doing:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"gr()\nplot!(br, title = \"I have a branch!\")","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"or you can use a scatter plot","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"scatter(br)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Then to save the plot, use savefig, for example:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"savefig(\"myplot.png\")","category":"page"},{"location":"plotting/#Specific-plotting-keyword-arguments","page":"Plot functions","title":"Specific plotting keyword arguments","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The available arguments specific to our plotting methods are","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plotfold = true: plot the fold points with black dots\nputspecialptlegend = true: display the legend corresponding to the bifurcation points\nvars = nothing: see below\nplotstability = true: display the stability of the branch\nplotspecialpoints = true: plot the special (bifurcation) points on the branch\nbranchlabel = \"fold branch\": assign label to a branch which is printed in the legend\nlinewidthunstable: set the linewidth for the unstable part of the branch\nlinewidthstable: set the linewidth for the stable part of the branch\nplotcirclesbif = false use circles to plot bifurcation points\napplytoX = identity apply transformation applytoX to x-axis\napplytoY = identity apply transformation applytoY to y-axis","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"If you have several branches br1, br2, you can plot them in the same figure by doing","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br1, br2)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"in place of","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br1)\nplot!(br2)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"warn: Plot of bifurcation points\nThe bifurcation points for which the bisection was successful are indicated with circles and with squares otherwise.","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Note that the plot recipes use the parameter axis as xlabel, and the passed variable as ylabel.","category":"page"},{"location":"plotting/#Choosing-Variables","page":"Plot functions","title":"Choosing Variables","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"You can select which variables to plot using the keyword argument vars, for example:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br, vars = (:param, :x))","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The available symbols are :x, :param, :itnewton, :itlinear, :ds, :θ, :n_unstable, :n_imag, :stable, :step,... and:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"x if record_from_solution (see continuation) returns a Number.\nx1, x2,... if record_from_solution returns a Tuple.\nthe keys of the NamedTuple returned by record_from_solution.","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The available symbols are provided by calling propertynames(br.branch).","category":"page"},{"location":"plotting/#Plotting-bifurcation-diagrams","page":"Plot functions","title":"Plotting bifurcation diagrams","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"To do this, you just need to call","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(diagram)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"where diagram is a branch computed after a call to diagram = bifurcationdiagram(...). You can use the keywords provided by Plots.jl and the different backends. You can thus call scatter(diagram). In addition to the options for plotting branches (see above), there are specific arguments available for bifurcation diagrams","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"code specify the part of the bifurcation diagram to plot. For example code = (1,1,) plots the part after the first branch of the first branch of the root branch.\nlevel = (-Inf, Inf) restrict the branching level for plotting.","category":"page"},{"location":"plotting/#Plotting-without-the-plot-recipe","page":"Plot functions","title":"Plotting without the plot recipe","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"What if you don't want to use Plots.jl? You can define your own plotting functions using the internal fields of br which is of type ContResult. For example, in PyPlot, Gadfly, GR, etc., you can do the following to plot the branch (like the plot recipe plot(br, vars = (:param, :x))):","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br.branch.param, br.branch.x)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"You can also have access to the stability of the points by using br.stable. More information concerning the fields can be found in ContResult. For example, you can change the color depending on the stability:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"col = [stb ? :green : :red for stb in br.stable]\nplot(br.param, br.x, color=col)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"You can also plot the spectrum at a specific continuation step::Int by calling","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"# get the eigenvalues\neigvals = br.eig[step].eigenvals\n\n# plot them in the complex plane\nscatter(real.(eigvals), imag.(eigvals))","category":"page"},{"location":"plotting/#Standard-plots-using-the-Makie.jl-[Experimental]","page":"Plot functions","title":"Standard plots using the Makie.jl [Experimental]","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Plotting is also provided by calling recipes to Makie.jl. It means that to plot a branch br, you just need to call","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"#]add GLMakie # You need to install GLMakie.jl before your first time using it!\nusing GLMakie\nBifurcationKit.plot(br)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The keyword arguments to BifurcationKit.plot are the same as decribed above in the page. You can also combine diagrams with BifurcationKit.plot(br1, br2) or use BifurcationKit.plot!(ax, br) to add a branch to an existing plot.","category":"page"},{"location":"plotting/#Example","page":"Plot functions","title":"Example","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"using Revise, GLMakie, BifurcationKit\nMakie.inline!(true)\nq = 1/0\nk = 2\nF(x, p) = (@. p + x - x^(k+1)/(k+1))\nprob = BifurcationProblem(F, [0.8], 1., (@lens _); record_from_solution = (x,p) -> x[1])\nopts = ContinuationPar(dsmax = 0.1, dsmin = 1e-3, ds = -0.001, p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(), opts)\nBifurcationKit.plot(br)","category":"page"},{"location":"pd/#Period-doubling-point","page":"Period-doubling","title":"Period-doubling point","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"Pages = [\"pd.md\"]\nDepth = 2","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"At a period-doubling (PD) bifurcation of a periodic orbit gamma (with period T) for parameter value p_0 for the Cauchy problem ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"fracdudt=F(up)tagE","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"the eigenvalues (Floquet coefficients) of the monodromy operator mathcal M=Y(T) solution to","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"fracdYdt=A(t)Y(t) Y(0)=I_n","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"contain the simple eigenvalue mu=-1.","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"There are two ways to compute the normal form of this bifurcation","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"using the Poincaré return map [Kuznetsov]\nusing the method of [Iooss] see also [Kuz2]","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"You can obtain the normal form of a PD bifurcation using ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"pd = get_normal_form(br, ind; prm = false)","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where prm indicates whether you want to use the method based on Poincaré return map (PRM) or the one based on Iooss method.","category":"page"},{"location":"pd/#Normal-form-based-on-Poincaré-return-map","page":"Period-doubling","title":"Normal form based on Poincaré return map","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"Given a transversal section Sigma to gamma at gamma(0), the Poincaré return map mathcal P associates to each point xinSigma close to gamma(0) the first point mathcal P(xp)inSigma where the orbit of (E) with initial condition x intersects again Sigma at mathcal P(xp). Hence, the discrete map x_n+1=mathcal P(x_np) has normal form","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"x_n+1 = -x_n+cx_n^3+","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where [Kuz2]","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"c =frac16leftlangle p^* mathcalC(p p p)+3 mathcalBleft(pleft(I_n-1-mathcalAright)^-1 mathcalB(p p)right)rightrangle","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where mathcal C=d^3mathcal P(gamma(0)), mathcal B = d^2mathcal P(gamma(0)) and mathcal A = dmathcal P(gamma(0)). Also:","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"mathcalA p=-p mathcalA^mathrmT p^*=-p^*","category":"page"},{"location":"pd/#Normal-form-based-on-Iooss-method","page":"Period-doubling","title":"Normal form based on Iooss method","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"This is based on [Iooss],[Kuz2]. Suppose that the T periodic orbit gamma(tau) has a Period-Doubling bifurcation for a parameter value p_0. Locally, the orbits can be represented by ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"x(tau) = gamma(tau)+Q_0(tau)xi+Phi(tau xi)","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"leftbeginarrayl\nfracd taud t=1+a_0cdot(p-p_0)+a xi^2+cdots \nfracd xid tau=c_0cdot(p-p_0)xi+c xi^3+cdots\nendarrayright","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"with center manifold correction Phi(tau xi) being 2T periodic in tau and Q_0(tau) is the Floquet operator.","category":"page"},{"location":"pd/#References","page":"Period-doubling","title":"References","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"[Kuznetsov]: Yu. A. Kuznetsov, \"Elements of Applied Bifurcation Theory\", 2nd ed., 1998.","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"[Kuz2]: Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"[Iooss]: Iooss, \"Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.\", 1988","category":"page"},{"location":"MooreSpence/#Moore-Penrose-continuation","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"warning: WIP\nThis is work in progress. The interface will be improved in the future.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"This is one of the various continuation methods implemented in BifurcationKit.jl. It is set by the option alg = MoorePenrose() in continuation. See also MoorePenrose for more information.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"For solving","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"mathbb R^nni F(xp) = 0 quadtagE","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"using a Newton algorithm, we miss an equation. Hence, we proceed as follows [Meijer]. Starting from a predictor (x_1p_1), we look for the solution to (E) that is closest to (x_1p_1). Hence, we optimise","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"min_(xp) (xp)-(x_1p_1) text such that F(xp)=0 tagMS","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"It can be interpreted as a PALC in which the hyperplane is adapted at every step. ","category":"page"},{"location":"MooreSpence/#Predictor","page":"Moore-Penrose continuation","title":"Predictor","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"The possible predictors tangent::AbstractTangentPredictor are listed in Predictors - Correctors. They can be used to create a Moore-Penrose algorithm like MoorePenrose(tangent = PALC())","category":"page"},{"location":"MooreSpence/#Corrector","page":"Moore-Penrose continuation","title":"Corrector","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"The corrector is the Gauss Newton algorithm applied to (MS).","category":"page"},{"location":"MooreSpence/#Linear-Algebra","page":"Moore-Penrose continuation","title":"Linear Algebra","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"Let us discuss more about the norm and dot product. First, the option normC continuation specifies the norm used to evaluate the distance in (MS). The dot product (resp. norm) used in the (iterative) linear solvers is LinearAlgebra.dot (resp. LinearAlgebra.norm). It can be changed by importing these functions and redefining it. Note that by default, the L^2 norm is used.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"The linear solver for the linear problem associated to (MS) is set by the option linearAlgo in continuation: it is one of Bordered linear solvers (BLS).","category":"page"},{"location":"MooreSpence/#Algorithm-for-solving-(MS)","page":"Moore-Penrose continuation","title":"Algorithm for solving (MS)","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"Let us write yequiv(xp)inmathbb R^N+1. In order to solve for the argmin, we apply the newton algorithm with jacobian belonging to mathbb R^Ntimes (N+1):","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"y^k+1 = y^k -d_yF(y^k)^+F(y^k)","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"where the superscript ^+ indicates the Moore-Penrose pseudoinverse of rank N.","category":"page"},{"location":"MooreSpence/#Direct-case","page":"Moore-Penrose continuation","title":"Direct case","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"In this case, triggered by the option MoorePenrose(method = BifurcationKit.direct), the pseudoinverse is computed with \\.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"the option MoorePenrose(method = BifurcationKit.pInv), the pseudoinverse is computed with pinv.","category":"page"},{"location":"MooreSpence/#Iterative-case","page":"Moore-Penrose continuation","title":"Iterative case","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"In this case, triggered by the option MoorePenrose(method = BifurcationKit.iterative), the pseudoinverse is computed with an iterative method described in [Meijer]:","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"leftbeginarrayl\ny_1^j+1=y_1^j-left(beginarrayc\nF_yleft(y_1^jright) \nleft(phi_1^jright)^top\nendarrayright)^-1left(beginarrayc\nFleft(y_1^jright) \n0\nendarrayright) \nphi_1^j+1=left(beginarrayc\nF_yleft(y_1^j+1right) \nleft(phi_1^jright)^top\nendarrayright)^-1left(beginarrayl\n0 \n1\nendarrayright) quad j=012 ldots\nendarrayright","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"We initialise phi_1^0 with the tangent.","category":"page"},{"location":"MooreSpence/#Step-size-control","page":"Moore-Penrose continuation","title":"Step size control","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"Each time the corrector fails, the step size ds is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.","category":"page"},{"location":"MooreSpence/#References","page":"Moore-Penrose continuation","title":"References","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"[Meijer]: Meijer, Dercole, and Oldeman, “Numerical Bifurcation Analysis.”","category":"page"}] +[{"location":"bt/#Normal-form-of-the-Bogdanov-Takens-bifurcation","page":"Bogdanov-Takens","title":"Normal form of the Bogdanov-Takens bifurcation","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We follow the book[Haragus] and consider a Cauchy problem","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"dot x=mathbf F(xp)","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"mathbfL zeta_0=0 quad mathbfL zeta_1=zeta_0","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We can also select a basis:","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"mathbfL^* zeta_1^*=0 quad mathbfL^* zeta_0^*=zeta_1^*","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"such that","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"leftlanglezeta_0 zeta_0^*rightrangle=1 quadleftlanglezeta_1 zeta_0^*rightrangle=0 quadleftlanglezeta_0 zeta_1^*rightrangle=0 quadleftlanglezeta_1 zeta_1^*rightrangle=1","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"Under some conditions, x(t)approx x_0+A(t)zeta_0 + B(t)zeta_1 where AB satisfy the normal form:","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\nfracd Ad t=B \nfracd Bd t=alpha_1(mu)+alpha_2(mu) A+alpha_3(mu) B+b A B+a A^2widetilderho(A B mu)\nendalignedtagE","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"where p = p_0+mu and with coefficients","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\na=leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_1^*rightrangle \nb=leftlangle 2 mathbfF_20left(zeta_0 zeta_1right)-2 Psi_200 zeta_1^*rightrangle\nendaligned","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"The Psis satisfy","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\na zeta_1 =mathbfL Psi_200+mathbfF_20left(zeta_0 zeta_0right) \nb zeta_1+2 Psi_200 =mathbfL Psi_110+2 mathbfF_20left(zeta_0 zeta_1right) \nPsi_110 =mathbfL Psi_020+mathbfF_20left(zeta_1 zeta_1right)\nendaligned","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"which gives","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"0=leftlanglePsi_200 zeta_1^*rightrangle + leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_0^*rightrangle","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"We conclude that","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"beginaligned\na=leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_1^*rightrangle \nb=2leftlangle mathbfF_20left(zeta_0 zeta_1right) zeta_1^*rightrangle + 2leftlanglemathbfF_20left(zeta_0 zeta_0right) zeta_0^*rightrangle\nendaligned","category":"page"},{"location":"bt/#Computation-of-the-basis","page":"Bogdanov-Takens","title":"Computation of the basis","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"To build the basis leftzeta_0 zeta_1right, we follow the procedure described in [AlHdaibat] on page 972.","category":"page"},{"location":"bt/#Computation-of-the-parameter-transform","page":"Bogdanov-Takens","title":"Computation of the parameter transform","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"To invert the mapping muto (alpha_1(mu)alpha_2(mu)alpha_3(mu)), we follow the procedure described in [AlHdaibat] on page 956 forward.","category":"page"},{"location":"bt/#Normal-form-computation","page":"Bogdanov-Takens","title":"Normal form computation","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"get_normal_form(br::ContResult, ind_bif::Int ;\n\tnev = 5, verbose = false, ζs = nothing, autodiff = true, detailed = true)","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The option detailed controls the computation of a simplified version of the normal form. autodiff controls the use of ForwardDiff during the normal form computation.","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BogdanovTakens.","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"bt/#References","page":"Bogdanov-Takens","title":"References","text":"","category":"section"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"[Haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"bt/","page":"Bogdanov-Takens","title":"Bogdanov-Takens","text":"[AlHdaibat]: Al-Hdaibat, B., W. Govaerts, Yu. A. Kuznetsov, and H. G. E. Meijer. “Initialization of Homoclinic Solutions near Bogdanov–Takens Points: Lindstedt–Poincaré Compared with Regular Perturbation Method.” SIAM Journal on Applied Dynamical Systems 15, no. 2 (January 2016): 952–80. https://doi.org/10.1137/15M1017491.","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/#Neural-mass-equation","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"The following model is taken from [Cortes]:","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"leftbeginarrayl\ntau dotE=-E+gleft(J u x E+E_0right) \ndotx=tau_D^-1(1-x)-u E x \ndotu=U E(1-u)-tau_F^-1(u-U)\nendarrayright","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"We use this model as a mean to introduce the basics of BifurcationKit.jl, namely the continuation of equilibria.","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# vector field\nfunction TMvf(z, p)\n\t@unpack J, α, E0, τ, τD, τF, U0 = p\n\tE, x, u = z\n\tSS0 = J * u * x * E + E0\n\tSS1 = α * log(1 + exp(SS0 / α))\n\t[\n\t (-E + SS1) / τ,\n (1.0 - x) / τD - u * x * E,\n\t (U0 - u) / τF + U0 * (1.0 - u) * E\n\t]\nend\n\n# parameter values\npar_tm = (α = 1.5, τ = 0.013, J = 3.07, E0 = -2.0, τD = 0.200, U0 = 0.3, τF = 1.5, τS = 0.007)\n\n# initial condition\nz0 = [0.238616, 0.982747, 0.367876]\n\n# Bifurcation Problem\nprob = BifurcationProblem(TMvf, z0, par_tm, (@lens _.E0);\n\trecord_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]),)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"We first compute the branch of equilibria ","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"# continuation options, we limit the parameter range for E0\nopts_br = ContinuationPar(p_min = -4.0, p_max = -0.9)\n\n# continuation of equilibria\nbr = continuation(prob, PALC(), opts_br;\n\t# we want to compute both sides of the branch of the initial\n\t# value of E0 = -2\n\tbothside = true)\n\nscene = plot(br, legend=:topleft)","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"br","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"If you don't want to compute just the branch without the bifurcations (more information is provided here ), change the continuation options to","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"opts_br = ContinuationPar(p_min = -4.0, p_max = -0.9,\n\tdetect_bifurcation = 0)\n\t\n# continuation of equilibria\nbr = continuation(prob, PALC(), opts_br;\n\t# we want to compute both sides of the branch of the initial\n\t# value of E0 = -2\n\tbothside = true)\n\nscene = plot(br, plotfold=true)","category":"page"},{"location":"tutorials/ode/tutorialsBasic1/#References","page":"🟢 Neural mass equation","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialsBasic1/","page":"🟢 Neural mass equation","title":"🟢 Neural mass equation","text":"[Cortes]: Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.","category":"page"},{"location":"tutorials/BrusselatorFF/#Brusselator-1d-with-periodic-BC-using-FourierFlows.jl","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"Pages = [\"BrusselatorFF.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"info: Acknowledgment\nThe example was done in collaboration with Navid C. Constantinou. ","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We look at the Brusselator in 1d, see [Tzou]. The equations are","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"beginaligned frac partial u partial t = D frac partial ^ 2 u partial z ^ 2 + u ^ 2 v - ( B + 1 ) u + E frac partial v partial t = frac partial ^ 2 v partial z ^ 2 + B u - u ^ 2 v endalignedtagE","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"with periodic boundary conditions. These equations have been introduced to reproduce an oscillating chemical reaction.","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We focus on computing a snaking branch of periodic orbits using spectral methods implemented in Brusselator.jl:","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"using Revise, BifurcationKit\nusing Brusselator, Plots, Parameters, ForwardDiff, LinearAlgebra, Setfield, DiffEqBase\nusing FFTW: irfft\nconst BK = BifurcationKit\n\ndev = CPU()\t\t\t\t\t# Device (CPU/GPU)\n\nnx = 512\t\t\t\t# grid resolution\nstepper = \"FilteredRK4\"\t\t# timestepper\ndt \t= 0.01\t\t# timestep\nnsteps = 9000\t\t# total number of time-steps\nnsubs\t= 20\t\t# number of time-steps for intermediate logging/plotting (nsteps must be multiple of nsubs)\n\n# parameters for the model used by Tzou et al. (2013)\nE = 1.4\nL = 137.37\t\t\t\t # Domain length\nε = 0.1\nμ = 25\nρ = 0.178\n\nD_c = ((sqrt(1 + E^2) - 1) / E)^2\nB_H = (1 + E * sqrt(D_c))^2\n\nB = B_H + ε^2 * μ\nD = D_c + ε^2 * ρ\n\nkc = sqrt(E / sqrt(D))\n\n# building the model\ngrid = OneDGrid(dev, nx, L)\nparams = Brusselator.Params(B, D, E)\nvars = Brusselator.Vars(dev, grid)\nequation = Brusselator.Equation(dev, params, grid)\nprob = FourierFlows.Problem(equation, stepper, dt, grid, vars, params, dev)\n\nget_u(prob) = irfft(prob.sol[:, 1], prob.grid.nx)\nget_v(prob) = irfft(prob.sol[:, 2], prob.grid.nx)\nu_solution = Diagnostic(get_u, prob; nsteps=nsteps+1)\ndiags = [u_solution]","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We now integrate the model to find a periodic orbit:","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"l = 28\nθ = @. (grid.x > -l/2) & (grid.x < l/2)\n\nau, av = -(E^2 + kc^2) / B, -1\ncu, cv = -E * (E + im) / B, 1\n\n# initial condition\nu0 = @.\t E + ε * real( au * exp(im * kc * grid.x) * θ + cu * (1 - θ) )\nv0 = @. B/E + ε * real( av * exp(im * kc * grid.x) * θ + cv * (1 - θ) )\nset_uv!(prob, u0, v0)\n\nplot_output(prob)\n\n# move forward in time to capture the periodic orbit\nfor j=0:Int(nsteps/nsubs)\n\tupdatevars!(prob)\n\tstepforward!(prob, diags, nsubs)\nend\n\n# estimate of the periodic orbit, will be used as initial condition for a Krylov-Newton\ninitpo = copy(vcat(vcat(prob.vars.u, prob.vars.v), 4.9))\n\nusing RecursiveArrayTools\n\nt = u_solution.t[1:10:nsteps]\nU_xt = reduce(hcat, [ u_solution.data[j] for j=1:10:nsteps ])\nheatmap(grid.x, t, U_xt', c = :viridis, clims = (1, 3))","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"which gives","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"(Image: )","category":"page"},{"location":"tutorials/BrusselatorFF/#Building-the-Shooting-problem","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"Building the Shooting problem","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We compute the periodic solution of (E) with a shooting algorithm. We thus define a function to compute the flow and its differential.","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# update the states\nfunction _update!(out, pb::FourierFlows.Problem, N)\n\tout[1:N] .= pb.vars.u\n\tout[N+1:end] .= pb.vars.v\n\tout\nend\n\n# update the parameters in pb\nfunction _setD!(D, pb::FourierFlows.Problem)\n\tpb.eqn.L[:, 1] .*= D / prob.params.D\n\tpb.params.D = D\nend\n\n# compute the flow from x up to time t\nfunction ϕ(x, p, t)\n\t@unpack pb, D, N = p\n\t_setD!(D, pb)\n\n\t# set initial condition\n\t@views set_uv!(pb, x[1:N], x[N+1:2N])\n\tpb.clock.t=0.; pb.clock.step=0\n\t# determine number of time steps\n\tdt = pb.clock.dt\n\tnsteps = div(t, dt) |> Int\n\t# compute flow\n\tstepforward!(pb, nsteps)\n\n\trest = t - nsteps * dt\n\tdt = pb.clock.dt\n\tpb.clock.dt = rest\n\tstepforward!(pb, 1)\n\tpb.clock.dt = dt\n\tupdatevars!(pb)\n\tout = similar(x)\n\t_update!(out, pb, N)\n\treturn (t=t, u=out)\nend\n\n# differential of the flow by FD\nfunction dϕ(x, p, dx, t; δ = 1e-8)\n\tphi = ϕ(x, p, t).u\n\tdphi = (ϕ(x .+ δ .* dx, p, t).u .- phi) ./ δ\n\treturn (t=t, u=phi, du=dphi)\nend","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We also need the vector field","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"function vf(x, p)\n\t@unpack pb, D, N = p\n\t# set parameter in prob\n\tpb.eqn.L[:, 1] .*= D / pb.params.D\n\tpb.params.D = D\n\tu = @view x[1:N]\n\tv = @view x[N+1:end]\n\t# set initial condition\n\tset_uv!(pb, u, v)\n\trhs = Brusselator.get_righthandside(pb)\n\t# rhs is in Fourier space, put back to real space\n\tout = similar(x)\n\tldiv!((@view out[1:N]), pb.grid.rfftplan, rhs[:, 1])\n\tldiv!((@view out[N+1:end]), pb.grid.rfftplan, rhs[:, 2])\n\treturn out\nend","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"We then specify the shooting problem","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# parameters to be passed to ϕ\npar_bru = (pb = prob, N = nx, nsubs = nsubs, D = D)\n\n# example of vector passed to ϕ\nx0 = vcat(u0,v0)\n\n# here we define the problem which encodes the standard shooting\nflow = Flow(vf, ϕ, dϕ)\n\n# the first section is centered around a stationary state\n_center = vcat(E*ones(nx), B/E*ones(nx))\n\n# section for the flow\nsectionBru = BK.SectionSS(vf(initpo[1:end-1], par_bru), _center)\nprobSh = ShootingProblem(M = 1, flow = flow, ds = diff(LinRange(0, 1, 1 + 1)), section = sectionBru, par = par_bru, lens = (@lens _.D), jacobian = :FiniteDifferences)","category":"page"},{"location":"tutorials/BrusselatorFF/#Finding-a-periodic-orbit","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"Finding a periodic orbit","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# linear solver for the Shooting problem\nls = GMRESIterativeSolvers(N = 2nx+1, reltol = 1e-4)\n\n# parameters for Krylov-Newton\noptn = NewtonPar(tol = 1e-9, verbose = true,\n\t# linear solver\n\tlinsolver = ls,\n\t# eigen solver\n\teigsolver = EigKrylovKit(dim = 30, x₀ = rand(2nx), verbose = 1 )\n\t)\n\n# Newton-Krylov method to check convergence and tune parameters\nsolp = @time newton(probSh, initpo, optn,\n\tnormN = x->norm(x,Inf))","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"and you should see (the guess was not that good)","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.6216e+03 │ 0 │\n│ 1 │ 4.4376e+01 │ 6 │\n│ 2 │ 9.0109e-01 │ 15 │\n│ 3 │ 4.9044e-02 │ 32 │\n│ 4 │ 4.1139e-03 │ 27 │\n│ 5 │ 6.0704e-03 │ 33 │\n│ 6 │ 2.4721e-04 │ 33 │\n│ 7 │ 3.7889e-05 │ 34 │\n│ 8 │ 6.6836e-07 │ 31 │\n│ 9 │ 2.0295e-09 │ 39 │\n│ 10 │ 2.1685e-12 │ 41 │\n└─────────────┴──────────────────────┴────────────────┘\n 83.615047 seconds (284.31 M allocations: 24.250 GiB, 6.28% gc time)","category":"page"},{"location":"tutorials/BrusselatorFF/#Computation-of-the-snaking-branch","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"Computation of the snaking branch","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"# you can detect bifurcations with the option detect_bifurcation = 3\noptc = ContinuationPar(newton_options = optn, ds = -1e-3, dsmin = 1e-7, dsmax = 2e-3, p_max = 0.295, plot_every_step = 2, max_steps = 1000, detect_bifurcation = 0)\nbd = continuation(probSh,\n\tsolp, PALC(bls = MatrixFreeBLS(@set ls.N = 2nx+2)), optc;\n\tplot = true,\n\tverbosity = 3,\n\tplot_solution = (x,p ; kw...) -> plot!(x[1:nx];kw...),\n\tnormC = x->norm(x,Inf))","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"which leads to","category":"page"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"(Image: )","category":"page"},{"location":"tutorials/BrusselatorFF/#References","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"References","text":"","category":"section"},{"location":"tutorials/BrusselatorFF/","page":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","title":"🟠 Brusselator 1d with periodic BC using FourierFlows.jl","text":"[Tzou]: Tzou, J. C., Y.-P. Ma, A. Bayliss, B. J. Matkowsky, and V. A. Volpert. Homoclinic Snaking near a Codimension-Two Turing-Hopf Bifurcation Point in the Brusselator Model.” Physical Review E 87, no. 2 (February 14, 2013): 022908. https://doi.org/10.1103/PhysRevE.87.022908.","category":"page"},{"location":"tutorials/tutorialsPD/#Period-doubling-in-the-Barrio-Varea-Aragon-Maini-model","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"","category":"section"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"Pages = [\"tutorialsPD.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"The purpose of this example is to show how to handle period doubling bifurcations of periodic orbits. Note that we do not use automatic branch switching here although this is possible (but not yet for branching from period doubling points).","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"unknown: References\nThis example is taken from Aragón, J. L., R. A. Barrio, T. E. Woolley, R. E. Baker, and P. K. Maini. “Nonlinear Effects on Turing Patterns: Time Oscillations and Chaos.” Physical Review E 86, no. 2 (2012)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"info: Method and performance\nWe focus on the Shooting method but we could have based the computation of periodic orbits on finite differences instead. Performances of the current tutorial are directly linked to the ones of DifferentialEquations.jl. ","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We focus on the following 1D model:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"tagEbeginaligned\nfracpartial upartial t=D nabla^2 u+etaleft(u+a v-C u v-u v^2right)\nfracpartial vpartial t=nabla^2 v+etaleft(b v+H u+C u v+u v^2right)\nendaligned","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"with Neumann boundary conditions. We start by encoding the model","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"using Revise\nusing DiffEqOperators, ForwardDiff, DifferentialEquations, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\nf(u, v, p) = p.η * ( u + p.a * v - p.C * u * v - u * v^2)\ng(u, v, p) = p.η * (p.H * u + p.b * v + p.C * u * v + u * v^2)\n\nfunction Laplacian(N, lx, bc = :Dirichlet)\n\thx = 2lx/N\n\tD2x = CenteredDifference(2, 2, hx, N)\n\tif bc == :Neumann\n\t\tQx = Neumann0BC(hx)\n\telseif bc == :Dirichlet\n\t\tQx = Dirichlet0BC(typeof(hx))\n\tend\n\tD2xsp = sparse(D2x * Qx)[1]\nend\n\nfunction NL!(dest, u, p, t = 0.)\n\tN = div(length(u), 2)\n\tu1 = @view (u[1:N])\n\tu2 = @view (u[N+1:end])\n\tdest[1:N] .= f.(u1, u2, Ref(p))\n\tdest[N+1:end] .= g.(u1, u2, Ref(p))\n\treturn dest\nend\n\nfunction Fbr!(f, u, p)\n\tNL!(f, u, p)\n\tmul!(f, p.Δ, u,1,1)\n\tf\nend\n\nNL(u, p) = NL!(similar(u), u, p)\nFbr(x, p, t = 0.) = Fbr!(similar(x), x, p)\n\n# this is not very efficient but simple enough ;)\nJbr(x,p) = sparse(ForwardDiff.jacobian(x -> Fbr(x, p), x))","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We can now perform bifurcation of the following Turing solution:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"N = 100\nn = 2N\nlx = 3pi /2\nX = LinRange(-lx,lx, N)\n\nΔ = Laplacian(N, lx, :Neumann)\nD = 0.08\npar_br = (η = 1.0, a = -1., b = -3/2., H = 3.0, D = D, C = -0.6, Δ = blockdiag(D*Δ, Δ))\n\nu0 = 1.0 * cos.(2X)\nsolc0 = vcat(u0, u0)\n\nprobBif = BK.BifurcationProblem(Fbr, solc0, par_br, (@lens _.C) ;J = Jbr,\n\t\trecord_from_solution = (x, p) -> norm(x, Inf),\n\t\tplot_solution = (x, p; kwargs...) -> plot!(x[1:end÷2];label=\"\",ylabel =\"u\", kwargs...))\n\n# parameters for continuation\neigls = EigArpack(0.5, :LM)\nopt_newton = NewtonPar(eigsolver = eigls, verbose=true, max_iterations = 3200, tol=1e-9)\nopts_br = ContinuationPar(dsmax = 0.04, ds = -0.01, p_min = -1.8,\n\tdetect_bifurcation = 3, nev = 21, plot_every_step = 50, newton_options = opt_newton, max_steps = 400)\n\nbr = continuation(re_make(probBif, params = (@set par_br.C = -0.2)), PALC(), opts_br;\n\tplot = true, verbosity = 3)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"which yields","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsPD/#Periodic-orbits-from-the-Hopf-point-(Standard-Shooting)","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"Periodic orbits from the Hopf point (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We continue the periodic orbit form the first Hopf point around Capprox -08598 using a Standard Simple Shooting method (see Periodic orbits based on the shooting method). To this end, we define a SplitODEProblem from DifferentialEquations.jl which is convenient for solving semilinear problems of the form","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"dot x = Ax+g(x)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"where A is the infinitesimal generator of a C_0-semigroup. We use the exponential-RK scheme ETDRK2 ODE solver to compute the solution of (E) just after the Hopf point.","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"# parameters close to the Hopf bifurcation\npar_br_hopf = @set par_br.C = -0.86\n# parameters for the ODEProblem\nf1 = DiffEqArrayOperator(par_br.Δ)\nf2 = NL!\nprob_sp = SplitODEProblem(f1, f2, solc0, (0.0, 280.0), @set par_br.C = -0.86)\n\nsol = @time solve(prob_sp, ETDRK2(krylov=true); abstol=1e-14, reltol=1e-14, dt = 0.1)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We estimate the period of the limit cycle to be around Tapprox 3. We then use this as a guess for the shooting method:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"# compute the guess for the shooting method\norbitsection = Array(sol[:, end])\ninitpo = vcat(vec(orbitsection), 3.)\n\n# define the functional for the standard simple shooting based on the\n# ODE solver ETDRK2. SectionShooting implements an appropriate phase condition\nprobSh = ShootingProblem(prob_sp, ETDRK2(krylov=true),\n\t[sol(280.0)]; abstol=1e-14, reltol=1e-14, dt = 0.1,\n lens = (@lens _.C),\n jacobian = BK.FiniteDifferencesMF())\n\n# parameters for the Newton-Krylov solver\nls = GMRESIterativeSolvers(reltol = 1e-7, N = length(initpo), maxiter = 50, verbose = false)\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 120, linsolver = ls)\n# Newton-Krylov solver\nout_po_sh = @time newton(probSh, initpo, optn; normN = norminf)\nBK.converged(out_po_sh) && printstyled(color=:red, \"--> T = \", out_po_sh.u[end], \", amplitude = \", BK.getamplitude(probSh, out_po_sh.u, par_br_hopf; ratio = 2),\"\\n\")","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"which gives","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"--> T = 2.94557883943451, amplitude = 0.05791350025709674","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We can now continue this periodic orbit:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"eig = DefaultEig()\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.01, ds= 0.005, p_min = -1.8, max_steps = 170, newton_options = (@set optn.eigsolver = eig),\n\tnev = 10, tol_stability = 1e-2, detect_bifurcation = 3)\nbr_po_sh = @time continuation(probSh, out_po_sh.u, PALC(), opts_po_cont; verbosity = 3,\n\tplot = true,\n\tlinear_algo = MatrixFreeBLS(@set ls.N = probSh.M*n+2),\n plot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], 1; kwargs...),\n record_from_solution = (u, p) -> BK.getmaximum(probSh, u, (@set par_br_hopf.C = p.p); ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We plot the result using plot(br_po_sh, br, label = \"\"):","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"tip: Numerical precision for stability\nThe Floquet multipliers are not very precisely computed here using the Shooting method. We know that 1=exp(0) should be a Floquet multiplier but this is only true here at precision ~1e-3. In order to prevent spurious bifurcation detection, there is a threshold tol_stability in ContinuationPar for declaring an unstable eigenvalue. Another way would be to use Poincaré Shooting so that this issue does not show up.","category":"page"},{"location":"tutorials/tutorialsPD/#Periodic-orbits-from-the-PD-point-(Standard-Shooting)","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"Periodic orbits from the PD point (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We now compute the periodic orbits branching of the first Period-Doubling bifurcation point. It is straightforward to obtain an initial guess using the flow around the bifurcation point:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"par_br_pd = @set par_br.C = -1.32\nprob_sp = SplitODEProblem(f1, f2, solc0, (0.0, 300.0), par_br_pd)\n# solution close to the PD point.\nsolpd = @time solve(prob_sp, ETDRK2(krylov=true); abstol=1e-14, reltol=1e-14, dt = 0.1)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"The estimated period is T_pd=62:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"orbitsectionpd = Array(solpd[:,end-100])\ninitpo_pd = vcat(vec(orbitsectionpd), 6.2)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"For educational purposes, we show the newton outputs:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"out_po_sh_pd = newton(BK.set_params_po(probSh, par_br_pd), initpo_pd , optn; normN = norminf)\nBK.converged(out_po_sh_pd) && printstyled(color=:red, \"--> T = \", out_po_sh_pd.u[end], \", amplitude = \", BK.getamplitude(probSh, out_po_sh_pd.u, (@set par_br.C = -0.86); ratio = 2),\"\\n\")","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"which gives","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 4.3061e+00 │ 0 │\n│ 1 │ 5.3254e-02 │ 10 │\n│ 2 │ 5.5053e-03 │ 12 │\n│ 3 │ 1.6203e-03 │ 13 │\n│ 4 │ 5.6236e-05 │ 12 │\n│ 5 │ 7.6290e-07 │ 12 │\n│ 6 │ 3.0634e-08 │ 13 │\n│ 7 │ 1.2282e-09 │ 12 │\n│ 8 │ 4.9233e-11 │ 13 │\n└─────────────┴──────────────────────┴────────────────┘\n 4.249150 seconds (497.85 k allocations: 2.030 GiB, 11.13% gc time)\n--> T = 6.126399996979465, amplitude = 1.410164896740365","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"We also compute the branch of periodic orbits using the following command:","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"opts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= 0.001, p_min = -1.8, max_steps = 100, newton_options = (@set optn.eigsolver = eig), nev = 5, tol_stability = 1e-3, detect_bifurcation = 2)\nbr_po_sh_pd = @time continuation(BK.set_params_po(probSh,par_br_pd), out_po_sh_pd.u, PALC(),\topts_po_cont;\n verbosity = 2, plot = true,\n linear_algo = MatrixFreeBLS(@set ls.N = probSh.M*n+2),\n plot_solution = (x, p; kwargs...) -> (BK.plot_periodic_shooting!(x[1:end-1], 1; kwargs...); plot!(br_po_sh; subplot=1, legend=false)),\n record_from_solution = (u, p; k...) -> BK.getmaximum(probSh, u, (@set par_br_pd.C = p.p); ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"and plot it using plot(br_po_sh, br, br_po_sh_pd, label = \"\"):","category":"page"},{"location":"tutorials/tutorialsPD/","page":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","title":"🟡 Period doubling in the Barrio-Varea-Aragon-Maini model","text":"(Image: )","category":"page"},{"location":"tutorials/autocatalyticAuto/#Fronts-in-1d-autocatalytic-model-(Automatic)","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Pages = [\"autocatalyticAuto.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We consider the following model [Balmforth][Malham] which is also treated in [Beyn]","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"beginarrayl\nu_t=a u_x x-u f(v) quad a0 u v mathbbR rightarrow mathbbR \nv_t=v_x x+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"where f(u) = u^m 1_ugeq 0. We chose the boundary conditions","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"left(u_- v_-right)=(01)quad left(u_+ v_+right)=(10)tagBC","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"It is straightforward to implement this problem as follows:","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"using Revise\nusing ForwardDiff, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\n# supremum norm\nnorminf(x) = norm(x, Inf)\nf(u) = u^9 # solutions are positive, so remove the heaviside\n\n# helper function to plot solutions\nfunction plotsol!(x; k...)\n\tu = @view x[1:end÷2]\n\tv = @view x[end÷2:end]\n\tplot!(u; label=\"u\", k...)\n\tplot!(v; label=\"v\", k...)\nend\nplotsol(x; k...) = (plot();plotsol!(x; k...))\n\n# encode the nonlinearity\n@views function NL!(dest, U, p, t = 0.)\n\tN = p.N\n\tu = U[1:N]\n\tv = U[N+1:2N]\n\tdest[1:N] .= -u .* f.(v)\n\tdest[N+1:2N] .= -dest[1:N]#u .* f.(v)\n\treturn dest\nend\n\n# function for the differential with specific boundary conditions\n# for fronts\n@views function applyD_add!(f, U, p, a)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tc1 = 1 / (2p.h)\n\tf[1] += a * (uL - u[2] ) * c1\n\tf[end] += a * (v[n-1] - vR ) * c1\n\n\tf[n] += a * (u[n-1] - uR ) * c1\n\tf[n+1] += a * ( vL - v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += a * (u[i-1] - u[i+1]) * c1\n\t\tf[n+i] += a * (v[i-1] - v[i+1]) * c1\n\tend\n\treturn f\nend\n\n# function which encodes the full PDE\n@views function Fcat!(f, U, p, t = 0)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\t# nonlinearity\n\tNL!(f, U, p)\n\n\t# Dirichlet boundary conditions\n\th2 = p.h * p.h\n\tc1 = 1 / h2\n\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tf[1] += p.a * (uL - 2u[1] + u[2] ) * c1\n\tf[end] += (v[n-1] - 2v[n] + vR ) * c1\n\n\tf[n] += p.a * (u[n-1] - 2u[n] + uR ) * c1\n\tf[n+1] += (vL - 2v[1] + v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += p.a * (u[i-1] - 2u[i] + u[i+1]) * c1\n\t\tf[n+i] += (v[i-1] - 2v[i] + v[i+1]) * c1\n\tend\n\treturn f\nend\nFcat(x, p, t = 0.) = Fcat!(similar(x), x, p, t)\nJcat(x,p) = sparse(ForwardDiff.jacobian(x -> Fcat(x, p), x))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We chose the following parameters:","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"N = 200\nlx = 25.\nX = LinRange(-lx,lx, N)\npar_cat = (N = N, a = 0.18, h = 2lx/N)\n\nu0 = @. (tanh(2X)+1)/2\nU0 = vcat(u0, 1 .- u0)\n\n# we define a problem to hold the vector field\nprob = BifurcationProblem(Fcat, u0, par_cat, (@lens _.a); J = Jcat)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/#Freezing-method","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"Freezing method","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"The problem may feature fronts, that is solutions of the form u(xt) = tilde u(x-st) (same for v) for a fixed value of the profile tilde u and the speed s. The equation for the front profile is, up to an abuse of notations (we removed the tildes)","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"beginarrayl\n0=a u_xixi+scdot u_xi-u f(v)\n0=v_xixi+scdot v_xi+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"with unknowns uvs. The front is solution of these equations but it is not uniquely determined because of the phase invariance. Hence, we add the phase condition (see [Beyn])","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"0 = leftlangle (uv) partial_xi (u_0v_0) rightrangle","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"where U_0=(u_0v_0) is some fixed profile. This is encoded in the problem TWProblem","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"using LinearAlgebra\n\n# this structure encodes the Lie generator\nstruct Advection{T}\n\tp::T\nend\n\nfunction LinearAlgebra.mul!(f, aD::Advection, U, α, β)\n\trmul!(f, β)\n\tapplyD_add!(f, U, aD.p, α)\nend\n\nuold = vcat(u0, (1 .- u0))\n\n# we create a TW problem\nprobTW = BK.TWProblem(prob, Advection(par_cat), copy(uold))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We now define the U_0 profile","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"uold = vcat(u0, (1 .- u0))\nDuold = zero(uold); applyD_add!(Duold, uold, par_cat,1)\n\n# update problem parameters for front problem\npar_cat_wave = (par_cat..., u0Du0 = dot(uold, Duold), Du0 = Duold, uold = uold)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Let us find the front using newton","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"front = newton(probTW, vcat(U0, 0.1), NewtonPar(verbose = true))\nprintln(\"norm front = \", front.u[1:end-1] |> norminf, \", speed = \", front.u[end])","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"plotsol(front.u[1:end-1], title=\"front solution\")","category":"page"},{"location":"tutorials/autocatalyticAuto/#Continuation-of-front-solutions","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"Continuation of front solutions","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Following [Malham], the modulated fronts are solutions of the following DAE","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"beginarrayltagDAE\nu_t=a u_x x+scdot u_x-u f(v)\nv_t=v_x x+scdot v_x+u f(v)\n0 = leftlangle U partial_xi U_0\trightrangle\nendarray","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"which can be written with a PDE M_aU_t = G(u) with mass matrix M_a = (Id Id 0). We have already written the vector field of (MF) in the problem probTW.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"Having found a front U^f, we can continue it as function of the parameter a and detect instabilities. The stability of the front is linked to the eigenelements (lambda V) solution of the generalized eigenvalue problem:","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"lambda M_acdot V = dG(U^f)cdot V","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"This is handled automatically when calling continuation on a TWProblem.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"optn = NewtonPar(tol = 1e-8)\nopt_cont_br = ContinuationPar(p_min = 0.015, p_max = 0.18, newton_options = optn, ds= -0.001, plot_every_step = 2, detect_bifurcation = 3, nev = 10, n_inversion = 6)\nbr_TW = continuation(probTW, front.u, PALC(), opt_cont_br)\nplot(br_TW, legend = :topright)","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts.","category":"page"},{"location":"tutorials/autocatalyticAuto/#References","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"References","text":"","category":"section"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"[Balmforth]: N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"[Malham]: S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.","category":"page"},{"location":"tutorials/autocatalyticAuto/","page":"🟠 Fronts in 1d autocatalytic model (Automatic)","title":"🟠 Fronts in 1d autocatalytic model (Automatic)","text":"[Beyn]: Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.","category":"page"},{"location":"tutorials/ode/lorenz84/#lorenz","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"Pages = [\"lorenz84.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"In this tutorial, we study the extended Lorenz-84 model which is also treated in MatCont [Kuznetsov]. This model is interesting because it features all codim 2 bifurcations of equilibria. It is thus convenient to test our algorithms.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"After this tutorial, you will be able to","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"detect codim 1 bifurcation Fold / Hopf / Branch point\nfollow Fold / Hopf points and detect codim 2 bifurcation points\nbranch from the detected codim 2 points to curves of Fold / Hopf points","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"The model is as follows","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"leftbeginarrayl\ndotX=-Y^2-Z^2-alpha X+alpha F-gamma U^2 \ndotY=X Y-beta X Z-Y+G \ndotZ=beta X Y+X Z-Z \ndotU=-delta U+gamma U X+T\nendarrayrighttagE","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We start with some imports:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"using Revise, Parameters, Setfield, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/lorenz84/#Problem-setting","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Problem setting","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We can now encode the vector field (E) in a function and use automatic differentiation to compute its various derivatives.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"# vector field\nfunction Lor(u, p)\n @unpack α,β,γ,δ,G,F,T = p\n\tX,Y,Z,U = u\n\t[\n\t\t-Y^2 - Z^2 - α*X + α*F - γ*U^2,\n\t\tX*Y - β*X*Z - Y + G,\n\t\tβ*X*Y + X*Z - Z,\n\t\t-δ*U + γ*U*X + T\n\t]\nend\n\n# parameter values\nparlor = (α = 1//4, β = 1, G = .25, δ = 1.04, γ = 0.987, F = 1.7620532879639, T = .0001265)\n\n# initial condition\nz0 = [2.9787004394953343, -0.03868302503393752, 0.058232737694740085, -0.02105288273117459]\n\n# bifurcation problem\nrecordFromSolutionLor(x, p) = (X = x[1], Y = x[2], Z = x[3], U = x[4])\nprob = BifurcationProblem(Lor, z0, setproperties(parlor; T=0.04, F=3.), (@lens _.F);\n record_from_solution = recordFromSolutionLor)\nnothing #hide","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-and-codim-1-bifurcations","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation and codim 1 bifurcations","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"Once the problem is set up, we can continue the state w.r.t. F to and detect codim 1 bifurcations. This is achieved as follows:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = -1.5, p_max = 3.0, ds = 0.002, dsmax = 0.15,\n\t# Optional: bisection options for locating bifurcations\n\tn_inversion = 6, max_bisection_steps = 25,\n\t# number of eigenvalues\n\tnev = 4, max_steps = 200)\n\n# compute the branch of solutions\nbr = continuation(prob, PALC(), opts_br;\n\tnormC = norminf,\n\tbothside = true)\n\nscene = plot(br, plotfold=false, markersize=4, legend=:topleft)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"br","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Fold-points","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Fold points","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We follow the Fold points in the parameter plane (TF). We tell the solver to consider br.specialpoint[5] and continue it.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"# function to record the current state\nsn_codim2 = continuation(br, 5, (@lens _.T), ContinuationPar(opts_br, p_max = 3.2, p_min = -0.1, detect_bifurcation = 1, dsmin=1e-5, ds = -0.001, dsmax = 0.005, n_inversion = 10, max_steps = 130, max_bisection_steps = 55) ; normC = norminf,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = false,\n\t# we save the different components for plotting\n\trecord_from_solution = recordFromSolutionLor,\n\t)\n\nscene = plot(sn_codim2, vars=(:X, :U), branchlabel = \"Folds\", ylims=(-0.5, 0.5))","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"sn_codim2","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"For example, we can compute the following normal form","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"get_normal_form(sn_codim2, 1; nev = 4)","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Hopf-points","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"We follow the Hopf points in the parameter plane (TF). We tell the solver to consider br.specialpoint[3] and continue it.","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_codim2_1 = continuation((@set br.alg.tangent = Bordered()), 3, (@lens _.T), ContinuationPar(opts_br, ds = -0.001, dsmax = 0.02, dsmin = 1e-4, n_inversion = 6, detect_bifurcation = 1) ; normC = norminf,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# we save the different components for plotting\n\trecord_from_solution = recordFromSolutionLor,\n\t# compute both sides of the initial condition\n\tbothside = true,\n\t)\n\nplot(sn_codim2, vars=(:X, :U), branchlabel = \"Folds\")\n\tplot!(hp_codim2_1, vars=(:X, :U), branchlabel = \"Hopfs\")\n\tylims!(-0.7,0.7);xlims!(1,1.3)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_codim2_1","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"For example, we can compute the following normal form","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"get_normal_form(hp_codim2_1, 3; nev = 4)","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Hopf-points-from-the-Bogdanov-Takens-point","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Hopf points from the Bogdanov-Takens point","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"When we computed the curve of Fold points, we detected a Bogdanov-Takens bifurcation. We can branch from it to get the curve of Hopf points. This is done as follows:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_bt = continuation((@set sn_codim2.alg.tangent = Bordered()), 4, ContinuationPar(opts_br, ds = -0.001, dsmax = 0.02, dsmin = 1e-4,\n\tn_inversion = 6, detect_bifurcation = 1) ; normC = norminf,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# we save the different components for plotting\n\trecord_from_solution = recordFromSolutionLor,\n\t)\n\nplot(sn_codim2, vars=(:X, :U), branchlabel = \"SN\")\n\tplot!(hp_codim2_1, vars=(:X, :U), branchlabel = \"Hopf1\")\n\tplot!(hp_from_bt, vars=(:X, :U), branchlabel = \"Hopf2\")\n\tylims!(-0.7,0.75);xlims!(0.95,1.3)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_bt","category":"page"},{"location":"tutorials/ode/lorenz84/#Continuation-of-Hopf-points-from-the-Zero-Hopf-point","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"Continuation of Hopf points from the Zero-Hopf point","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"When we computed the curve of Fold points, we detected a Zero-Hopf bifurcation. We can branch from it to get the curve of Hopf points. This is done as follows:","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_zh = continuation((@set sn_codim2.alg.tangent = Bordered()), 2, ContinuationPar(opts_br, ds = 0.001, dsmax = 0.02, dsmin = 1e-4, n_inversion = 6, detect_bifurcation = 1, max_steps = 150) ;\n\tnormC = norminf,\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = true,\n\trecord_from_solution = recordFromSolutionLor,\n\tbothside = false,\n\tbdlinsolver = MatrixBLS(),\n\t)\n\nplot(sn_codim2,vars=(:X, :U),)\n\tplot!(hp_codim2_1, vars=(:X, :U), branchlabel = \"Hopf\")\n\tplot!(hp_from_bt, vars=(:X, :U), branchlabel = \"Hopf2\")\n\tplot!( hp_from_zh, vars=(:X, :U), branchlabel = \"Hopf\", plotspecialpoints = false, legend = :topleft)\n\tylims!(-0.7,0.75);xlims!(0.95,1.3)","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"hp_from_zh","category":"page"},{"location":"tutorials/ode/lorenz84/#References","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"References","text":"","category":"section"},{"location":"tutorials/ode/lorenz84/","page":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","title":"🟡 Extended Lorenz-84 model (codim 2 + BT/ZH aBS)","text":"[Kuznetsov]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.","category":"page"},{"location":"tutorials/ode/steinmetz/#steinmetz","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"","category":"section"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"Pages = [\"steinmetz.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"This example is found in the MatCont ecosystem.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"The Steinmetz-Larter model is studied in the MatCont ecosystem because it is a simple example where a Chenciner bifurcation occurs.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"tagEleftbeginarrayl\ndotA=-k_1 A B X-k_3 A B Y+k_7-k_-7 A \ndotB=-k_1 A B X-k_3 A B Y+k_8 \ndotX=k_1 A B X-2 k_2 X^2+2 k_3 A B Y-k_4 X+k_6 \ndotY=-k_3 A B Y+2 k_2 X^2-k_5 Y\nendarrayright","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"This tutorial is also useful in that we show how to start periodic orbits continuation from solutions obtained from solving ODEs. Being a relatively advanced tutorial, we do not give too many details.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"We start by coding the bifurcation problem.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"using Revise\nusing Test, ForwardDiff, Parameters, Plots\nusing BifurcationKit, Test\nconst BK = BifurcationKit\n\nfunction SL!(du, u, p, t = 0)\n\t@unpack k1, k2, k3, k4, k5, k6, k7, k₋₇, k8 = p\n\tA,B,X,Y = u\n\n\tdu[1] = -k1*A*B*X - k3*A*B*Y + k7 - k₋₇*A\n\tdu[2] = -k1*A*B*X - k3*A*B*Y + k8\n\tdu[3] = k1*A*B*X - 2*k2*X^2 + 2*k3*A*B*Y - k4*X+k6\n\tdu[4] = -k3*A*B*Y + 2*k2*X^2 - k5*Y\n\tdu\nend\n\nz0 = rand(4)\npar_sl = (k1=0.1631021, k2=1250., k3=0.046875, k4=20., k5=1.104, k6=0.001, k₋₇=0.1175, k7=1.5, k8=0.75)\nprob = BifurcationProblem(SL!, z0, par_sl, (@lens _.k8);)\n\n# record variables for plotting\nfunction recordFromSolution(x, p) \n\txtt = BK.get_periodic_orbit(p.prob, x, p.p)\n\treturn (max = maximum(xtt[1,:]),\n\t\t\tmin = minimum(xtt[1,:]),\n\t\t\tperiod = getperiod(p.prob, x, p.p))\nend\n\n# plotting function\nfunction plotSolution(x, p; k...)\n\txtt = BK.get_periodic_orbit(p.prob, x, p.p)\n\tplot!(xtt.t, xtt[:,:]'; label = \"\", k...)\nend\n\n# group parameters\nargspo = (record_from_solution = recordFromSolution,\n\tplot_solution = plotSolution)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"We obtain some trajectories as seeds for computing periodic orbits.","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"using DifferentialEquations\nalg_ode = Rodas5()\nprob_de = ODEProblem(SL!, z0, (0,136.), par_sl)\nsol = solve(prob_de, alg_ode)\nprob_de = ODEProblem(SL!, sol.u[end], (0,30.), sol.prob.p, reltol = 1e-11, abstol = 1e-13)\nsol = solve(prob_de, alg_ode)\nplot(sol)","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"We generate a shooting problem form the computed trajectories and continue the periodic orbits as function of k_8","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"probsh, cish = generate_ci_problem( ShootingProblem(M=4), prob, prob_de, sol, 16.; reltol = 1e-10, abstol = 1e-12, parallel = true)\n\nopts_po_cont = ContinuationPar(p_min = 0., p_max = 20.0, ds = 0.002, dsmax = 0.05, n_inversion = 8, detect_bifurcation = 3, max_bisection_steps = 25, nev = 4, max_steps = 60, save_eigenvectors = true, tol_stability = 1e-3)\n@set! opts_po_cont.newton_options.verbose = false\n@set! opts_po_cont.newton_options.max_iterations = 10\nbr_sh = continuation(deepcopy(probsh), cish, PALC(tangent = Bordered()), opts_po_cont;\n\t#verbosity = 3, plot = true,\n\tcallback_newton = BK.cbMaxNorm(10),\n\targspo...)","category":"page"},{"location":"tutorials/ode/steinmetz/#Curve-of-Fold-points-of-periodic-orbits","page":"🟠 Steinmetz-Larter model","title":"Curve of Fold points of periodic orbits","text":"","category":"section"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"opts_posh_fold = ContinuationPar(br_sh.contparams, detect_bifurcation = 2, max_steps = 35, p_max = 1.9, plot_every_step = 10, dsmax = 4e-2, ds = 1e-2)\n@set! opts_posh_fold.newton_options.tol = 1e-12\n@set! opts_posh_fold.newton_options.verbose = true\nfold_po_sh = @time continuation(br_sh, 2, (@lens _.k7), opts_posh_fold;\n\t\t#verbosity = 3, plot = true,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tstart_with_eigen = false,\n\t\tusehessian = false,\n\t\tjacobian_ma = :minaug,\n\t\tnormC = norminf,\n\t\tcallback_newton = BK.cbMaxNorm(1e1),\n\t\tbdlinsolver = BorderingBLS(solver = DefaultLS(), check_precision = false),\n\t\t)\nplot(fold_po_sh)","category":"page"},{"location":"tutorials/ode/steinmetz/#Curve-of-NS-points-of-periodic-orbits","page":"🟠 Steinmetz-Larter model","title":"Curve of NS points of periodic orbits","text":"","category":"section"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"opts_posh_ns = ContinuationPar(br_sh.contparams, detect_bifurcation = 0, max_steps = 35, p_max = 1.9, plot_every_step = 10, dsmax = 4e-2, ds = 1e-2)\n@set! opts_posh_ns.newton_options.tol = 1e-12\nns_po_sh = continuation(br_sh, 1, (@lens _.k7), opts_posh_ns;\n\t\tverbosity = 2, plot = false,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tstart_with_eigen = false,\n\t\tusehessian = false,\n\t\tjacobian_ma = :minaug,\n\t\tnormC = norminf,\n\t\tcallback_newton = BK.cbMaxNorm(1e1),\n\t\t)","category":"page"},{"location":"tutorials/ode/steinmetz/","page":"🟠 Steinmetz-Larter model","title":"🟠 Steinmetz-Larter model","text":"plot(ns_po_sh, fold_po_sh, branchlabel = [\"NS\",\"Fold\"])","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-predator-prey-model","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"Pages = [\"tutorialsCodim2PO.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"This example is found in the MatCont ecosystem.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"The following is a periodically forced predator-prey model studied in [Kuznetsov] using shooting techniques.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"tagEleftbeginaligned\ndotx =rleft(1-fracxKright) x-fraca x yb_0(1+varepsilon u)+x \ndoty =e fraca x yb_0(1+varepsilon u)+x-d y \ndotu =u-2 pi v-left(u^2+v^2right) u \ndotv =2 pi u+v-left(u^2+v^2right) v\nendalignedright","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"This tutorial is useful in that we show how to start periodic orbits continuation from solutions obtained from solving ODEs. We are interested in cases where (uv)neq (00) for which we have only periodic solutions. Thus, we cannot rely on branching from equilibria to find these periodic orbits.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nfunction Pop!(du, X, p, t = 0)\n\t@unpack r,K,a,ϵ,b0,e,d, = p\n\tx, y, u, v = X\n\tp = a * x / (b0 * (1 + ϵ * u) + x)\n\tdu[1] = r * (1 - x/K) * x - p * y\n\tdu[2] = e * p * y - d * y\n\ts = u^2 + v^2\n\tdu[3] = u-2pi * v - s * u\n\tdu[4] = 2pi * u + v - s * v\n\tdu\nend\n\npar_pop = ( K = 1., r = 6.28, a = 12.56, b0 = 0.25, e = 1., d = 6.28, ϵ = 0.2, )\n\nz0 = [0.1,0.1,1,0]\n\nprob = BifurcationProblem(Pop!, z0, par_pop, (@lens _.b0);\n\trecord_from_solution = (x, p) -> (x = x[1], y = x[2], u = x[3]))\n\nopts_br = ContinuationPar(p_min = 0., p_max = 20.0, ds = 0.002, dsmax = 0.01, n_inversion = 6, detect_bifurcation = 3, max_bisection_steps = 25, nev = 4, max_steps = 20000)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Simulation-of-the-model","page":"🟠 Periodic predator-prey model","title":"Simulation of the model","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"This is very straightforward thanks to SciML.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"using DifferentialEquations\nprob_de = ODEProblem(Pop!, z0, (0,200.), par_pop)\nsol = solve(prob_de, Rodas5())\nprob_de = ODEProblem(Pop!, sol.u[end], (0,3.), par_pop, reltol = 1e-8, abstol = 1e-10)\nsol = solve(prob_de, Rodas5())\nplot(sol)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Utility-functions","page":"🟠 Periodic predator-prey model","title":"Utility functions","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We start with two helper functions that record and plot the periodic orbits. The following works for shooting, collocation and trapezoid methods for computing periodic orbits.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"argspo = (record_from_solution = (x, p) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\t\tmin = minimum(xtt[1,:]),\n\t\t\t\tperiod = getperiod(p.prob, x, p.p))\n\tend,\n\tplot_solution = (x, p; k...) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\tplot!(xtt.t, xtt[1,:]; label = \"x\", k...)\n\t\tplot!(xtt.t, xtt[2,:]; label = \"y\", k...)\n\t\t# plot!(br; subplot = 1, putspecialptlegend = false)\n\tend)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-orbits-with-trapezoid-method","page":"🟠 Periodic predator-prey model","title":"Periodic orbits with trapezoid method","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We compute periodic orbits of (E) using the Trapezoid method. We are now equipped to build a periodic orbit problem from a solution sol::ODEProblem.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"# function to build probtrap from sol\nprobtrap, ci = BK.generate_ci_problem(PeriodicOrbitTrapProblem(M = 150),\n\tprob, sol, 2.)\n\nopts_po_cont = setproperties(opts_br, max_steps = 50, tol_stability = 1e-8)\nbrpo_fold = continuation(probtrap, ci, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\n\nscene = plot(brpo_fold)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue w.r.t. to epsilon and find a period-doubling bifurcation.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"prob2 = @set probtrap.prob_vf.lens = @lens _.ϵ\nbrpo_pd = continuation(prob2, ci, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\nscene = plot(brpo_pd)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-orbits-with-parallel-standard-shooting","page":"🟠 Periodic predator-prey model","title":"Periodic orbits with parallel standard shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We are now ready to build a periodic orbit problem from a solution sol::ODEProblem.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"probsh, cish = generate_ci_problem( ShootingProblem(M=3),\n\tprob, prob_de, sol, 2.; alg = Rodas5())\n\nopts_po_cont = setproperties(opts_br, max_steps = 50, tol_stability = 1e-3)\nbr_fold_sh = continuation(probsh, cish, PALC(tangent = Bordered()), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n)\n\nscene = plot(br_fold_sh)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue w.r.t. to epsilon and find a period-doubling bifurcation.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"probsh2 = @set probsh.lens = @lens _.ϵ\nbrpo_pd_sh = continuation(probsh2, cish, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\nscene = plot(brpo_pd_sh)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Periodic-orbits-with-orthogonal-collocation","page":"🟠 Periodic predator-prey model","title":"Periodic orbits with orthogonal collocation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We do the same as in the previous section but using orthogonal collocation. This is the most reliable and precise method for ODE. When the dimension of the ODE is large, it becomes prohibitive.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"# this is the function which builds probcoll from sol\nprobcoll, ci = generate_ci_problem(PeriodicOrbitOCollProblem(26, 3; update_section_every_step = 0),\n\tprob, sol, 2.)\n\nopts_po_cont = setproperties(opts_br, max_steps = 50, tol_stability = 1e-8)\nbrpo_fold = continuation(probcoll, ci, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\nscene = plot(brpo_fold)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue w.r.t. to epsilon and find a period-doubling bifurcation.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"prob2 = @set probcoll.prob_vf.lens = @lens _.ϵ\nbrpo_pd = continuation(prob2, ci, PALC(), ContinuationPar(opts_po_cont, dsmax = 5e-3);\n\tverbosity = 3, plot = true,\n\targspo...\n\t)\n\nscene = plot(brpo_pd)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#Continuation-of-Fold-/-PD-of-periodic-orbits-with-Shooting","page":"🟠 Periodic predator-prey model","title":"Continuation of Fold / PD of periodic orbits with Shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We continue the previously detected fold/period-doubling bifurcations as function of two parameters and detect codim 2 bifurcations. We first start with the computation of the curve of Folds.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"opts_posh_fold = ContinuationPar(br_fold_sh.contparams, detect_bifurcation = 3, max_steps = 100, p_min = 0.01, p_max = 1.2)\n@set! opts_posh_fold.newton_options.tol = 1e-12\n\nfold_po_sh2 = continuation(br_fold_sh, 1, (@lens _.ϵ), opts_posh_fold;\n\t\tverbosity = 2, plot = true,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tjacobian_ma = :minaug,\n\t\tstart_with_eigen = false,\n\t\tbothside = true,\n\t\tcallback_newton = BK.cbMaxNorm(1),\n\t\t)\n\nfold_po_sh1 = continuation(br_fold_sh, 2, (@lens _.ϵ), opts_posh_fold;\n\t\tverbosity = 2, plot = true,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tjacobian_ma = :minaug,\n\t\tstart_with_eigen = false,\n\t\tbothside = true,\n\t\tcallback_newton = BK.cbMaxNorm(1),\n\t\t)","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"We turn to the computation of the curve of PD points.","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"par_pop2 = @set par_pop.b0 = 0.45\nsol2 = solve(remake(prob_de, p = par_pop2, u0 = [0.1,0.1,1,0], tspan=(0,1000)), Rodas5())\nsol2 = solve(remake(sol2.prob, tspan = (0,10), u0 = sol2[end]), Rodas5())\nplot(sol2, xlims= (8,10))\n\nprobshpd, ci = generate_ci_problem(ShootingProblem(M=3), re_make(prob, params = sol2.prob.p), remake(prob_de, p = par_pop2), sol2, 1.; alg = Rodas5())\n\nprob2 = @set probshpd.lens = @lens _.ϵ\nbrpo_pd = continuation(prob2, ci, PALC(), ContinuationPar(opts_po_cont, dsmax = 5e-3);\n\tverbosity = 3, plot = true,\n\targspo...,\n\tbothside = true,\n\t)\n\nopts_pocoll_pd = ContinuationPar(brpo_pd.contparams, detect_bifurcation = 3, max_steps = 40, p_min = 1.e-2, plot_every_step = 10, dsmax = 1e-2, ds = -1e-3)\n@set! opts_pocoll_pd.newton_options.tol = 1e-12\npd_po_sh2 = continuation(brpo_pd, 2, (@lens _.b0), opts_pocoll_pd;\n\t\tverbosity = 3,\n\t\tdetect_codim2_bifurcation = 2,\n\t\tstart_with_eigen = false,\n\t\tusehessian = false,\n\t\tjacobian_ma = :minaug,\n\t\tnormC = norminf,\n\t\tcallback_newton = BK.cbMaxNorm(10),\n\t\tbothside = true,\n\t\t)\n\nplot(fold_po_sh1, fold_po_sh2, branchlabel = [\"FOLD\", \"FOLD\"])\nplot!(pd_po_sh2, vars = (:ϵ, :b0), branchlabel = \"PD\")","category":"page"},{"location":"tutorials/ode/tutorialsCodim2PO/#References","page":"🟠 Periodic predator-prey model","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialsCodim2PO/","page":"🟠 Periodic predator-prey model","title":"🟠 Periodic predator-prey model","text":"[Kuznetsov]: Yu.A. Kuznetsov, S. Muratori, and S. Rinaldi. Bifurcations and chaos in a periodic predator-prey model, Internat. J. Bifur. Chaos Appl. Sci. Engr., 2 (1992), 117-128.","category":"page"},{"location":"borderedlinearsolver/#Bordered-linear-solvers-(BLS)","page":"Bordered linear solvers","title":"Bordered linear solvers (BLS)","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"The bordered linear solvers must be subtypes of AbstractBorderedLinearSolver <: AbstractLinearSolver.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"The methods provided here solve bordered linear equations. More precisely, one is interested in the solution u to Jcdot u = v where","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"tag E J=left(beginarrayll\nA b \nc^T d\nendarrayright) text and v=left(beginarrayl\nv_1 \nv_2\nendarrayright)","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"Such linear solver bdlsolve will be called like sol, success, itnumber = bdlsolve(A, b, c, d, v1, v2) throughout the package.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"warning: Complex numbers\nIn the case where cinmathbb C^N, please note that the adjoint operator c^T involves a conjugate.","category":"page"},{"location":"borderedlinearsolver/#Full-matrix-MatrixBLS","page":"Bordered linear solvers","title":"Full matrix MatrixBLS","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"This easiest way to solve (E) is by forming the matrix J. In case it is sparse, it should be relatively efficient. You can create such bordered linear solver using bls = MatrixBLS(ls) where ls::AbstractLinearSolver is a linear solver (which defaults to \\) used to solve the linear problem associated to J. This is the default method used in the package. ","category":"page"},{"location":"borderedlinearsolver/#Bordering-method-BorderingBLS","page":"Bordered linear solvers","title":"Bordering method BorderingBLS","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"The general solution u=left(beginarrayl u_1 \nu_2 endarrayright) to (E) when A is non singular is","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"beginarrayl\nu_2 = frac1d - ccdot x_2(v_2 - ccdot x_1) \nu_1=x_1-u_2x_2\nendarray","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"where x_1=A^-1v_1 x_2=A^-1b. ","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"It is very efficient for large scale problems because it is entirely Matrix-Free and one can use preconditioners. You can create such bordered linear solver using bls = BorderingBLS(ls) where ls::AbstractLinearSolver is a linear solver which defaults to \\. The intermediate solutions x_1=A^-1v_1 x_2=A^-1b are formed using ls.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"In the case where ls = DefaultLS(), the factorisation of A is cached so the second linear solve is very fast","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"There are more options to BorderingBLS. First, the residual can be checked using the option check_precision = true. If the residual is above a prescribed tolerance, an iterative method is used based on several bordering transformations. This is the BEC+k algorithm in [Govaerts].","category":"page"},{"location":"borderedlinearsolver/#Full-Matrix-Free-MatrixFreeBLS","page":"Bordered linear solvers","title":"Full Matrix-Free MatrixFreeBLS","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"In cases where A is singular but J is not, the bordering method may fail. It can thus be advantageous to form the Matrix-Free version of J and call a generic linear solver to find the solution to (E). You can create such bordered linear solver using bls = MatrixFreeBLS(ls) where ls::AbstractLinearSolver is a (Matrix Free) linear solver which is used to invert J.","category":"page"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"For now, this linear solver only works with AbstractArray","category":"page"},{"location":"borderedlinearsolver/#References","page":"Bordered linear solvers","title":"References","text":"","category":"section"},{"location":"borderedlinearsolver/","page":"Bordered linear solvers","title":"Bordered linear solvers","text":"[Govaerts]: Govaerts, W. “Stable Solvers and Block Elimination for Bordered Systems.” SIAM Journal on Matrix Analysis and Applications 12, no. 3 (July 1, 1991): 469–83. https://doi.org/10.1137/0612034.","category":"page"},{"location":"capabilities/#Overview-of-capabilities","page":"Overview of capabilities","title":"Overview of capabilities","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Pages = [\"capabilities.md\"]\nDepth = 3","category":"page"},{"location":"capabilities/#Main-features","page":"Overview of capabilities","title":"Main features","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Newton-Krylov solver with generic linear / eigen preconditioned solver. Idem for the arc-length continuation.\nNewton-Krylov solver with nonlinear deflation and preconditioner. It can be used for branch switching for example. It is used for deflated continuation.\nContinuation written as an iterator\nMonitoring user functions along curves computed by continuation, see events\nContinuation methods: PALC, Moore Penrose, Multiple, Polynomial, Deflated continuation, ANM, ...\nBifurcation points located with bisection","category":"page"},{"location":"capabilities/#Capabilities-related-to-equilibria","page":"Overview of capabilities","title":"Capabilities related to equilibria","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Detection of Branch, Fold, Hopf bifurcation points of stationary solutions and computation of their normal form.\nAutomatic branch switching at branch points (whatever the dimension of the kernel) to equilibria\nAutomatic computation of bifurcation diagrams of equilibria\nFold / Hopf continuation based on Minimally Augmented formulation, with Matrix Free / Sparse / Dense Jacobian.\nDetection of all codim 2 bifurcations of equilibria and computation of the normal forms of Bogdanov-Takens, Bautin and Cusp\nBranching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf points to Fold / Hopf curve","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Note that you can combine most solvers, like use Deflation for Periodic orbit computation or Fold of periodic orbits family.","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Custom state means, we can use something else than AbstractArray, for example your own struct.","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Features Matrix Free Custom state Tutorial GPU\n(Deflated) Krylov-Newton Yes Yes link Yes\nContinuation PALC (Natural, Secant, Tangent, Polynomial) Yes Yes All Yes\nDeflated Continuation Yes Yes link Yes\nBifurcation / Fold / Hopf point detection Yes Yes All / All / link Yes\nFold Point continuation Yes Yes PDE, PDE, ODE Yes\nHopf Point continuation Yes AbstractArray ODE \nBranch point / Fold / Hopf normal form Yes Yes Yes\nBranch switching at Branch points Yes AbstractArray link Yes\nAutomatic bifurcation diagram computation of equilibria Yes AbstractArray link \nBogdanov-Takens / Bautin / Cusp / Zero-Hopf / Hopf-Hopf point detection Yes Yes ODE \nBogdanov-Takens / Bautin / Cusp normal forms Yes AbstractArray ODE Yes\nBranching from Bogdanov-Takens / Zero-Hopf / Hopf-Hopf to Fold / Hopf curve Yes AbstractArray ODE ","category":"page"},{"location":"capabilities/#Capabilities-related-to-Periodic-orbits","page":"Overview of capabilities","title":"Capabilities related to Periodic orbits","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Periodic orbit computation and continuation using parallel (Standard or Poincaré) Shooting, Finite Differences or Orthogonal Collocation.\nAutomatic branch switching at simple Hopf points to periodic orbits\nDetection of Branch, Fold, Neimark-Sacker, Period Doubling bifurcation points of periodic orbits.\nContinuation of Fold of periodic orbits","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Legend for the table: Standard shooting (SS), Poincaré shooting (PS), Orthogonal collocation (OC), trapezoid (T).","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"Features Method Matrix Free Custom state Tutorial GPU\nBranch switching at Hopf points SS/PS/OC/T See each ODE \nNewton / continuation T Yes AbstractVector PDE, PDE Yes\nNewton / continuation OC AbstractVector ODE \nNewton / continuation SS Yes AbstractArray ODE Yes\nNewton / continuation PS Yes AbstractArray PDE Yes\nFold, Neimark-Sacker, Period doubling detection SS/PS/OC/T See each AbstractVector link \nBranch switching at Branch point SS/PS/OC/T See each ODE \nBranch switching at PD point SS/PS/OC/T See each ODE \nContinuation of Fold points SS/PS/OC/T See each AbstractVector ODE PDE Yes\nContinuation of Period-doubling points SS/OC AbstractVector ODE \nContinuation of Neimark-Sacker points SS/OC AbstractVector ODE \ndetection of codim 2 bifurcations of periodic orbits SS/OC AbstractVector ODE \nBranch switching at Bautin point to curve of Fold of periodic orbits SS/OC AbstractVector ODE \nBranch switching at ZH/HH point to curve of NS of periodic orbits SS/OC AbstractVector ODE ","category":"page"},{"location":"capabilities/#Capabilities-related-to-Homoclinic-orbits","page":"Overview of capabilities","title":"Capabilities related to Homoclinic orbits","text":"","category":"section"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"This is available through the plugin HclinicBifurcationKit.jl. Please see the specific docs for more information.","category":"page"},{"location":"capabilities/","page":"Overview of capabilities","title":"Overview of capabilities","text":"compute Homoclinic to Hyperbolic Saddle Orbits (HomHS) using Orthogonal collocation or Standard shooting\ncompute bifurcation of HomHS\nstart HomHS from a direct simulation\nautomatic branch switching to HomHS from Bogdanov-Takes bifurcation point","category":"page"},{"location":"migration/#Migration-from-previous-versions","page":"Migration from old versions","title":"Migration from previous versions","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"Pages = [\"migration.md\"]\nDepth = 2","category":"page"},{"location":"migration/#Migration-from-v0.1.x-to-v0.2.x","page":"Migration from old versions","title":"Migration from v0.1.x to v0.2.x","text":"","category":"section"},{"location":"migration/#IMPORTANT-NOTICE","page":"Migration from old versions","title":"IMPORTANT NOTICE","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"New version of the package with modified interface. You are now required to define a BifurcationProblem to perform continuation or bifurcation analysis. The previous interface is available under the tag 0.1.12 which can be installed by doing","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"] add BifurcationKit@0.1.12","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"The new version provides many bugs fix though. (Please note that the docs are up to date).","category":"page"},{"location":"migration/#Introduction","page":"Migration from old versions","title":"Introduction","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"In v0.2.x, we introduced problem based bifurcation diagram, meaning that you have now to wrap your vector field in a BifurcationProblem. You also need to pass your plot/record functions.","category":"page"},{"location":"migration/#Don't-use-AD-yourself","page":"Migration from old versions","title":"Don't use AD yourself","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"There is nothing wrong with doing so but this is done in the constructor of BifurcationPoblem, so if myJacAD is the jacobian computed using ForwardDiff, the declaration","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"prob = BifurcationProblem(F, x, p, lens ; J = myJacAD) ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"should be ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"prob = BifurcationProblem(F, x, p, lens) ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"There is nothing wrong in passing your own jacobian though","category":"page"},{"location":"migration/#Error:-no-method-matching-iterate(::BifurcationKit.ContResult","page":"Migration from old versions","title":"Error: no method matching iterate(::BifurcationKit.ContResult","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"This is because you use the old syntax ","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"br, = continuation(...)","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"instead of (no comma)","category":"page"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"br = continuation(...)","category":"page"},{"location":"migration/#Arguments-to-continuation","page":"Migration from old versions","title":"Arguments to continuation","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"recordFromSolution and plotFromSolution should be passed to BifurcationProblem instead of continuation.","category":"page"},{"location":"migration/#Migration-from-v0.2.x-to-v0.3.x","page":"Migration from old versions","title":"Migration from v0.2.x to v0.3.x","text":"","category":"section"},{"location":"migration/","page":"Migration from old versions","title":"Migration from old versions","text":"A new version v0.3 has been tagged in which the function names, keyword arguments,... follow the Julia convention. There are a lot of breaking changes. For example, callbackN has been changed to callback_newton.","category":"page"},{"location":"tutorials/ode/Colpitts/#Colpitts–type-Oscillator","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"","category":"section"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Pages = [\"Colpitts.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"In this tutorial, we show how to study parametrized quasilinear DAEs like:","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"A(mux)dot x = G(mux)","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"In particular, we detect a Hopf bifurcation and compute the periodic orbit branching from it using a multiple standard method.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"The following DAE model is taken from [Rabier]:","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"left(beginarraycccc\n-left(C_1+C_2right) C_2 0 0 \nC_2 -C_2 0 0 \nC_1 0 0 0 \n0 0 L 0\nendarrayright)left(beginarrayc\ndotx_1 \ndotx_2 \ndotx_3 \ndotx_4\nendarrayright)=left(beginarrayc\nR^-1left(x_1-Vright)+I Eleft(x_1 x_2right) \nx_3+I Cleft(x_1 x_2right) \n-x_3-x_4 \n-mu+x_2\nendarrayright)","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"It is easy to encode the DAE as follows. The mass matrix is defined next.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nusing LinearAlgebra # for eigen\nconst BK = BifurcationKit\n\n# function to record information from the soluton\nrecordFromSolution(x, p) = (u1 = norminf(x), x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4])\n\n# vector field\nf(x, p) = p.Is * (exp(p.q * x) - 1)\nIE(x1, x2, p) = -f(x2, p) + f(x1, p) / p.αF\nIC(x1, x2, p) = f(x2, p)/ p.αR - f(x1, p)\n\nfunction Colpitts!(dz, z, p, t = 0)\n\t@unpack C1, C2, L, R, Is, q, αF, αR, V, μ = p\n\tx1, x2, x3, x4 = z\n\tdz[1] = (x1 - V) / R + IE(x1, x2, p)\n\tdz[2] =\tx3 + IC(x1, x2, p)\n\tdz[3] = -x3-x4\n\tdz[4] = -μ+x2\n\tdz\nend\n\n# parameter values\npar_Colpitts = (C1 = 1.0, C2 = 1.0, L = 1.0, R = 1/4., Is = 1e-16, q = 40., αF = 0.99, αR = 0.5, μ = 0.5, V = 6.)\n\n# initial condition\nz0 = [0.9957,0.7650,19.81,-19.81]\n\n# mass matrix\nBe = [-(par_Colpitts.C1+par_Colpitts.C2) par_Colpitts.C2 0 0;par_Colpitts.C2 -par_Colpitts.C2 0 0;par_Colpitts.C1 0 0 0; 0 0 par_Colpitts.L 0]\n\n# we group the differentials together\nprob = BifurcationProblem(Colpitts!, z0, par_Colpitts, (@lens _.μ); record_from_solution = recordFromSolution)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"We first compute the branch of equilibria. But we need a generalized eigenvalue solver for this.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"# we need a specific eigensolver with mass matrix B\nstruct EigenDAE{Tb} <: BK.AbstractDirectEigenSolver\n\tB::Tb\nend\n\n# compute the eigen elements\nfunction (eig::EigenDAE)(Jac, nev; k...)\n\tF = eigen(Jac, eig.B)\n\tI = sortperm(F.values, by = real, rev = true)\n\treturn Complex.(F.values[I]), Complex.(F.vectors[:, I]), true, 1\nend\n\n# continuation options\noptn = NewtonPar(tol = 1e-13, max_iterations = 10, eigsolver = EigenDAE(Be))\nopts_br = ContinuationPar(p_min = -0.4, p_max = 0.8, ds = 0.01, dsmax = 0.01, nev = 4, plot_every_step = 3, max_steps = 1000, newton_options = optn)\n\topts_br = @set opts_br.newton_options.verbose = false\n\tbr = continuation(prob, PALC(), opts_br; normC = norminf)\n\nscene = plot(br, vars = (:param, :x1))","category":"page"},{"location":"tutorials/ode/Colpitts/#Periodic-orbits-with-Multiple-Standard-Shooting","page":"🟡 Colpitts–type Oscillator","title":"Periodic orbits with Multiple Standard Shooting","text":"","category":"section"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"We use shooting to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Thanks to [Lamour], we can just compute the Floquet coefficients to get the nonlinear stability of the periodic orbit. Two period doubling bifurcations are detected.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Note that we use Automatic Branch Switching from a Hopf bifurcation despite the fact the normal form implemented in BifurcationKit.jl is not valid for DAE. For example, it predicts a subciritical Hopf point whereas we see below that it is supercritical. Nevertheless, it provides a","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"using DifferentialEquations\n\n# this is the ODEProblem used with `DiffEqBase.solve`\n# we set the initial conditions\nprob_dae = ODEFunction(Colpitts!; mass_matrix = Be)\nprobFreez_ode = ODEProblem(prob_dae, z0, (0., 1.), par_Colpitts)\n\n# we lower the tolerance of newton for the periodic orbits\noptnpo = @set optn.tol = 1e-9\n@set! optnpo.eigsolver = DefaultEig()\n\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= -0.0001, p_min = 0.2, max_steps = 50, newton_options = optnpo, nev = 4, tol_stability = 1e-3, plot_every_step = 5)\n\n\n# Shooting functional. Note the stringent tolerances used to cope with\n# the extreme parameters of the model\nprobSH = ShootingProblem(10, probFreez_ode, Rodas5P(); reltol = 1e-10, abstol = 1e-13)\n\n# automatic branching from the Hopf point\nbr_po = continuation(br, 1, opts_po_cont, probSH;\n\tplot = true, verbosity = 3,\n\tlinear_algo = MatrixBLS(),\n\t# δp is use to parametrise the first parameter point on the\n\t# branch of periodic orbits\n\tδp = 0.001,\n\trecord_from_solution = (u, p) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, u, (@set par_Colpitts.μ=p.p))\n\t\tm = maximum(outt[1,:])\n\t\treturn (s = m, period = u[end])\n\tend,\n\t# plotting of a solution\n\tplot_solution = (x, p; k...) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, x, (@set par_Colpitts.μ=p.p))\n\t\tplot!(outt.t, outt[2,:], subplot = 3)\n\t\tplot!(br, vars = (:param, :x1), subplot = 1)\n\tend,\n\t# the newton Callback is used to reject residual > 1\n\t# this is to avoid numerical instabilities from DE.jl\n\tcallback_newton = BK.cbMaxNorm(1.0),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"(Image: )","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"with detailed information","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":" ┌─ Curve type: PeriodicOrbitCont from Hopf bifurcation point.\n ├─ Number of points: 38\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter μ starts at 0.7642229295455086, ends at 0.6352549726782099\n ├─ Algo: PALC\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, pd at μ ≈ +0.73116245 ∈ (+0.73116245, +0.73152250), |δp|=4e-04, [converged], δ = ( 1, 1), step = 17, eigenelements in eig[ 18], ind_ev = 1\n- # 2, pd at μ ≈ +0.67272920 ∈ (+0.67272920, +0.67310008), |δp|=4e-04, [converged], δ = (-1, -1), step = 27, eigenelements in eig[ 28], ind_ev = 1\n- # 3, endpoint at μ ≈ +0.63525497, step = 37","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"Let us show that this bifurcation diagram is valid by showing evidences for the period doubling bifurcation.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"probFreez_ode = ODEProblem(prob_dae, br.specialpoint[1].x .+ 0.01rand(4), (0., 200.), @set par_Colpitts.μ = 0.733)\n\nsolFreez = @time solve(probFreez_ode, Rodas4(), progress = true;reltol = 1e-10, abstol = 1e-13)\n\nscene = plot(solFreez, vars = [2], xlims=(195,200), title=\"μ = $(probFreez_ode.p.μ)\")","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"and after the bifurcation","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"probFreez_ode = ODEProblem(prob_dae, br.specialpoint[1].x .+ 0.01rand(4), (0., 200.), @set par_Colpitts.μ = 0.72)\n\nsolFreez = @time solve(probFreez_ode, Rodas4(), progress = true;reltol = 1e-10, abstol = 1e-13)\n\nscene = plot(solFreez, vars = [2], xlims=(195,200), title=\"μ = $(probFreez_ode.p.μ)\")","category":"page"},{"location":"tutorials/ode/Colpitts/#References","page":"🟡 Colpitts–type Oscillator","title":"References","text":"","category":"section"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"[Rabier]: Rabier, Patrick J. “The Hopf Bifurcation Theorem for Quasilinear Differential-Algebraic Equations.” Computer Methods in Applied Mechanics and Engineering 170, no. 3–4 (March 1999): 355–71. https://doi.org/10.1016/S0045-7825(98)00203-5.","category":"page"},{"location":"tutorials/ode/Colpitts/","page":"🟡 Colpitts–type Oscillator","title":"🟡 Colpitts–type Oscillator","text":"[Lamour]: Lamour, René, Roswitha März, and Renate Winkler. “How Floquet Theory Applies to Index 1 Differential Algebraic Equations.” Journal of Mathematical Analysis and Applications 217, no. 2 (January 1998): 372–94. https://doi.org/10.1006/jmaa.1997.5714.","category":"page"},{"location":"constrainedproblem/#Constrained-problems","page":"Constrained problems","title":"Constrained problems","text":"","category":"section"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"compat: Experimental\nThis feature is still experimental. It has not been tested thoroughly and may not work, especially the case of multiple constraints and matrix-free functionals.","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"This section is dedicated to the study of an equation (in x) F(x,p)=0 where one wishes to add a constraint g(x,p)=0. Hence, one is interested in solving in the couple (xp):","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"left\nbeginarrayl\nF(xp)=0 \ng(xp)=0\nendarrayright","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"There are several situations where this proves useful:","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"the pseudo-arclength continuation method is such a constrained problem, see continuation for more details.\nwhen the equation F(x) has a continuous symmetry described by a Lie group G and action gcdot x for gin G. One can reduce the symmetry of the problem by considering the constrained problem:","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"left\nbeginarrayl\nF(x) + pcdot Tcdot x=0 \nlangle Tcdot x_refx-x_refrangle=0\nendarrayright","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"where T is a generator of the Lie algebra associated to G and x_ref is a reference solution. This is known as the freezing method.","category":"page"},{"location":"constrainedproblem/","page":"Constrained problems","title":"Constrained problems","text":"unknown: Reference\nSee Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation. for more information on the freezing method.","category":"page"},{"location":"gettingstarted/#Getting-Started-with-BifurcationKit","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"This tutorial will introduce you to the functionality for computing bifurcation diagrams and follow branch of solutions.","category":"page"},{"location":"gettingstarted/#Example-1:-solving-the-perturbed-pitchfork-equation","page":"Getting Started with BifurcationKit","title":"Example 1: solving the perturbed pitchfork equation","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In this example, we will solve the equation","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"mu + x-fracx^33=0","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"as function of mu by looking at the solution in connected component of (x_0mu_0)approx(-2-1). Here uinmathbb R is the state variable and mu is our parameter. The general workflow is to define a problem, solve the problem, and then analyze the solution. The full code for solving this problem is:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using BifurcationKit, Plots\nF(x, p) = @. p.μ + x - x^3/3\nprob = BifurcationProblem(F, [-2.], (μ = -1.,), (@lens _.μ);\n record_from_solution = (x,p) -> (x = x[1]))\nopts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(), opts)\nplot(br)\nscene = plot(br) #hide","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"where the pieces are described below.","category":"page"},{"location":"gettingstarted/#Step-1:-Defining-a-Problem","page":"Getting Started with BifurcationKit","title":"Step 1: Defining a Problem","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"To solve this numerically, we define a problem type by giving it the equation, the initial condition, the parameters and the parameter axis to solve over:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using BifurcationKit\nF(x, p) = @. p.μ + x - x^3/3\nprob = BifurcationProblem(F, [-2.], (μ = -1.,), (@lens _.μ);\n record_from_solution = (x,p) -> (x = x[1]))","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Note that BifurcationKit.jl will choose the types for the problem based on the types used to define the problem type. For our example, notice that u0 is a Vector{Float64}, and therefore this will solve with the dependent variables being Vector{Float64}. You can use this to choose to solve with Float32 for example to run this on the GPU (see example).","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"You can customize a few scalar indicators for each step (for example if you don't want to save all solutions) by providing a function record_from_solution. You can also control how the solution is plotted during a continuation run by providing a function plot_solution. This is especially useful when studying PDE for example.","category":"page"},{"location":"gettingstarted/#Step-2:-Solving-a-Problem","page":"Getting Started with BifurcationKit","title":"Step 2: Solving a Problem","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"After defining a problem, you \"solve\" it using continuation.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(), opts)\nnothing #hide","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The solvers can be controlled using the available options ContinuationPar. For example, we can increase the maximum continuation step (in order to get a less points) by using the command dsmax = 0.25","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using Plots\nopts = ContinuationPar(p_min = -1., p_max = 1., dsmax = 0.25, max_steps = 1000)\nbr = continuation(prob, PALC(), opts)\nscene = plot(br)","category":"page"},{"location":"gettingstarted/#Choosing-a-continuation-Algorithm","page":"Getting Started with BifurcationKit","title":"Choosing a continuation Algorithm","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"BifurcationKit.jl offers a much wider variety of continuation algorithms than traditional continuation softwares. Many of these algorithms are from recent research and have their own strengths and weaknesses. Each algoritm comes with a doc string, for example:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"? PALC","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"For example, you can chose a different tangent predictor in PALC","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(tangent = Bordered()), opts)\nscene = plot(br)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"or you can use the Moore-Penrose continuation algorithm","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar(p_min = -1., p_max = 1.)\nbr = continuation(prob, MoorePenrose(), opts)\nscene = plot(br)","category":"page"},{"location":"gettingstarted/#Step-3:-Analyzing-the-Solution","page":"Getting Started with BifurcationKit","title":"Step 3: Analyzing the Solution","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The result of continuation is a solution object. A summary of the result is provided by the show method:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"show(br) # this is equivalent to the REPL julia> br","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"From there, you can see that the branch has 55 points, the algorithm is also recalled because it can be modified internally. This summary shows that two bifurcation points where detected. At each such point, the couple δ indicates how many real/complex eigenvalues crossed the imaginary axis. This is useful for debugging or when non generic bifurcations are encountered.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"We can access the 5th value of the branch with:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br[5]","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The solution contains many other fields:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"propertynames(br)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Hence, the eigenelements are saved in br.eig, the solutions are saved in br.sol and the bifurcation points in br.specialpoint.","category":"page"},{"location":"gettingstarted/#Plotting-branches","page":"Getting Started with BifurcationKit","title":"Plotting branches","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"While one can directly plot solution time points using the tools given above, convenience commands are defined by recipes for Plots.jl. To plot the solution object, simply call plot:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"#]add Plots # You need to install Plots.jl before your first time using it!\nusing Plots\n#plotly() # You can optionally choose a plotting backend\nplot(br)\nscene = plot(br) #hide","category":"page"},{"location":"gettingstarted/#Example-2:-simple-branching","page":"Getting Started with BifurcationKit","title":"Example 2: simple branching","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In this example, we will solve the equation","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"0 = xcdot(mu-x)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"as function of mu. Here uinmathbb R is the state variable and mu is our parameter.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In our example, we know by calculus that the solutions to this equation are u_0(mu)=0 and u_1(mu)=mu but we will use BifurcationKit.jl to solve this problem numerically, which is essential for problems where a symbolic solution is not known.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In case we know there are many branches, the best is to use an automatic method to compute them all. We will focus on bifurcationdiagram which computes the connected component of the initial guess in the plane (xmu). An alternative is to use Deflated Continuation.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"We define a problem type by giving it the equation, the initial condition, the parameters and the parameter axis to solve over:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using Plots\nusing BifurcationKit\n\nFbp(u, p) = @. u * (p.μ - u)\n\n# bifurcation problem\nprob = BifurcationProblem(Fbp, [0.0], (μ = -0.2,),\n\t# specify the continuation parameter\n\t(@lens _.μ), \n\trecord_from_solution = (x, p) -> x[1])","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"We then aim at calling bifurcationdiagram which will do the jobs of computing recursively the branches which are connected together. Compared to continuation, bifurcationdiagram requires the maximal level of recursion (in this case 2 because there are 2 branches) and a function providing the continuation parameters for each branch (which may differ from branch to branch if the user decides). This explains the following code: ","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"# options for continuation\nopts_br = ContinuationPar(\n\t# parameter interval\n\tp_max = 0.2, p_min = -0.2,\n\t# detect bifurcations with bisection method\n\t# we increase the precision of the bisection\n\tn_inversion = 4)\n\n# automatic bifurcation diagram computation\ndiagram = bifurcationdiagram(prob, PALC(),\n\t# very important parameter. This specifies the maximum amount of recursion\n\t# when computing the bifurcation diagram. It means we allow computing branches of branches\n\t# at most in the present case.\n\t2,\n\t(args...) -> opts_br,\n\t)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"You can plot the diagram like","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"plot(diagram)","category":"page"},{"location":"gettingstarted/#gt-hopf","page":"Getting Started with BifurcationKit","title":"Example 3: continuing periodic orbits","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In this example, we will compute periodic orbits of the Stuart-Landau oscillator:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"beginaligned\nfracdudt = r u - nu v - (u^2+v^2) (c_3 u - mu v) \nfracdvdt = r v + nu u - (u^2+v^2) (c_3 + mu u)\nendaligned","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The ODE is easily written with a function:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"using BifurcationKit, Parameters, Plots\n\nfunction Fsl(X, p)\n @unpack r, μ, ν, c3 = p\n u, v = X\n\n ua = u^2 + v^2\n\n [\n r * u - ν * v - ua * (c3 * u - μ * v)\n r * v + ν * u - ua * (c3 * v + μ * u)\n ]\nend","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"and then we can use this to define a bifurcation problem:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"par_sl = (r = 0.1, μ = 0., ν = 1.0, c3 = 1.0)\nu0 = zeros(2)\nprob = BifurcationProblem(Fsl, u0, par_sl, (@lens _.r))","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"For this simple problem, we detect the existence of periodic orbits by locating a Hopf bifurcation. This is done as in the previous example by continuing the zero solution:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"opts = ContinuationPar()\nbr = continuation(prob, PALC(), opts, bothside = true)","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Having found a Hopf bifurcation, we compute the branch of periodic orbits which is nearby. Thus, we provide the branch br, the index of the special point we want to branch from: 2 in this case and a method PeriodicOrbitOCollProblem(20, 5) to compute periodic orbits. You can look at Periodic orbits computation for a list of all methods. Suffice it to say that PeriodicOrbitOCollProblem is the default method in the case of ODEs.","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po = continuation(br, 2, opts,\n PeriodicOrbitOCollProblem(20, 5)\n )","category":"page"},{"location":"gettingstarted/#Analyzing-the-Solution","page":"Getting Started with BifurcationKit","title":"Analyzing the Solution","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"The branch of periodic orbits has been computed. You can look at what is recorded in the first point on the branch:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po[1]","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"It shows that the maximum/minimum/amplitude/period of the periodic orbit are recorded by default. You can also plot all the branches as follows","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"plot(br, br_po, branchlabel = [\"equilibria\", \"periodic orbits\"])","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"Finally, if you are interested in the periodic orbits saved in br_po, for example to plot it, the method get_periodic_orbit is what you are looking for:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"sol = get_periodic_orbit(br_po, 10)\nplot(sol.t, sol[1,:], label = \"u\", xlabel = \"time\")\nplot!(sol.t, sol[2,:], label = \"v\", xlabel = \"time\")","category":"page"},{"location":"gettingstarted/#Plotting-the-periodic-orbit-during-continuation","page":"Getting Started with BifurcationKit","title":"Plotting the periodic orbit during continuation","text":"","category":"section"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"If you plot the solution during continuation, you see that the right bottom panel is empty ; this panel is used to plot the solution at the current continuation step:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po = continuation(br, 2, opts,\n PeriodicOrbitOCollProblem(20, 5);\n plot = true,\n )\nscene = title!(\"\") #hide","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"(Note that the bottom panel is a plot of the eigenvalues of the jacobian in the complex plane at the current continuation step. )","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"In order to plot the periodic solution during continuation, you need to supply a periodic_solution to continuation. This is not done by default because in some cases, obtaining the solution is costly (e.g. for Shooting methods). Based on the previous paragraph, it is straightforward to implement this plotting function:","category":"page"},{"location":"gettingstarted/","page":"Getting Started with BifurcationKit","title":"Getting Started with BifurcationKit","text":"br_po = continuation(br, 2, opts,\n PeriodicOrbitOCollProblem(20, 5);\n plot = true,\n plot_solution = (x, par; k...) -> begin\n # par is a Named tuple which contains \n # the problem for computing periodic orbits\n # and the value of the parameter at the current step\n sol = get_periodic_orbit(par.prob, x, par.p)\n plot!(sol.t, sol.u'; xlabel = \"time\", label=\"\", k...)\n end\n )\nscene = title!(\"\") #hide","category":"page"},{"location":"interfaceFlow/#Interface-for-Flow-of-Cauchy-problem","page":"Flow","title":"Interface for Flow of Cauchy problem","text":"","category":"section"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"Here is a description of the interface that is used to specify flows or semigroups of solutions of a Cauchy problem fracdudt = F(u p)quad u(0) = u_0","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"More precisely, we call flow the mapping Flow(x p t) = u(t).","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"The flow fl must be a subtype of the abstract type AbstractFlow. Note that in most cases, we only need u(t). However, for plotting, we need optionally the full trajectory with time stamps in 0T.","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"Another point is the need for implementing serial versions of multithreaded flows.","category":"page"},{"location":"interfaceFlow/","page":"Flow","title":"Flow","text":"Required methods Brief description\nvf(fl, x, p) The vector field F(x, p) associated to a Cauchy problem. Used for the differential of the shooting problem. Must return F(x, p)\nevolve(fl, x, par, t; k...) the function implements the flow (or semigroup) (x, p, t) -> flow(x, p, t) associated to an autonomous Cauchy problem. Only the last time point must be returned in the form Named Tuple (u = ..., t = t). In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, x, par, Inf).\nOptional methods Brief description\nevolve(fl, x, par, t; k...) Same as above but for t::AbstractVector of some length M and x a matrix of size N x M. In this case, you are asked to compute several flows flow(x[:, i],p,t[i]). This can be done in parallel.\nevolve(fl, x, par, dx, t; k...) The differential dflow of the flow w.r.t. x, (x, p, dx, t) -> dflow(x, p, dx, t). One important thing is that we require dflow(x, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = dflow(x, p, dx, t)), the last component being the value of the derivative of the flow.\nevolve(fl, ::Val{:Full}, x, par, t; k...) The function implements the flow (or semigroup) associated to an autonomous Cauchy problem (x, p, t) -> flow(x, p, t). The whole solution on the time interval [0,t] must be returned. It is not strictly necessary to provide this, it is mainly used for plotting on the user side. In the case of Poincaré Shooting, one must be able to call the flow like evolve(fl, Val(:Full), x, par, Inf).\nevolve(fl, ::Val{:SerialTimeSol}, x, par, t; k...) Serial version of the flow. Used for Matrix based jacobian (Shooting and Poincaré Shooting) and diffPoincareMap\nevolve(fl, ::Val{:TimeSol}, x, par, t = Inf; k...) Flow which returns the tuple (t, u(t)). Optional, mainly used for plotting on the user side.\nevolve(fl, ::Val{:SerialdFlow}, x, par, dx, t; k...) Serial version of dflow. Used internally when using parallel multiple shooting. Named Tuple (u = ..., du = ..., t = t).","category":"page"},{"location":"tutorials/tutorialsCGLShoot/#cglshoot","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"","category":"section"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"Pages = [\"tutorialsCGLShoot.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"In this tutorial, we re-visit the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS) using a Standard Simple Shooting method. In the tutorial 1d Brusselator (advanced user), we used the implicit solver Rodas4P for the shooting. We will use the exponential-RK scheme ETDRK2 ODE solver to compute the solution of cGL equations. This method is convenient for solving semilinear problems of the form","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"dot x = Ax+g(x)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"where A is the infinitesimal generator of a C_0-semigroup. We use the same beginning as in 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS):","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"using Revise\n\tusing DiffEqOperators, DifferentialEquations\n\tusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\n\tconst BK = BifurcationKit\n\nfunction Laplacian2D(Nx, Ny, lx, ly)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Dirichlet0BC(typeof(hx))\n\tQy = Dirichlet0BC(typeof(hy))\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A, D2x\nend","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We then encode the PDE:","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"function NL!(f, u, p, t = 0.)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@. f1 .= r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1\n\t@. f2 .= r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\n\treturn f\nend\n\nfunction Fcgl!(f, u, p, t = 0.)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\nend\n\nNL(u, p) = NL!(similar(u), u, p)\nFcgl(u, p, t = 0.) = Fcgl!(similar(u), u, p, t)\n\nfunction Jcgl(u, p, t = 0.)\n\t@unpack r, μ, ν, c3, c5, Δ = p\n\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1u = zero(u1)\n\tf2u = zero(u1)\n\tf1v = zero(u1)\n\tf2v = zero(u1)\n\n\t@. f1u = r - 2 * u1 * (c3 * u1 - μ * u2) - c3 * ua - 4 * c5 * ua * u1^2 - c5 * ua^2\n\t@. f1v = -ν - 2 * u2 * (c3 * u1 - μ * u2) + μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2u = ν - 2 * u1 * (c3 * u2 + μ * u1) - μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2v = r - 2 * u2 * (c3 * u2 + μ * u1) - c3 * ua - 4 * c5 * ua * u2 ^2 - c5 * ua^2\n\n\tjacdiag = vcat(f1u, f2v)\n\n\tΔ + spdiagm(0 => jacdiag, n => f1v, -n => f2u)\nend","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"with parameters","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"Nx = 41\nNy = 21\nn = Nx*Ny\nlx = pi\nly = pi/2\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)[1]\npar_cgl = (r = 0.5, μ = 0.1, ν = 1.0, c3 = -1.0, c5 = 1.0, Δ = blockdiag(Δ, Δ))\nsol0 = 0.1rand(2Nx, Ny)\nsol0_f = vec(sol0)\n\nprob = BK.BifurcationProblem(Fcgl, sol0_f, par_cgl, (@lens _.r); J = Jcgl)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"and the ODE problem","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"f1 = DiffEqArrayOperator(par_cgl.Δ)\nf2 = NL!\nprob_sp = SplitODEProblem(f1, f2, sol0_f, (0.0, 120.0), (@set par_cgl.r = 1.2), dt = 0.1)\n# we solve the PDE!!!\nsol = @time solve(prob_sp, ETDRK2(krylov=true); abstol=1e-14, reltol=1e-14)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/#Automatic-branch-switching-from-the-Hopf-points","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"Automatic branch switching from the Hopf points","text":"","category":"section"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We show how to use automatic branch switching from the Hopf points computed in the previous section. To compute the periodic orbits, we use a Standard Shooting method.","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We first recompute the Hopf points as in the previous tutorial:","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"eigls = EigArpack(1.0, :LM)\nopt_newton = NewtonPar(tol = 1e-9, verbose = true, eigsolver = eigls, max_iterations = 20)\nopts_br = ContinuationPar(dsmax = 0.02, ds = 0.01, p_max = 2., detect_bifurcation = 3, nev = 15, newton_options = (@set opt_newton.verbose = false), n_inversion = 4)\n\nbr = @time continuation(prob, PALC(), opts_br, verbosity = 0)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We then compute the differentials of the vector field, this is needed by the branch switching method because it first computes the Hopf normal form. Thankfully, this is little work using Automatic Differentiation.","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We define the linear solvers to be use by the (Matrix-Free) shooting method","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"ls = GMRESIterativeSolvers(reltol = 1e-4, maxiter = 50, verbose = false)\neig = EigKrylovKit(tol = 1e-7, x₀ = rand(2Nx*Ny), verbose = 2, dim = 40)\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 25, linsolver = ls, eigsolver = eig)\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.02, ds= 0.01, p_max = 2.5, max_steps = 32, newton_options = optn, nev = 7, tol_stability = 1e-3, detect_bifurcation = 3, plot_every_step = 1)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"as","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"Mt = 1 # number of time sections\nbr_po = continuation(\n\t# we want to compute the bifurcated branch from\n\t# the first Hopf point\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n\t# this is how to pass the method to compute the periodic\n\t# orbits. We shall use 1 section and the ODE solver ETDRK2\n\tShootingProblem(Mt, prob_sp, ETDRK2(krylov = true); abstol = 1e-10, reltol = 1e-8, jacobian = BK.FiniteDifferencesMF()) ;\n\t# linear solver for bordered linear system\n\t# we combine the 2 solves. It is here faster than BorderingBLS()\n\tlinear_algo = MatrixFreeBLS(@set ls.N = Mt*2n+2),\n\t# to help branching from the Hopf point\n\tampfactor = 1.5, δp = 0.01,\n\t# regular parameters for the continuation\n\tverbosity = 3, plot = true,\n\t# a few parameters saved during run\n\trecord_from_solution = (u, p) -> (amp = BK.getamplitude(p.prob, u, (@set par_cgl.r = p.p)), period = u[end]),\n\t# plotting of a section\n\tplot_solution = (x, p; k...) -> heatmap!(reshape(x[1:Nx*Ny], Nx, Ny); color=:viridis, k...),\n\t# print the Floquet exponent\n\tfinalise_solution = (z, tau, step, contResult; k...) ->\n\t\t(Base.display(contResult.eig[end].eigenvals) ;true),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGLShoot/#Manual-branch-switching-from-the-Hopf-points","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"Manual branch switching from the Hopf points","text":"","category":"section"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"The goal of this section is to show how to use the package in case automatic branch switching fails. This can happen for tedious PDEs and \"one has to get his hands dirty\".","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We decide to use Standard Shooting and thus define a Shooting functional","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"probSh = ShootingProblem(\n\t# we pass the ODEProblem encoding the flow and the time stepper\n\tremake(prob_sp, p = (@set par_cgl.r = 1.2)), ETDRK2(krylov = true),\n\n\t# this is the phase condition\n\t[sol[:, end]];\n\n\t# parameter axis\n\tlens = (@lens _.r),\n\n\t# jacobian of the periodic orbit functional\n\tjacobian = BK.FiniteDifferencesMF(),\n\n\t# these are options passed to the ODE time stepper\n\tabstol = 1e-14, reltol = 1e-14)","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"We use the solution from the ODE solver as a starting guess for the shooting method.","category":"page"},{"location":"tutorials/tutorialsCGLShoot/","page":"🟢 2d Ginzburg-Landau equation (Shooting)","title":"🟢 2d Ginzburg-Landau equation (Shooting)","text":"# initial guess with period 6.9 using solution at time t = 116\ninitpo = vcat(sol(116.), 6.9) |> vec\n\n# linear solver for shooting functional\nls = GMRESIterativeSolvers(reltol = 1e-4, N = 2Nx * Ny + 1, maxiter = 50, verbose = false)\n\n# newton parameters\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 20, linsolver = ls)\n\n# continuation parameters\neig = EigKrylovKit(tol=1e-7, x₀ = rand(2Nx*Ny), verbose = 2, dim = 40)\nopts_po_cont = ContinuationPar(dsmin = 0.001,\n\t\t\t\tdsmax = 0.01,\n\t\t\t\tds = -0.01,\n\t\t\t\tp_max = 1.5,\n\t\t\t\tmax_steps = 60,\n\t\t\t\tnewton_options = (@set optn.eigsolver = eig),\n\t\t\t\tnev = 5,\n\t\t\t\ttol_stability = 1e-3,\n\t\t\t\tdetect_bifurcation = 0)\n\nbr_po = @time continuation(probSh,\n\tinitpo, PALC(), opts_po_cont;\n\tverbosity = 3, plot = true,\n\tlinear_algo = MatrixFreeBLS(@set ls.N = probSh.M*2n+2),\n\tplot_solution = (x, p; kwargs...) -> heatmap!(reshape(x[1:Nx*Ny], Nx, Ny); color=:viridis, kwargs...),\n\trecord_from_solution = (u, p) -> BK.getamplitude(probSh, u, (@set par_cgl.r = p.p); ratio = 2), normC = norminf)","category":"page"},{"location":"deflatedproblem/#Deflated-problems","page":"Deflated problems","title":"Deflated problems","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"unknown: References\nP. E. Farrell, A. Birkisson, and S. W. Funke. Deflation techniques for finding distinct solutions of nonlinear partial differential equations. SIAM J. Sci. Comput., 2015.,","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Assume you want to solve F(x)=0 with a Newton algorithm but you want to avoid the algorithm to return some already known solutions x_i i=1cdots n.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"The idea proposed in the paper quoted above is to penalize these solutions by looking for the zeros of the function G(x)=F(x)M(x) where","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"M(x) = prod_i=1^nleft(x - x_i^-2p + alpharight)","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"and alpha0. Obviously F and G have the same zeros away from the x_is but the factor M penalizes the residual of the Newton iterations of G, effectively producing zeros of F different from x_i.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"tip: Tip\nIn some case, you may want to use a custom distance, in place of the squared norm cdot^2. Please see DeflationOperator for how to do this.","category":"page"},{"location":"deflatedproblem/#Encoding-of-the-functional","page":"Deflated problems","title":"Encoding of the functional","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"A composite type DeflationOperator implements this functional. Given a deflation operator M = DeflationOperator(p, dot, α, xis), you can build a deflated functional pb = DeflatedProblem(F, J, M) which you can use to access the values of G by doing pb(x). A Matrix-Free / Sparse linear solver is implemented which works on the GPU.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"the dot argument in DeflationOperator lets you specify a dot product from which the norm is derived in the expression of M.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"See example Snaking computed with deflation.","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Note that you can add new solution x0 to M by doing push!(M, x0). Also M[i] returns xi.","category":"page"},{"location":"deflatedproblem/#Computation-with-newton","page":"Deflated problems","title":"Computation with newton","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Most newton functions can be used with a deflated problem, see for example Snaking computed with deflation. The idea is to pass the deflation operator M. For example, we have the following overloaded method, which works on GPUs:","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"newton(prob::BifurcationKit.AbstractBifurcationProblem,\n\t\tdefOp::DeflationOperator,\n\t\toptions::NewtonPar,\n\t\t_linsolver = DefProbCustomLinearSolver();\n\t\tkwargs...)","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"We refer to the regular newton for more information. This newton penalises the roots saved in defOp.roots. ","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"Compared to newton, the only different arguments are","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"defOp::DeflationOperator deflation operator\nlinsolver linear solver used to invert the Jacobian of the deflated functional.\ncustom solver DefProbCustomLinearSolver() with requires solving two linear systems J⋅x = rhs.\nFor other linear solvers <: AbstractLinearSolver, a matrix free method is used for the deflated functional.\nif passed Val(:autodiff), then ForwardDiff.jl is used to compute the jacobian of the deflated problem\nif passed Val{:fullIterative}, then a full matrix free method is used.","category":"page"},{"location":"deflatedproblem/#Simple-example","page":"Deflated problems","title":"Simple example","text":"","category":"section"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"In this basic example, we show how to get the different roots of F","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"using BifurcationKit, LinearAlgebra\nF(x, p) = @. (x-1) * (x-2)\n# define a deflation operator which deflates the \n# already know solution x = 1\ndeflationOp = DeflationOperator(2, dot, 0.1, [ones(1)])\n# define a problem, this compute jacobian automatically\nprob = BifurcationProblem(F, rand(1), nothing)\n# call deflated newton\nsol = newton(prob, deflationOp, NewtonPar())\nprintln(\"We found the additional root: \", sol.u)","category":"page"},{"location":"deflatedproblem/","page":"Deflated problems","title":"Deflated problems","text":"tip: Tip\nYou can use this method for periodic orbits as well by passing the deflation operator M to the newton method","category":"page"},{"location":"tutorials/ode/tutorialCO/#CO-oxidation-(codim-2)","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"Pages = [\"tutorialCO.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"In this tutorial, we study the Bykov–Yablonskii–Kim model of CO oxidation (see [Govaerts]). The goal of the tutorial is to show a simple example of how to perform codimension 2 bifurcation detection.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"leftbeginarrayldotx=2 q_1 z^2-2 q_5 x^2-q_3 x y doty=q_2 z-q_6 y-q_3 x y dots=q_4 z-k q_4 sendarrayrighttagE","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"where z=1-x-y-s.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We start with some imports:","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nnothing # hide","category":"page"},{"location":"tutorials/ode/tutorialCO/#Problem-setting","page":"🟡 CO oxidation (codim 2)","title":"Problem setting","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We can now encode the vector field (E) in a function and use automatic differentiation to compute its various derivatives.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"# vector field of the problem\nfunction COm(u, p)\n\t@unpack q1,q2,q3,q4,q5,q6,k = p\n\tx, y, s = u\n\tz = 1-x-y-s\n\tout = similar(u)\n\tout[1] = 2q1 * z^2 - 2q5 * x^2 - q3 * x * y\n\tout[2] = q2 * z - q6 * y - q3 * x * y\n\tout[3] = q4 * z - k * q4 * s\n\tout\nend\n\n# parameters used in the model\npar_com = (q1 = 2.5, q2 = 0.6, q3 = 10., q4 = 0.0675, q5 = 1., q6 = 0.1, k = 0.4)\n\nrecordCO(x, p) = (x = x[1], y = x[2], s = x[3])\n\n# initial condition\nz0 = [0.07, 0.2, 05]\n\n# Bifurcation Problem\nprob = BifurcationProblem(COm, z0, par_com, (@lens _.q2); record_from_solution = recordCO)\nnothing # hide","category":"page"},{"location":"tutorials/ode/tutorialCO/#Continuation-and-codim-1-bifurcations","page":"🟡 CO oxidation (codim 2)","title":"Continuation and codim 1 bifurcations","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"Once the problem is set up, we can continue the state w.r.t. q_2 and detect codim 1 bifurcations. This is achieved as follows:","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"# continuation parameters\nopts_br = ContinuationPar(p_min = 0., p_max = 1.9, ds = 0.002, dsmax = 0.01)\n\n# compute the branch of solutions\nbr = continuation(prob, PALC(), opts_br; plot = true, verbosity = 2, normC = norminf)","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"# plot the branch\nscene = plot(br, xlims = (0.8,1.8))","category":"page"},{"location":"tutorials/ode/tutorialCO/#Continuation-of-Fold-points","page":"🟡 CO oxidation (codim 2)","title":"Continuation of Fold points","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We follow the Fold points in the parameter plane (q_2 k). We tell the solver to consider br.specialpoint[2] and continue it.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"sn_codim2 = continuation(br, 2, (@lens _.k),\n\tContinuationPar(opts_br, p_max = 2.2, ds = -0.001, dsmax = 0.05);\n\tnormC = norminf,\n\t# detection of codim 2 bifurcations\n\tdetect_codim2_bifurcation = 2,\n\t# update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# compute both sides of the initial condition\n\tbothside = true,)\n\nscene = plot(sn_codim2, vars = (:q2, :x), branchlabel = \"Fold\")\nplot!(scene, br, xlims=(0.8, 1.8))","category":"page"},{"location":"tutorials/ode/tutorialCO/#Continuation-of-Hopf-points","page":"🟡 CO oxidation (codim 2)","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"We tell the solver to consider br.specialpoint[1] and continue it.","category":"page"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"hp_codim2 = continuation(br, 1, (@lens _.k),\n\tContinuationPar(opts_br, p_max = 2.8, ds = -0.001, dsmax = 0.05) ;\n\tnormC = norminf,\n\t# detection of codim 2 bifurcations\n\tdetect_codim2_bifurcation = 2,\n\t# tell to start the Hopf problem using eigen elements: compute left eigenvector\n\t#start_with_eigen = true,\n\t# we update the Hopf problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# compute both sides of the initial condition\n\tbothside = true,\n\t)\n\n# plotting\nscene = plot(sn_codim2, vars = (:q2, :x), branchlabel = \"Fold\")\nplot!(scene, hp_codim2, vars = (:q2, :x), branchlabel = \"Hopf\")\nplot!(scene, br, xlims = (0.6, 1.5))","category":"page"},{"location":"tutorials/ode/tutorialCO/#References","page":"🟡 CO oxidation (codim 2)","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialCO/","page":"🟡 CO oxidation (codim 2)","title":"🟡 CO oxidation (codim 2)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"tutorials/cgl1dwave/#1d-Ginzburg-Landau-equation-(TW)","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"","category":"section"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"Pages = [\"cgl1dwave.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We look at the Ginzburg-Landau equations in 1d with periodic boundary condition. The goal of this tutorial is to show how one can study a Hopf bifurcation with symmetry group O(2). It is known that this bifurcation supports standing / travelling waves. Using the tools for periodic orbits, it is easy to compute the standing wave. We thus focus on the computation of the travelling wave.","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"The equations are as follows","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"partial_t u=Delta u+(r+mathrmi v) u-left(c_3+mathrmi muright)u^2 u-c_5u^4 u quad u=u(t x) in mathbbC","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"with periodic boundary conditions. We discretize the circle Omega = (-pipi) with n points. We start by writing the Laplacian:","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\nconst FD = ForwardDiff\n\n# plotting utilities\nplotsol!(x, m, n; np = n, k...) = heatmap!(reshape(x[1:end-1],m,n)[1:np,:]; color = :viridis, k...)\ncontoursol!(x, m, n; np = n, k...) = contour!(reshape(x[1:end-1],m,n)[1:np,:]; color = :viridis, k...)\nplotsol(x,m,n;k...) = (plot();plotsol!(x,m,n;k...))\n\nfunction Laplacian1D(Nx, lx)\n\thx = 2lx/Nx\n\tT = typeof(hx)\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD1x = CenteredDifference(1, 2, hx, Nx)\n\tQx = PeriodicBC(T)\n\n\tΔ = sparse(D2x * Qx)[1] |> sparse\n\tD = sparse(D1x * Qx)[1] |> sparse\n\treturn Δ, D\nend\n\n# add the nonlinearity to f\n@views function NL!(f, u, p)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1 = u[1:n]\n\tu2 = u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1 = f[1:n]\n\tf2 = f[n+1:2n]\n\n\tf1 .+= @. r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1\n\tf2 .+= @. r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\n\treturn f\nend\n\n# full functional\nfunction Fcgl!(f, u, p, t = 0)\n\tmul!(f, p.Δ, u)\n\tNL!(f, u, p)\nend\nFcgl(u, p, t = 0) = Fcgl!(similar(u), u, p)\n\n# analytical expression off the jacobian\n@views function Jcgl(u, p)\n\t@unpack r, μ, ν, c3, c5, Δ = p\n\n\tn = div(length(u), 2)\n\tu1 = u[1:n]\n\tu2 = u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1u = zero(u1)\n\tf2u = zero(u1)\n\tf1v = zero(u1)\n\tf2v = zero(u1)\n\n\t@. f1u = r - 2 * u1 * (c3 * u1 - μ * u2) - c3 * ua - 4 * c5 * ua * u1^2 - c5 * ua^2\n\t@. f1v = -ν - 2 * u2 * (c3 * u1 - μ * u2) + μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2u = ν - 2 * u1 * (c3 * u2 + μ * u1) - μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2v = r - 2 * u2 * (c3 * u2 + μ * u1) - c3 * ua - 4 * c5 * ua * u2 ^2 - c5 * ua^2\n\n\tjacdiag = vcat(f1u, f2v)\n\n\tΔ + spdiagm(0 => jacdiag, n => f1v, -n => f2u)\nend\n\nnothing #hide","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We then define a problem for computing the bifurcations of the trivial state u=0 as function of r.","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"# space discretization\nn = 50\n\nl = pi\nΔ, D = Laplacian1D(n, l)\n\n# model parameters\npar_cgl = (r = 0.0, μ = 0.5, ν = 1.0, c3 = -1.0, c5 = 1.0, Δ = blockdiag(Δ, Δ), Db = blockdiag(D, D), δ = 1.0, N = 2n)\n\n# initial guess\nsol0 = zeros(par_cgl.N)\n\n# bifurcation problem\nprob = BifurcationProblem(Fcgl, sol0, par_cgl, (@lens _.r); J = Jcgl)\n\nopt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.15, ds = 0.001, p_max = 2.5,\n\tdetect_bifurcation = 3, nev = 9, newton_options = (@set opt_newton.verbose = false), max_steps = 100, n_inversion = 8, max_bisection_steps = 20)\nbr = continuation(prob, PALC(), opts_br, verbosity = 0)","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"The first bifurcation point is a regular Hopf bifurcation in the zero mode, i.e. u(x t) = u_0cos(omega t +phi) with no spatial structure. The second bifurcation point, labelled nd is a Hopf bifurcation with O(2) symmetry group generated by the translations T_zcdot u(x) = u(x+y) and the reflection Scdot u(x) = u(-x).","category":"page"},{"location":"tutorials/cgl1dwave/#Computation-of-the-travelling-wave","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"Computation of the travelling wave","text":"","category":"section"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We focus on the O(2)-Hopf (second bifurcation point in br), with frequency omega0, for which no normal form is currently implemented in BifurcationKit.jl. We write zeta_0zeta_1 two eigenvectors associated with the eigenvalue iomega such that","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"T_zcdotzeta_0 = e^im zzeta_0quad T_zcdotzeta_1 = e^-im zzeta_1quad Scdotzeta_0 = zeta_1quad Scdotzeta_1 = zeta_0","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"By the center manifold theory[Haragus], one has","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"u = A(t)zeta_0+B(t)zeta_1+overlineA(t)zeta_0+overlineB(t)zeta_1+textsmall terms","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"Using the normal form, one finds standing waves (A(t)B(t)) = (r_0e^iomega t r_0e^iomega t) with r_0geq 0 and travelling waves (A(t)B(t)) = (r_0e^iomega t 0) at first order in AB. This provides us with a way to compute the initial guess for the travelling waves as written in the following function:","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"function guessFromHopfO2(branch, ind_hopf, eigsolver, M, A, B = 0.; phase = 0, k = 1.)\n\tspecialpoint = branch.specialpoint[ind_hopf]\n\n\t# parameter value at the Hopf point\n\tp_hopf = specialpoint.param\n\n\t# frequency at the Hopf point\n\tωH = imag(branch.eig[specialpoint.idx].eigenvals[specialpoint.ind_ev]) |> abs\n\n\t# eigenvectors for the eigenvalues iω\n\tζ0 = geteigenvector(eigsolver, br.eig[specialpoint.idx][2], specialpoint.ind_ev)\n\tζ0 ./= norm(ζ0)\n\n\tζ1 = geteigenvector(eigsolver, br.eig[specialpoint.idx][2], specialpoint.ind_ev - 2)\n\tζ1 ./= norm(ζ1)\n\n\torbitguess = [real.(specialpoint.x .+\n\t \t\t\tA .* ζ0 .* exp(2pi * complex(0, 1) .* (ii/(M-1) - phase)) .+\n\t\t\t\tB .* ζ1 .* exp(2pi * complex(0, 1) .* (ii/(M-1) - phase))) for ii in 0:M-1]\n\n\treturn (; p = p_hopf, period = 2pi/ωH, guess = orbitguess, x0 = specialpoint.x, ζ0 = ζ0, ζ1 = ζ1)\nend\nnothing #hide","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We can use this function to effectively build a guess for the travelling wave:","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"M = 50 # number of time slices (plotting purposes)\nr_hopf, Th, orbitguess2, hopfpt, eigvec = guessFromHopfO2(br, 2, opt_newton.eigsolver, M, 1. + 0.0im, 1+0.0im; k = 2.) #TW\n\nuold = copy(orbitguess2[1][1:2n])\n\n# we create a TW problem\nprobTW = TWProblem(re_make(prob, params = setproperties(par_cgl; r = r_hopf - 0.01)), par_cgl.Db, uold; jacobian = :FullLU)\n\n# refine the guesss\nwave = newton(probTW, vcat(uold, 0),\n\t\tNewtonPar(verbose = true, max_iterations = 50),\n\t)\nprintln(\"norm wave = \", wave.u[1:end-1] |> norminf)\nplot(wave.u[1:end-1]; linewidth = 5, label = \"solution\")\nplot!(uold, color = :blue, label=\"guess\")","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"Note that in the following code, a generalized eigensolver is automatically created during the call to continuation which properly computes the stability of the wave.","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"amplitude(x) = maximum(x) - minimum(x)\noptn = NewtonPar(tol = 1e-8, verbose = true, max_iterations = 10)\nopt_cont_br = ContinuationPar(p_min = 0.015, p_max = 2.5, newton_options = optn, ds= 0.001, dsmax = 0.1, detect_bifurcation = 3, nev = 10, max_steps = 190, n_inversion = 6)\n\nbr_TW = @time continuation(probTW, wave.u, PALC(), opt_cont_br;\n\trecord_from_solution = (x, p) -> (u∞ = maximum(x[1:n]), s = x[end], amp = amplitude(x[1:n])),\n\tplot_solution = (x, p; k...) -> (plot!(x[1:end-1];k...);plot!(br,subplot=1, legend=false)),\n\tfinalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\tamplitude(z.u[n+1:2n]) > 0.01\nend, bothside = true)\n\nplot(br, br_TW, legend = :bottomright, branchlabel =[\"\",\"TW\"])","category":"page"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"We note that the branch of travelling wave solutions has a Hopf bifurcation point at which point Modulated Travelling waves will emerge. This will be analyzed in the future.","category":"page"},{"location":"tutorials/cgl1dwave/#References","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"References","text":"","category":"section"},{"location":"tutorials/cgl1dwave/","page":"🟤 1d Ginzburg-Landau equation (TW)","title":"🟤 1d Ginzburg-Landau equation (TW)","text":"[Haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"tutorials/mittelmannGridap/#2d-Bratu–Gelfand-problem-with-[Gridap.jl](https://github.com/gridap/Gridap.jl)","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"","category":"section"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Pages = [\"mittelmannGridap.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We re-consider the problem of Mittelmann treated in the previous tutorial but using a finite elements method (FEM) implemented in the package Gridap.jl.","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Recall that the problem is defined by solving","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Delta u +NL(lambdau) = 0","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"with Neumann boundary condition on Omega = (01)^2 and where NL(lambdau)equiv-10(u-lambda e^u).","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We start by installing the package GridapBifurcationKit.jl. Then, we can import the different packages:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"using Revise\nusing Plots, Gridap, Setfield\nusing Gridap.FESpaces\nusing GridapBifurcationKit, BifurcationKit\n\n# custom plot function to deal with Gridap\nplotgridap!(x; k...) = (n=isqrt(length(x));heatmap!(reshape(x,n,n); color=:viridis, k...))\nplotgridap(x; k...) =( plot();plotgridap!(x; k...))","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We are now ready to specify the problem using the setting of Gridap.jl: it allows to write the equations very closely to the mathematical formulation:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"# discretisation\nn = 40\ndomain = (0, 1, 0, 1)\ncells = (n,n)\nmodel = CartesianDiscreteModel(domain,cells)\n\n# function spaces\norder = 1\nreffe = ReferenceFE(lagrangian, Float64, order)\nV = TestFESpace(model, reffe, conformity=:H1,)#dirichlet_tags=\"boundary\")\nU = TrialFESpace(V)\n\nΩ = Triangulation(model)\ndegree = 2*order\nconst dΩ = Measure(Ω, degree) # we make it const because it is used in res\n\n# nonlinearity\nNL(u) = exp(u)\n\n# residual\nres(u,p,v) = ∫( -∇(v)⋅∇(u) - v ⋅ (u - p.λ ⋅ (NL ∘ u)) * 10 )*dΩ\n\n# jacobian of the residual\njac(u,p,du,v) = ∫( -∇(v)⋅∇(du) - v ⋅ du ⋅ (1 - p.λ * ( NL ∘ u)) * 10 )*dΩ\n\n# 3rd and 4th derivatives, used for aBS\nd2res(u,p,du1,du2,v) = ∫( v ⋅ du1 ⋅ du2 ⋅ (NL ∘ u) * 10 * p.λ )*dΩ\nd3res(u,p,du1,du2,du3,v) = ∫( v ⋅ du1 ⋅ du2 ⋅ du3 ⋅ (NL ∘ u) * 10 * p.λ )*dΩ\n\n# example of initial guess\nuh = zero(U)\n\n# model parameter\npar_bratu = (λ = 0.01,)\n\n# problem definition\nprob = GridapBifProblem(res, uh, par_bratu, V, U, (@lens _.λ); jac = jac, d2res = d2res, d3res = d3res, plot_solution = (x,p; k...) -> plotgridap!(x; k...))","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We can call then the newton solver:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"optn = NewtonPar(eigsolver = EigArpack())\nsol = newton(prob, NewtonPar(optn; verbose = true))","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"which gives","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 2.4687e-03 │ 0 │\n│ 1 │ 1.2637e-07 │ 1 │\n│ 2 │ 3.3833e-16 │ 1 │\n└─────────────┴──────────────────────┴────────────────┘","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"In the same vein, we can continue this solution as function of lambda:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"opts = ContinuationPar(p_max = 40., p_min = 0.01, ds = 0.01,\n\tmax_steps = 1000, detect_bifurcation = 3, newton_options = optn, nev = 20)\nbr = continuation(prob, PALC(tangent = Bordered()), opts;\n\tplot = true,\n\tverbosity = 0,\n\t)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We obtain:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"julia> br\n ┌─ Number of points: 56\n ├─ Curve of EquilibriumCont\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter λ starts at 0.01, ends at 0.01\n ├─ Algo: PALC\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, bp at λ ≈ +0.36787944 ∈ (+0.36787944, +0.36787944), |δp|=1e-12, [converged], δ = ( 1, 0), step = 13, eigenelements in eig[ 14], ind_ev = 1\n- # 2, nd at λ ≈ +0.27234314 ∈ (+0.27234314, +0.27234328), |δp|=1e-07, [converged], δ = ( 2, 0), step = 21, eigenelements in eig[ 22], ind_ev = 3\n- # 3, bp at λ ≈ +0.15185452 ∈ (+0.15185452, +0.15185495), |δp|=4e-07, [converged], δ = ( 1, 0), step = 29, eigenelements in eig[ 30], ind_ev = 4\n- # 4, nd at λ ≈ +0.03489122 ∈ (+0.03489122, +0.03489170), |δp|=5e-07, [converged], δ = ( 2, 0), step = 44, eigenelements in eig[ 45], ind_ev = 6\n- # 5, nd at λ ≈ +0.01558733 ∈ (+0.01558733, +0.01558744), |δp|=1e-07, [converged], δ = ( 2, 0), step = 51, eigenelements in eig[ 52], ind_ev = 8\n- # 6, endpoint at λ ≈ +0.01000000, step = 55","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannGridap/#Computation-of-the-first-branches","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"Computation of the first branches","text":"","category":"section"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Let us now compute the first branches from the bifurcation points. We start with the one with 1d kernel:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"br1 = continuation(br, 3,\n\tsetproperties(opts; ds = 0.005, dsmax = 0.05, max_steps = 140, detect_bifurcation = 3);\n\tverbosity = 3, plot = true, nev = 10,\n\tusedeflation = true,\n\tcallback_newton = BifurcationKit.cbMaxNorm(100),\n\t)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We also compute the branch from the first bifurcation point on this branch br1:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"br2 = continuation(br1, 3,\n\tsetproperties(opts;ds = 0.005, dsmax = 0.05, max_steps = 140, detect_bifurcation = 3);\n\tverbosity = 0, plot = true, nev = 10,\n\tusedeflation = true,\n\tcallback_newton = BifurcationKit.cbMaxNorm(100),\n\t)\n\nplot(br, br1, br2)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"We get:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"Finally, we compute the branches from the 2d bifurcation point:","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"br3 = continuation(br, 2,\n\tsetproperties(opts; ds = 0.005, dsmax = 0.05, max_steps = 140, detect_bifurcation = 0);\n\tverbosity = 0, plot = true,\n\tusedeflation = true,\n\tverbosedeflation = false,\n\tcallback_newton = BifurcationKit.cbMaxNorm(100),\n\t)\n\nplot(br, br1, br2, br3...)","category":"page"},{"location":"tutorials/mittelmannGridap/","page":"🟡 2d Bratu–Gelfand problem with Gridap.jl","title":"🟡 2d Bratu–Gelfand problem with Gridap.jl","text":"(Image: )","category":"page"},{"location":"BifProblem/#Bifurcation-problems","page":"Bifurcation Problem","title":"Bifurcation problems","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"Pages = [\"BifProblem.md\"]\nDepth = 3","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"The idea behind BifurcationKit is to compute bifurcation diagrams in memory limited environments where the device can barely hold the current continuation state. We thus disable by default saving all solutions along the branch and all eigenvectors (see ContinuationPar to change this behaviour). Still, one needs to save a few solution indicators, like for plotting. This is the reason for the function record_from_solution (see below).","category":"page"},{"location":"BifProblem/#Generic-bifurcation-problem","page":"Bifurcation Problem","title":"Generic bifurcation problem","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"BifurcationProblem is the basic / generic structure for encoding a bifurcation problem ; it holds the following fields:","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"the vector field\nan initial guess\na set of parameters\na parameter axis","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"as well as user defined functions for ","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"plotting, plot_solution\nrecording (record_from_solution) indicators about the solution when this one is too large to be saved at every continuation step.","category":"page"},{"location":"BifProblem/#Example","page":"Bifurcation Problem","title":"Example","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"f(x,p) = @. sin(x * p.a)\nu0 = zeros(100_000_000) \nparams = (a = 1.0, b = 2.0)\n\n# record a few components / indicators about x \nmyRecord(x,p) = (x1 = x[1], max = maximum(x), nrm = norm(x, Inf))\n\nprob = BifurcationProblem(f, u0, p, (@lens _.a);\n\trecord_from_solution = myRecord\n\t)","category":"page"},{"location":"BifProblem/#Problem-modification","page":"Bifurcation Problem","title":"Problem modification","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"In case you want to modify an existing problem, you should use the following method","category":"page"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"re_make(prob::BifurcationKit.AbstractBifurcationProblem;\n\t\tu0 = prob.u0,\n\t\tparams = prob.params,\n\t\tlens::Lens = prob.lens,\n\t\trecord_from_solution = prob.record_from_solution,\n\t\tplot_solution = prob.plot_solution,\n J = missing,\n d2F = missing,\n\t\td3F = missing)","category":"page"},{"location":"BifProblem/#BifurcationKit.re_make-Tuple{BifurcationKit.AbstractBifurcationProblem}","page":"Bifurcation Problem","title":"BifurcationKit.re_make","text":"re_make(\n prob;\n u0,\n params,\n lens,\n record_from_solution,\n plot_solution,\n J,\n Jᵗ,\n d2F,\n d3F\n)\n\n\nThis function changes the fields of a problem ::AbstractBifurcationProblem. For example, you can change the initial condition by doing\n\nre_make(prob; u0 = new_u0)\n\n\n\n\n\n","category":"method"},{"location":"BifProblem/#Example-2","page":"Bifurcation Problem","title":"Example","text":"","category":"section"},{"location":"BifProblem/","page":"Bifurcation Problem","title":"Bifurcation Problem","text":"using BifurcationKit, Setfield\nF(x,p) = @. p.a + x^2\n# parameters\npar = (a = 0., b = 2)\nprob = BifurcationProblem(F, zeros(3), par, (@lens _.a))\n# change u0\nprob2 = BifurcationKit.re_make(prob, u0 = rand(3))","category":"page"},{"location":"tutorials/ode/tutorialsODE/#nmepo","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"Pages = [\"tutorialsODE.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"The following model is taken from [Cortes]:","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"leftbeginarrayl\ntau dotE=-E+gleft(J u x E+E_0right) \ndotx=tau_D^-1(1-x)-u E x \ndotu=U E(1-u)-tau_F^-1(u-U)\nendarrayright","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We use this model as a mean to introduce the basics of BifurcationKit.jl, namely the continuation of equilibria and periodic orbits (with the different methods).","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"The model is interesting on its own because the branch of periodic solutions converges to an homoclinic orbit which can be challenging to compute. We provide three different ways to compute these periodic orbits and highlight their pro / cons.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# vector field\nfunction TMvf!(dz, z, p, t = 0)\n\t@unpack J, α, E0, τ, τD, τF, U0 = p\n\tE, x, u = z\n\tSS0 = J * u * x * E + E0\n\tSS1 = α * log(1 + exp(SS0 / α))\n\tdz[1] = (-E + SS1) / τ\n\tdz[2] =\t(1.0 - x) / τD - u * x * E\n\tdz[3] = (U0 - u) / τF + U0 * (1.0 - u) * E\n\tdz\nend\n\n# parameter values\npar_tm = (α = 1.4, τ = 0.013, J = 3.07, E0 = -2.0, τD = 0.20, U0 = 0.3, τF = 1.5)\n\n# initial condition\nz0 = [0.238616, 0.982747, 0.367876]\n\n# Bifurcation Problem\nprob = BifurcationProblem(TMvf!, z0, par_tm, (@lens _.E0);\n\trecord_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]),)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We first compute the branch of equilibria","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = -2.0, p_max = -1.)\n\n# continuation of equilibria\nbr = continuation(prob, PALC(tangent=Bordered()), opts_br; normC = norminf)\n\nscene = plot(br, plotfold=false, markersize=3, legend=:topleft)","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"br","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Branch-of-periodic-orbits-with-Trapezoid-method","page":"🟡 Neural mass equation (Hopf aBS)","title":"Branch of periodic orbits with Trapezoid method","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We then compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use finite differences to discretize the problem of finding periodic orbits. Obviously, this will be problematic when the period of the limit cycle grows unbounded close to the homoclinic orbit.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"# continuation parameters\nopts_po_cont = ContinuationPar(opts_br, dsmax = 0.1, ds = -0.001, dsmin = 1e-4,\n\tmax_steps = 80, tol_stability = 1e-8)\n\n# arguments for periodic orbits\n# one function to record information and one\n# function for plotting\nargs_po = (\trecord_from_solution = (x, p) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\t\tmin = minimum(xtt[1,:]),\n\t\t\t\tperiod = getperiod(p.prob, x, p.p))\n\tend,\n\tplot_solution = (x, p; k...) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\targ = (marker = :d, markersize = 1)\n\t\tplot!(xtt.t, xtt[1,:]; label = \"E\", arg..., k...)\n\t\tplot!(xtt.t, xtt[2,:]; label = \"x\", arg..., k...)\n\t\tplot!(xtt.t, xtt[3,:]; label = \"u\", arg..., k...)\n\t\tplot!(br; subplot = 1, putspecialptlegend = false)\n\t\tend,\n\t# we use the supremum norm\n\tnormC = norminf)\n\nMt = 250 # number of time sections\nbr_potrap = continuation(\n\t# we want to branch form the 4th bif. point\n\tbr, 4, opts_po_cont,\n\t# we want to use the Trapeze method to locate PO\n\tPeriodicOrbitTrapProblem(M = Mt);\n\targs_po...,\n\t)\n\nscene = plot(br, br_potrap, markersize = 3)\nplot!(scene, br_potrap.param, br_potrap.min, label = \"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We plot the maximum (resp. minimum) of the limit cycle. We can see that the min converges to the smallest equilibrium indicating a homoclinic orbit.","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Plot-of-some-of-the-periodic-orbits-as-function-of-E_0","page":"🟡 Neural mass equation (Hopf aBS)","title":"Plot of some of the periodic orbits as function of E_0","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We can plot some of the previously computed periodic orbits in the plane (Ex) as function of E_0:","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"plot()\n# fetch the saved solutions\nfor sol in br_potrap.sol[1:2:40]\n\t# periodic orbit\n\tpo = sol.x\n\t# get the mesh and trajectory\n\ttraj = get_periodic_orbit(br_potrap.prob, po, @set par_tm.E0 = sol.p)\n\tplot!(traj[1,:], traj[2,:], xlabel = \"E\", ylabel = \"x\", label = \"\")\nend\ntitle!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Branch-of-periodic-orbits-with-Orthogonal-Collocation","page":"🟡 Neural mass equation (Hopf aBS)","title":"Branch of periodic orbits with Orthogonal Collocation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use Orthogonal Collocation to discretize the problem of finding periodic orbits. This is vastly more precise than the previous method because we use mesh adaptation.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"# continuation parameters\nopts_po_cont = ContinuationPar(opts_br, ds= 0.001, dsmin = 1e-4, dsmax = 0.1,\n\tmax_steps = 150,\n\ttol_stability = 1e-5)\n\nbr_pocoll = @time continuation(\n\t# we want to branch form the 4th bif. point\n\tbr, 4, opts_po_cont,\n\t# we want to use the Collocation method to locate PO, with polynomial degree 4\n\tPeriodicOrbitOCollProblem(40, 4; meshadapt = true);\n\t# regular continuation options\n\tplot = true,\n\t# we reject the newton step if the residual is high\n\tcallback_newton = BK.cbMaxNorm(100.),\n\targs_po...)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/#Periodic-orbits-with-Parallel-Standard-Shooting","page":"🟡 Neural mass equation (Hopf aBS)","title":"Periodic orbits with Parallel Standard Shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"We use a different method to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl. This way of computing periodic orbits should be more precise than the Trapezoid method. We use a particular instance called multiple shooting which is computed in parallel. This is an additional advantage compared to the two previous methods.","category":"page"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"using DifferentialEquations\n\n# this is the ODEProblem used with `DiffEqBase.solve`\nprobsh = ODEProblem(TMvf!, copy(z0), (0., 1.), par_tm; abstol = 1e-12, reltol = 1e-10)\n\nopts_po_cont = ContinuationPar(opts_br, dsmax = 0.1, ds= -0.0001, dsmin = 1e-4, max_steps = 110, tol_stability = 1e-4)\n\nbr_posh = @time continuation(\n\tbr, 4, opts_po_cont,\n\t# this is where we tell that we want Standard Shooting\n\t# with 15 time sections\n\tShootingProblem(15, probsh, Rodas5(), parallel = true);\n\t# regular continuation parameters\n\tplot = true,\n\targs_po...,\n\t# we reject the step when the residual is high\n\tcallback_newton = BK.cbMaxNorm(10)\n\t)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE/#References","page":"🟡 Neural mass equation (Hopf aBS)","title":"References","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE/","page":"🟡 Neural mass equation (Hopf aBS)","title":"🟡 Neural mass equation (Hopf aBS)","text":"[Cortes]: Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.","category":"page"},{"location":"periodicOrbitCollocation/#Periodic-orbits-based-on-orthogonal-collocation","page":"Collocation","title":"Periodic orbits based on orthogonal collocation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We compute Ntst time slices of a periodic orbit using orthogonal collocation. This is implemented in the structure PeriodicOrbitOCollProblem.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"tip: Large scale\nThe current implementation is optimized for ODE and for large scale problems for which the jacobian is sparse. ","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The general method is very well exposed in [Dankowicz],[Doedel] and we adopt the notations of [Dankowicz]. However our implementation is based on [Doedel] because it is more economical (less equations) when it enforces the continuity of the solution.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We look for periodic orbits as solutions (x(0) T) of","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"dot x = Tcdot F(x) x(0)=x(1)inmathbb R^n","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We focus on the differential equality and consider a partition of the time domain","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"0=tau_1cdotstau_jcdotstau_N_tst+1=1","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"where the points are referred to as mesh points. On each mesh interval tau_jtau_j+1 for j=1cdotsN_tst, we define the affine transformation","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"tau=tau^(j)(sigma)=tau_j+frac(1+sigma)2left(tau_j+1-tau_jright) sigma in-11","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The functions x^(j) defined on -11 by x^(j)(sigma) equiv x(tau_j(sigma)) satisfies the following equation on -11:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"dot x^(j) = Tfractau_j+1-tau_j2cdot F(x^(j))tagE_j","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"with the continuity equation x^(j+1)(-1) = x^(j)(1).","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We now aim at solving (E_j) by using an approximation with a polynomial of degree m. Following [Dankowicz], we define a (uniform) partition:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"-1=sigma_1cdotssigma_icdotssigma_m+1=1","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The points tau_ij = tau^(i)(sigma_j) are called the base points: they serve as collocation points.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The associated m+1 Lagrange polynomials of degree m are:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"mathcalL_i(sigma)=prod_k=1 k neq i^m+1 fracsigma-sigma_ksigma_i-sigma_k i=1 ldots m+1","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We then introduce the approximation p_j of x^(j):","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"mathcal p_j(sigma)equiv sumlimits_k=1^m+1mathcal L_k(sigma)x_jk","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"and the problem to be solved at the nodes z_l, l=1cdotsm:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"forall 1leq lleq mquad 1leq jleq N_tstquad dot p_j(z_l) = Tfractau_j+1-tau_j2cdot F(p_j(z_l))tagE_j^2","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The nodes (z_l) are associated with a Gauss–Legendre quadrature.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"In order to have a unique solution, we need to remove the phase freedom. This is done by imposing a phase condition.","category":"page"},{"location":"periodicOrbitCollocation/#Number-of-unknowns","page":"Collocation","title":"Number of unknowns","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"Putting the period unknown aside, we have to find the x_jk which gives ntimes N_tsttimes (m+1) unknowns. ","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The equations E_j^2 provides ntimes N_tsttimes m plus the (N_tst-1)times n equations for the continuity equations. This makes a total of (N_tst-1)times mtimes n+ntimes N_tsttimes m = nN_tst(m+1)-1 equations to which we add the n equations for the periodic boundary condition. In total, we have","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"ntimes N_tsttimes (m+1)","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"equations which matches the number of unknowns.","category":"page"},{"location":"periodicOrbitCollocation/#Phase-condition","page":"Collocation","title":"Phase condition","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"To ensure uniqueness of the solution to the functional, we add the following phase condition","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"frac1T int_0^Tleftlangle x(s) dot x_0(s)rightrangle d s =0","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"During continuation at step k, we use frac1T int_0^Tleftlangle x(s) dot x_k-1(s)rightrangle d s","category":"page"},{"location":"periodicOrbitCollocation/#Discretization-of-the-BVP-and-jacobian","page":"Collocation","title":"Discretization of the BVP and jacobian","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We only focus on the differential part. Summing up, we obtained the following equations for the x_jlinmathbb R^n:","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"sumlimits_k=1^m+1mathcal L_k(z_l)x_jk = Fleft(sumlimits_k=1^m+1mathcal L_k(z_l)x_jkright)","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian in the case m=2 is given by: ","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"x_00 x_01 x_10 x_11 x_20 x_21 x_30 T\nH_00^0 H_01^0 H_10^0 *\nH_00^1 H_01^1 H_10^1 *\n H_10^0 H_11^0 H_20^0 *\n H_10^1 H_11^1 H_20^1 *\n H_20^0 H_21^0 H_30^0 *\n H_20^1 H_21^1 H_30^1 *\nI -I *\n* * * * * * * *","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"where","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"H_kl^l_2 = mathcal L_l_2lcdot I_n - Tfractau_j+1-tau_j2cdotmathcal L_l_2lcdot dFleft(x_klright)","category":"page"},{"location":"periodicOrbitCollocation/#Interpolation","page":"Collocation","title":"Interpolation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"BifurcationKit.POSolution","category":"page"},{"location":"periodicOrbitCollocation/#BifurcationKit.POSolution","page":"Collocation","title":"BifurcationKit.POSolution","text":"Structure to encode the solution associated to a functional like ::PeriodicOrbitOCollProblem or ::ShootingProblem. In the particular case of ::PeriodicOrbitOCollProblem, this allows to use the collocation polynomials to interpolate the solution. Hence, if sol::POSolution, one can call\n\nsol = BifurcationKit.POSolution(prob_coll, x)\nsol(t)\n\non any time t.\n\n\n\n\n\n","category":"type"},{"location":"periodicOrbitCollocation/#Mesh-adaptation","page":"Collocation","title":"Mesh adaptation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The goal of this method[Russell] is to adapt the mesh tau_i in order to minimize the error. It is particularly helpful near homoclinic solutions where the period diverge. It can also be useful in order to use a smaller N_tst.","category":"page"},{"location":"periodicOrbitCollocation/#Encoding-of-the-functional","page":"Collocation","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The functional is encoded in the composite type PeriodicOrbitOCollProblem. See the link for more information, in particular on how to access the underlying functional, its jacobian...","category":"page"},{"location":"periodicOrbitCollocation/#Jacobian-and-linear-solvers","page":"Collocation","title":"Jacobian and linear solvers","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We provide many different linear solvers to take advantage of the formulations or the dimensionality. These solvers are available through the argument jacobian in the constructor of PeriodicOrbitOCollProblem. For example, you can pass jacobian = FullSparse(). Note that all the internal solvers and jacobian are set up automatically, you don't need to do anything. However, for the sake of explanation, we detail how this works.\t","category":"page"},{"location":"periodicOrbitCollocation/#.-DenseAnalytical()","page":"Collocation","title":"1. DenseAnalytical()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed with an analytical formula, works for dense matrices. This is the default algorithm.","category":"page"},{"location":"periodicOrbitCollocation/#.-AutoDiffDense()","page":"Collocation","title":"2. AutoDiffDense()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed with automatic differentiation, works for dense matrices. Can be used for debugging.","category":"page"},{"location":"periodicOrbitCollocation/#.-FullSparse()","page":"Collocation","title":"3. FullSparse()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed with an analytical formula, works for sparse matrices.","category":"page"},{"location":"periodicOrbitCollocation/#.-FullSparseInplace()","page":"Collocation","title":"3. FullSparseInplace()","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The jacobian is computed in place, limiting memory allocations, with an analytical formula when the sparsity of the jacobian of the vector field is constant. This is much faster than FulSparse().","category":"page"},{"location":"periodicOrbitCollocation/#Floquet-multipliers-computation","page":"Collocation","title":"Floquet multipliers computation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We provide two methods to compute the Floquet coefficients.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The algorithm (Default) FloquetColl is based on the condensation of parameters described in [Doedel]. It is the fastest method.\nThe algorithm FloquetCollGEV is a simplified version of the procedure described in [Fairgrieve]. It boils down to solving a large generalized eigenvalue problem. There is clearly room for improvements here but this can be used to check the results of the previous method.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"These methods allow to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. However they may be imprecise[Lust].","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbitCollocation/#Computation-with-newton","page":"Collocation","title":"Computation with newton","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"newton(prob::PeriodicOrbitOCollProblem, orbitguess, options::NewtonPar; kwargs...)","category":"page"},{"location":"periodicOrbitCollocation/#BifurcationKit.newton-Tuple{PeriodicOrbitOCollProblem, Any, NewtonPar}","page":"Collocation","title":"BifurcationKit.newton","text":"newton(probPO, orbitguess, options; kwargs...)\n\n\nThis is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is a PeriodicOrbitOCollProblem.\n\nprob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit.\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG\nFor AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.\nFor DenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We provide a simplified call to newton to locate the periodic orbits. newton will look for prob.jacobian in order to select the requested way to compute the jacobian.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"The docs for this specific newton are located at newton.","category":"page"},{"location":"periodicOrbitCollocation/#Continuation","page":"Collocation","title":"Continuation","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"We refer to continuation for more information regarding the arguments. continuation will look for prob.jacobian in order to select the requested way to compute the jacobian.","category":"page"},{"location":"periodicOrbitCollocation/#References","page":"Collocation","title":"References","text":"","category":"section"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Dankowicz]: Dankowicz, Harry, and Frank Schilder. Recipes for Continuation. Computational Science and Engineering Series. Philadelphia: Society for Industrial and Applied Mathematics, 2013.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Doedel]: Doedel, Eusebius, Herbert B. Keller, and Jean Pierre Kernevez. “NUMERICAL ANALYSIS AND CONTROL OF BIFURCATION PROBLEMS (II): BIFURCATION IN INFINITE DIMENSIONS.” International Journal of Bifurcation and Chaos 01, no. 04 (December 1991): 745–72.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Fairgrieve]: Fairgrieve, Thomas F., and Allan D. Jepson. “O. K. Floquet Multipliers.” SIAM Journal on Numerical Analysis 28, no. 5 (October 1991): 1446–62. https://doi.org/10.1137/0728075.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Russell]: Russell, R. D., and J. Christiansen. “Adaptive Mesh Selection Strategies for Solving Boundary Value Problems.” SIAM Journal on Numerical Analysis 15, no. 1 (February 1978): 59–80. https://doi.org/10.1137/0715004.","category":"page"},{"location":"periodicOrbitCollocation/","page":"Collocation","title":"Collocation","text":"[Lust]: Lust, Kurt. “Improved Numerical Floquet Multipliers.” International Journal of Bifurcation and Chaos 11, no. 09 (September 2001): 2389–2410. https://doi.org/10.1142/S0218127401003486.","category":"page"},{"location":"codim3Continuation/#Bogdanov-Takens-refinement","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"In this page, we explain how to perform precise localisation of Bogdanov-Takens (BT) points. This is an unusual feature of numerical continuation libraries. We chose to implement it because the localisation of the BT points on the Hopf bifurcation curves is rather imprecise.","category":"page"},{"location":"codim3Continuation/#Method","page":"Bogdanov-Takens refinement (3 params)","title":"Method","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"The continuation of BT bifurcation points is based on a Minimally Augmented[Govaerts],[Blank],[Bindel] formulation which is an efficient way to detect singularities. The continuation of BT points is based on the formulation","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"G(up) = (F(up) g_1(up) g_2(up))inmathbb R^n+2quadquad (F_bt)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"where the test functions g_1g_2 are solutions of","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"leftbeginarraycc\ndF(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nv_1 \ng_1(up)\nendarrayright=leftbeginarrayc0_n 1endarrayrightquadquad (M_bt)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"and","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"leftbeginarraycc\ndF(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nv_2 \ng_2(up)\nendarrayright=leftbeginarraycv_1 0endarrayrightquadquad (M_bt)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"and where wv are chosen in order to have a non-singular matrix (M_bt). More precisely, v (resp. w) should be close to a null vector of dF(u,p) (resp. dF(u,p)').","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"note that there are very simplified calls for this, see Newton refinement below. In particular, you don't need to set up the Minimally Augmented problem yourself. This is done in the background.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"warning: Linear Method\nYou can pass the bordered linear solver to solve (M_bt) using the option bdlinsolver (see below). Note that the choice bdlinsolver = BorderingBLS() can lead to singular systems. Indeed, in this case, (M_bt) is solved by inverting dF(u,p) which is singular at Fold points.","category":"page"},{"location":"codim3Continuation/#Setting-the-jacobian","page":"Bogdanov-Takens refinement (3 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"In order to apply the newton algorithm to F_bt, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to F_bt and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian F_bt and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"codim3Continuation/#Example","page":"Bogdanov-Takens refinement (3 params)","title":"Example","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"using BifurcationKit, LinearAlgebra, Setfield, SparseArrays, ForwardDiff, Parameters\nFbt(x, p) = [x[2], p.β1 + p.β2 * x[2] + p.a * x[1]^2 + p.b * x[1] * x[2]]\npar = (β1 = 0.01, β2 = -0.3, a = -1., b = 1.)\nprob = BifurcationProblem(Fbt, [0.01, 0.01], par, (@lens _.β1))\nopts_br = ContinuationPar(p_max = 0.5, p_min = -0.5, detect_bifurcation = 3, nev = 2)\n\nbr = continuation(prob, PALC(), opts_br; bothside = true)\n\n# compute branch of Hopf points\nhopf_codim2 = continuation(br, 3, (@lens _.β2), ContinuationPar(opts_br, detect_bifurcation = 1, max_steps = 40, max_bisection_steps = 25) ;\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tbothside = true,\n\t)\n\n# refine BT point\nsolbt = BifurcationKit.newton_bt(hopf_codim2, 2; start_with_eigen = true)\nsolbt.u","category":"page"},{"location":"codim3Continuation/#Newton-refinement","page":"Bogdanov-Takens refinement (3 params)","title":"Newton refinement","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"Once a Bogdanov-Takens point has been detected after a call to br = continuation(...), it can be refined using newton iterations. Let us say that ind_bif is the index in br.specialpoint of a Bogdanov-Takens point. This guess can be refined as follows:","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"outfold = newton(br::AbstractBranchResult, ind_bif::Int; \n\tnormN = norm,\n\toptions = br.contparams.newton_options,\n\tbdlinsolver = BorderingBLS(options.linsolver),\n\tjacobian_ma = :autodiff,\n\tstart_with_eigen = false, kwargs...)","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"For the options parameters, we refer to Newton.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"It is important to note that for improved performances, a function implementing the expression of the hessian should be provided. This is by far the fastest. BifurcationProblem provides it by default using AD though.","category":"page"},{"location":"codim3Continuation/#Advanced-use","page":"Bogdanov-Takens refinement (3 params)","title":"Advanced use","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"Here, we expose the solvers that are used to perform newton refinement. This is useful in case it is too involved to expose the linear solver options.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"BifurcationKit.newton_bt","category":"page"},{"location":"codim3Continuation/#BifurcationKit.newton_bt","page":"Bogdanov-Takens refinement (3 params)","title":"BifurcationKit.newton_bt","text":"newton_bt(\n prob,\n btpointguess,\n par,\n lens2,\n eigenvec,\n eigenvec_ad,\n options;\n normN,\n jacobian_ma,\n usehessian,\n bdlinsolver,\n bdlinsolver_adjoint,\n bdlinsolver_block,\n kwargs...\n)\n\n\nThis function turns an initial guess for a BT point into a solution to the BT problem based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationFunction\nbtpointguess initial guess (x0, p0) for the BT point. It should be a BorderedArray as returned by the function BTPoint\npar parameters used for the vector field\neigenvec guess for the 0 eigenvector\neigenvec_ad guess for the 0 adjoint eigenvector\noptions::NewtonPar options for the Newton-Krylov algorithm, see NewtonPar.\n\nOptional arguments:\n\nnormN = norm\nbdlinsolver bordered linear solver for the constraint equation\njacobian_ma::Symbol = true specify the way the (newton) linear system is solved. Can be (:autodiff, :finitedifferences, :minaug)\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\nSimplified call\n\nSimplified call to refine an initial guess for a BT point. More precisely, the call is as follows\n\nnewton(br::AbstractBranchResult, ind_bt::Int; options = br.contparams.newton_options, kwargs...)\n\nThe parameters / options are as usual except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of bifurcation point in br you want to refine. You can pass newton parameters different from the ones stored in br by using the argument options.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian will be computed twice!\n\ntip: ODE problems\nFor ODE problems, it is more efficient to pass the option jacobian_ma = :autodiff\n\n\n\n\n\nnewton_bt(\n br,\n ind_bt;\n probvf,\n normN,\n options,\n nev,\n start_with_eigen,\n bdlinsolver,\n bdlinsolver_adjoint,\n kwargs...\n)\n\n\nThis function turns an initial guess for a Bogdanov-Takens point into a solution to the Bogdanov-Takens problem based on a Minimally Augmented formulation.\n\nArguments\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\n\nOptional arguments:\n\noptions::NewtonPar, default value br.contparams.newton_options\nnormN = norm\noptions You can pass newton parameters different from the ones stored in br by using this argument options.\njacobian_ma::Symbol = true specify the way the (newton) linear system is solved. Can be (:autodiff, :finitedifferences, :minaug)\nbdlinsolver bordered linear solver for the constraint equation\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements.\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\ntip: ODE problems\nFor ODE problems, it is more efficient to pass the option jacobian = :autodiff\n\ntip: start_with_eigen\nFor ODE problems, it is more efficient to pass the option start_with_eigen = true\n\n\n\n\n\n","category":"function"},{"location":"codim3Continuation/#References","page":"Bogdanov-Takens refinement (3 params)","title":"References","text":"","category":"section"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Blank]: Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.","category":"page"},{"location":"codim3Continuation/","page":"Bogdanov-Takens refinement (3 params)","title":"Bogdanov-Takens refinement (3 params)","text":"[Bindel]: Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.","category":"page"},{"location":"tutorials/ode/NME-MTK/#Neural-mass-equation-MTK","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"Pages = [\"NME-MTK.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"In this tutorial, we study the following model taken from [Cortes]. It is essentially the same tutorial as in Neural mass equation but treated with ModelingToolkit.jl.","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"leftbeginarrayl\ntau dotE=-E+gleft(J u x E+E_0right) \ndotx=tau_D^-1(1-x)-u E x \ndotu=U E(1-u)-tau_F^-1(u-U)\nendarrayright","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"The model is interesting because the branch of periodic solutions converges to an homoclinic orbit which is challenging to compute with our methods.","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"using Revise, ModelingToolkit, LinearAlgebra\nusing DifferentialEquations, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nindexof(sym, syms) = findfirst(isequal(sym),syms)\n\n@variables t E(t) x(t) u(t) SS0(t) SS1(t) \t# independent and dependent variables\n@parameters U0 τ J E0 τD U0 τF τS α \t\t# parameters\nD = Differential(t) \t\t\t\t# define an operator for the differentiation w.r.t. time\n\n# define the model\n@named NMmodel = ODESystem([SS0 ~ J * u * x * E + E0,\n\tSS1 ~ α * log(1 + exp(SS0 / α)),\n\tD(E) ~ (-E + SS1) / τ,\n\tD(x) ~ (1.0 - x) / τD - u * x * E,\n\tD(u) ~ (U0 - u) / τF + U0 * (1 - u) * E],\n\tdefaults = Dict(E => 0.238616, x => 0.982747, u => 0.367876,\n\tα => 1.5, τ => 0.013, J => 3.07, E0 => -2.0, τD => 0.200, U0 => 0.3, τF => 1.5, τS => 0.007))\n\n# get the vector field and jacobian\nodeprob = ODEProblem(structural_simplify(NMmodel), [], (0.,10.), [], jac = true)\nodefun = odeprob.f\nF = (u,p) -> odefun(u,p,0)\nJ = (u,p) -> odefun.jac(u,p,0)\n\nid_E0 = indexof(E0, parameters(NMmodel))\npar_tm = odeprob.p\n\n# we collect the differentials together in a problem\nprob = BifurcationProblem(F, odeprob.u0, par_tm, (@lens _[id_E0]); J = J,\n record_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]))\nnothing #hide","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We first compute the branch of equilibria","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"# continuation options\nopts_br = ContinuationPar(p_min = -10.0, p_max = -0.9,\n\t# parameters to have a smooth result\n\tds = 0.04, dsmax = 0.05,\n\t# this is to detect bifurcation points precisely with bisection\n\tdetect_bifurcation = 3,\n\t# Optional: bisection options for locating bifurcations\n\tn_inversion = 8, max_bisection_steps = 25, nev = 3)\n\n# continuation of equilibria\nbr = continuation(prob, PALC(tangent = Bordered()), opts_br; normC = norminf)\n\nscene = plot(br, plotfold=false, markersize=3, legend=:topleft)","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"br","category":"page"},{"location":"tutorials/ode/NME-MTK/#Branch-of-periodic-orbits-with-Collocation-method","page":"🟢 Neural mass equation - MTK","title":"Branch of periodic orbits with Collocation method","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We then compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use finite differences to discretize the problem of finding periodic orbits. Obviously, this will be problematic when the period of the limit cycle grows unbounded close to the homoclinic orbit.","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"# newton parameters\noptn_po = NewtonPar(tol = 1e-8, max_iterations = 10)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.15, ds= -0.0001, dsmin = 1e-4, p_max = 0., p_min=-5.,\n\tmax_steps = 150, newton_options = optn_po,\n\tnev = 3, plot_every_step = 10, detect_bifurcation = 0)\n\n# arguments for periodic orbits\n# this is mainly for printing purposes\nargs_po = (\trecord_from_solution = (x, p) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\t\tmin = minimum(xtt[1,:]),\n\t\t\t\tperiod = getperiod(p.prob, x, p.p))\n\tend,\n\tplot_solution = (x, p; k...) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\tplot!(xtt.t, xtt[1,:]; label = \"E\", k...)\n\t\tplot!(xtt.t, xtt[2,:]; label = \"x\", k...)\n\t\tplot!(xtt.t, xtt[3,:]; label = \"u\", k...)\n\t\tplot!(br; subplot = 1, putspecialptlegend = false)\n\t\tend,\n\tnormC = norminf)\n\n\nMt = 30 # number of time sections\n\tbr_pocoll = @time continuation(\n\t# we want to branch form the 4th bif. point\n\tbr, 4, opts_po_cont,\n\t# we want to use the Collocation method to locate PO, with polynomial degree 5\n\tPeriodicOrbitOCollProblem(Mt, 5; meshadapt = true);\n\t# regular continuation options\n\targs_po..., callback_newton = BK.cbMaxNorm(10))\n\nscene = plot(br, br_pocoll, markersize = 3)\nplot!(scene, br_pocoll.param, br_pocoll.min, label = \"\")","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We plot the maximum (resp. minimum) of the limit cycle. We can see that the min converges to the smallest equilibrium indicating a homoclinic orbit.","category":"page"},{"location":"tutorials/ode/NME-MTK/#Plot-of-some-of-the-periodic-orbits-as-function-of-E_0","page":"🟢 Neural mass equation - MTK","title":"Plot of some of the periodic orbits as function of E_0","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"We can plot some of the previously computed periodic orbits in the plane (Ex) as function of E_0:","category":"page"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"plot()\n# fetch the saved solutions\nfor sol in br_pocoll.sol[1:2:40]\n\t# periodic orbit\n\tpo = sol.x\n\t# get the mesh and trajectory\n\ttraj = BK.get_periodic_orbit(br_pocoll.prob, po, @set par_tm[id_E0] = sol.p)\n\tplot!(traj[1,:], traj[2,:], xlabel = \"E\", ylabel = \"x\", label = \"\")\nend\ntitle!(\"\")","category":"page"},{"location":"tutorials/ode/NME-MTK/#References","page":"🟢 Neural mass equation - MTK","title":"References","text":"","category":"section"},{"location":"tutorials/ode/NME-MTK/","page":"🟢 Neural mass equation - MTK","title":"🟢 Neural mass equation - MTK","text":"[Cortes]: Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.","category":"page"},{"location":"tutorials/ode/tutorials1/#Temperature-model","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"","category":"section"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"This is a classical example from the Trilinos library.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"This is a simple example in which we aim at solving Delta T+alpha N(Tbeta)=0 with boundary conditions T(0) = T(1)=beta. This example is coded in examples/chan.jl. We start with some imports:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"using BifurcationKit, LinearAlgebra, Plots, Parameters\nconst BK = BifurcationKit\n\nN(x; a = 0.5, b = 0.01) = 1 + (x + a*x^2)/(1 + b*x^2)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We then write our functional:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"function F_chan(x, p)\n\t@unpack α, β = p\n\tf = similar(x)\n\tn = length(x)\n\tf[1] = x[1] - β\n\tf[n] = x[n] - β\n\tfor i=2:n-1\n\t\tf[i] = (x[i-1] - 2 * x[i] + x[i+1]) * (n-1)^2 + α * N(x[i], b = β)\n\tend\n\treturn f\nend\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We want to call a Newton solver. We first need an initial guess:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"n = 101\nsol0 = [(i-1)*(n-i)/n^2+0.1 for i=1:n]\n\n# set of parameters\npar = (α = 3.3, β = 0.01)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"Finally, we need to provide some parameters for the Newton iterations. This is done by calling","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"optnewton = NewtonPar(tol = 1e-9, max_iterations = 10)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We call the Newton solver:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"prob = BifurcationProblem(F_chan, sol0, par, (@lens _.α),\n\t# function to plot the solution\n\tplot_solution = (x, p; k...) -> plot!(x; ylabel=\"solution\", label=\"\", k...))\nsol = newton(prob, optnewton) # hide\n# we set verbose to true to see the newton iterations\nsol = @time newton( prob, @set optnewton.verbose = true)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"We can perform numerical continuation w.r.t. the parameter alpha. This time, we need to provide additional parameters, but now for the continuation method:","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"optcont = ContinuationPar(max_steps = 150,\n\tp_min = 0., p_max = 4.2,\n\tnewton_options =optnewton)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"Next, we call the continuation routine as follows.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"br = continuation(prob, PALC(), optcont; plot = true)\nnothing #hide\t\t","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"The parameter axis lens = @lens _.α is used to extract the component of par corresponding to α. Internally, it is used as get(par, lens) which returns 3.3.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"You should see","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"scene = title!(\"\") #hide\t\t","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"The left figure is the norm of the solution as function of the parameter p=alpha, the y-axis can be changed by passing a different record_from_solution to BifurcationProblem. The top right figure is the value of alpha as function of the iteration number. The bottom right is the solution for the current value of the parameter. This last plot can be modified by changing the argument plot_solution to BifurcationProblem.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"note: Bif. point detection\nTwo Fold points were detected. This can be seen by looking at show(br) or br.specialpoint, by the black\tdots on the continuation plots when doing plot(br, plotfold=true) or by typing br in the REPL. Note that the bifurcation points are located in br.specialpoint.","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"What if we want to compute to continue both ways in one call?","category":"page"},{"location":"tutorials/ode/tutorials1/","page":"🟢 Temperature model","title":"🟢 Temperature model","text":"br = continuation(prob, PALC(), optcont; bothside = true)\nplot(br)","category":"page"},{"location":"guidelines/#Guidelines","page":"Guidelines","title":"Guidelines","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The goal of this package is to find solutions x to nonlinear equations ","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"F(xp) = 0 quadtagE","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"in large dimensions as function of a real parameter p. We want to be able to do so on GPU, distributed systems...","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The core of the package is built around a Newton-Krylov solver (see newton) which allows to solve equations of the form F(x)=0, or find a solution x_0 to (E) for a particular p_0.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"Once such a solution (or several) (x_0p_0) is known, we can continue it by computing a 1d curve of solutions gamma = (x(s)p(s))_sin I passing through (x_0p_0) (see continuation and Deflated Continuation).","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"In practice, you don't need to know exactly (x_0p_0) to compute gamma. Indeed, continuation will call newton to refine any initial guess that you pass.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Textbook\nOnly the basics of bifurcation theory is underlined here. We refer to [Kuznetsov],[haragus] for a more thorough description.","category":"page"},{"location":"guidelines/#Bifurcation-analysis-of-Equilibria","page":"Guidelines","title":"Bifurcation analysis of Equilibria","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We can detect if the curve of solutions gamma crosses another curve of solutions gamma^bif without knowing gamma^bif! The intersection point (x^bp^b)ingamma is called a bifurcation point and is such that partial_xF(x^bp^b) is non invertible. When calling γ = continuation(...) with the option detect_bifurcation > 1 inside ContinuationPar, the bifurcation points are automatically detected and stored in γ.specialpoints.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"warning: Eigenvalues\nThe rightmost eigenvalues are computed by default to detect bifurcations. Hence, the number of eigenvalues with positive real parts must be finite (e.g. small). This might require to consider -F(xp)=0 instead of (E).","category":"page"},{"location":"guidelines/#Branch-switching","page":"Guidelines","title":"Branch switching","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"In the simple case where dimker partial_xF(x^bp^b) = 1, we can compute automatically the bifurcated branch gamma^bif by calling continuation and passing gamma. This is explained in Branch switching from simple branch point to equilibria. Recursively, we can compute the curves of solutions which are connected to (x_0p_0), this is called a bifurcation diagram. This bifurcation diagram can be automatically computed using the function bifurcationdiagram with minimum input from the user. More information is provided in Automatic Bifurcation diagram computation and examples of use are 1d Swift-Hohenberg equation and Bratu–Gelfand problem.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"When dequiv dimker partial_xF(x^bp^b) 1, you can still compute automatically the bifurcated branches gamma^bifs by calling continuation. It is based on a reduction of (E) to a small system of d dimensional multivariate polynomial equations in d unknowns whose solutions give the local topology of branches in the neighborhood of the bifurcation point (x^b p^b). The solutions of this reduced equation are then used as initial guesses for the call to Krylov-Newton. This is explained in From simple branch point to equilibria and examples of use are shown in 2d Bratu–Gelfand problem and Automatic 2d Bratu–Gelfand problem (Intermediate).\t","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"In the case d=1, the reduced equation can be further simplified into a normal form. This is also automatically computed by the package.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Branch switching\nMany more branch switching procedures are available. They are all listed in Branch switching","category":"page"},{"location":"guidelines/#Bifurcation-analysis-of-Cauchy-problems","page":"Guidelines","title":"Bifurcation analysis of Cauchy problems","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The goal of this section is to study the dynamics of the Cauchy problem","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"fracddtx - F(xp) = 0 quadtagC","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"The equilibria are time independent solutions of (C) hence satisfying (E). The previous section can be applied to compute curves of equilibria. However, we can do more. By discretizing time, we can recast (C) in the general form (E) and look for time dependent solutions as well. ","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We can detect the existence of periodic solutions close to gamma. This is done automatically and those bifurcation points are stored in γ.specialpoint as well with the name of Hopf bifurcation points. ","category":"page"},{"location":"guidelines/#Branch-switching-at-Hopf-points","page":"Guidelines","title":"Branch switching at Hopf points","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We focus on computing the branch of periodic solutions branching from a Hopf point. This is done automatically by calling continuation, passing gamma and choosing a time discretization algorithm (see Periodic orbits computation). Some details about this branch switching are given in From Hopf point to periodic orbits.","category":"page"},{"location":"guidelines/#Branch-switching-at-bifurcation-points-of-periodic-orbits","page":"Guidelines","title":"Branch switching at bifurcation points of periodic orbits","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"Let us consider the case where a branch of periodic orbits gamma^po have been computed (see for example previous section) and several bifurcation points have been detected (branch point, period doubling and Neimark Sacker). Can we compute bifurcated branches from gamma^po? Automatically?","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"We do not provide an automatic branch switching for those points and for all methods (Shooting, Finite differences). However, for branch points of periodic orbits, you can call continuation by passing gamma^po and some simple arguments (amplitude of the periodic orbits) to perform branch switching in a semi-automatic way. For the case of Periodic orbits based on Trapezoidal rule, see From Branch / Period-doubling point of curve of periodic orbits.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Branch switching\nMany more branch switching procedures are available. They are all listed in Branch switching","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"tip: Manual Branch switching\nYou can perform manual branch switching by computing the nearby solutions close to a bifurcation point using a deflated newton (see Deflated problems), which provides a way to compute solutions other than a set of already known solutions. You can then use these solutions to compute branches by calling continuation. Many, if not all tutorials give example of doing so like 2d Bratu–Gelfand problem or 1d Brusselator.","category":"page"},{"location":"guidelines/#References","page":"Guidelines","title":"References","text":"","category":"section"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"[Kuznetsov]: Kuznetsov, Yuri A. Elements of Applied Bifurcation Theory. Vol. 112. Applied Mathematical Sciences. Cham: Springer International Publishing, 2023. https://doi.org/10.1007/978-3-031-22007-4.","category":"page"},{"location":"guidelines/","page":"Guidelines","title":"Guidelines","text":"[haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"tutorials/mittelmann/#gelfand","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Pages = [\"mittelmann.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"unknown: References\nThe following example is exposed in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. The Computation of Disconnected Bifurcation Diagrams. ArXiv:1603.00809 [Math], March 2, 2016. It is also treated in Michiel Wouters. Automatic Exploration Techniques for the Numerical Continuation of Large–Scale Nonlinear Systems, 2019.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We consider the problem of Mittelmann:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Delta u + NL(lambdau) = 0","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"with Neumann boundary condition on Omega = (01)^2 and where NL(lambdau)equiv-10(u-lambda e^u). This is a good example to show how automatic branch switching works and also nonlinear deflation.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We start with some imports:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\n\n# define the sup norm and a L2 norm\nnormbratu(x) = norm(x .* w) / sqrt(length(x)) # the weight w is defined below\n\n# some plotting functions to simplify our life\nplotsol!(x, nx = Nx, ny = Ny; kwargs...) = heatmap!(reshape(x, nx, ny); color = :viridis, kwargs...)\nplotsol(x, nx = Nx, ny = Ny; kwargs...) = (plot();plotsol!(x, nx, ny; kwargs...))\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"and with the discretization of the problem","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"function Laplacian2D(Nx, Ny, lx, ly, bc = :Neumann)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Neumann0BC(hx)\n\tQy = Neumann0BC(hy)\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A\nend\n\nϕ(u, λ) = -10(u-λ*exp(u))\ndϕ(u, λ) = -10(1-λ*exp(u))\n\nfunction NL!(dest, u, p)\n\t@unpack λ = p\n\tdest .= ϕ.(u, λ)\n\treturn dest\nend\n\nNL(u, p) = NL!(similar(u), u, p)\n\nfunction Fmit!(f, u, p)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\n\treturn f\nend\n\nFmit(u, p) = Fmit!(similar(u), u, p)\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"It will also prove useful to have the derivatives of our functional:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"function JFmit(x,p)\n\tJ = p.Δ\n\tdg = dϕ.(x, p.λ)\n\treturn J + spdiagm(0 => dg)\nend\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We need to define the parameters associated to this problem:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Nx = 30; Ny = 30\nlx = 0.5; ly = 0.5\n# weight for the weighted norm\nconst w = (lx .+ LinRange(-lx,lx,Nx)) * (LinRange(-ly,ly,Ny))' |> vec\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)\npar_mit = (λ = .05, Δ = Δ)\n\n# initial guess f for newton\nsol0 = zeros(Nx, Ny) |> vec\n\n# Bifurcation Problem\nprob = BifurcationProblem(Fmit, sol0, par_mit, (@lens _.λ),; J = JFmit,\n record_from_solution = (x, p) -> (x = normbratu(x), n2 = norm(x), n∞ = norminf(x)),\n plot_solution = (x, p; k...) -> plotsol!(x ; k...))\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"To compute the eigenvalues, we opt for the shift-invert strategy with shift =0.5","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"# eigensolver\neigls = EigKrylovKit(dim = 70)\n\n# options for Newton solver, we pass the eigensolverr\nopt_newton = BK.NewtonPar(tol = 1e-8, verbose = false, eigsolver = eigls, max_iterations = 20)\n\n# options for continuation\nopts_br = ContinuationPar(p_max = 3.5, p_min = 0.025,\n\t# for a good looking curve\n\tdsmin = 0.001, dsmax = 0.05, ds = 0.01,\n\t# number of eigenvalues to compute\n\tnev = 30,\n\tplot_every_step = 10, newton_options = (@set opt_newton.verbose = false),\n\tmax_steps = 100, tol_stability = 1e-6,\n\t# detect codim 1 bifurcations\n\tdetect_bifurcation = 3,\n\t# Optional: bisection options for locating bifurcations\n\tn_inversion = 4, dsmin_bisection = 1e-7, max_bisection_steps = 25)\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Note that we put the option detect_bifurcation = 3 to detect bifurcations precisely with a bisection method. Indeed, we need to locate these branch points precisely to be able to call automatic branch switching.","category":"page"},{"location":"tutorials/mittelmann/#Branch-of-homogeneous-solutions","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Branch of homogeneous solutions","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"At this stage, we note that the problem has a curve of homogeneous (constant in space) solutions u_h solving N(lambda u_h)=0. We shall compute this branch now.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Given that we will use these arguments for continuation many times, it is wise to collect them:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"# optional arguments for continuation\nkwargsC = (verbosity = 0, plot = true, normC = norminf)\nnothing #hide","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We call continuation with the initial guess sol0 which is homogeneous, thereby generating homogeneous solutions:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"br = continuation(prob, PALC(), opts_br; kwargsC...)\nshow(br)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You should see the following result:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"title!(\"\")","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We note several simple bifurcation points for which the dimension of the kernel of the jacobian is one dimensional. In the above box, δ = ( 1, 0) gives the change in the stability. In this case, there is one vector in the kernel which is real. The bifurcation point 2 has a 2d kernel and is thus not amenable to automatic branch switching.","category":"page"},{"location":"tutorials/mittelmann/#Automatic-branch-switching-at-simple-branch-points","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Automatic branch switching at simple branch points","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can compute the branch off the third bifurcation point:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"br1 = continuation(br, 3, setproperties(opts_br;ds = 0.001, max_steps = 40); kwargsC...)\ntitle!(\"\")","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You can also plot the two branches together plot(br, br1, plotfold=false) and get","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"scene = plot(br,br1,plotfold=false)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We continue our journey and compute the branch bifurcating of the first bifurcation point from the last branch we computed:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"br2 = continuation(br1, 1, setproperties(opts_br;ds = 0.001, max_steps = 40); kwargsC...)\nscene = plot(br,br1,br2)","category":"page"},{"location":"tutorials/mittelmann/#Automatic-branch-switching-at-the-2d-branch-points","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Automatic branch switching at the 2d-branch points","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We now show how to perform automatic branch switching at the nonsimple branch points. However, we think it is important that the user is able to use the previous tools in case automatic branch switching fails. This is explained in the next sections.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"The call for automatic branch switching is the same as in the case of simple branch points (see above) except that many branches are returned.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"branches = continuation(br, 2,\n\tsetproperties(opts_br; detect_bifurcation = 3, ds = 0.001, p_min = 0.01, max_steps = 32 ) ;\n alg = PALC(tangent = Bordered()),\n\tkwargsC...,\n\tnev = 30,\n\t)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You can plot the branches using","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"scene = plot(br, branches...)","category":"page"},{"location":"tutorials/mittelmann/#Analysis-at-the-2d-branch-points-(manual)","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Analysis at the 2d-branch points (manual)","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"The second bifurcation point on the branch br of homogeneous solutions has a 2d kernel. we provide two methods to deal with such case","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"automatic local bifurcation diagram (see below)\nbranch switching with deflation (see next section)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We provide a generic way to study branch points of arbitrary dimensions by computing a reduced equation. The general method is based on a Lyapunov-Schmidt reduction. We can compute the information about the branch point using the generic function (valid for simple branch points, Hopf bifurcation points,...)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"bp2d = get_normal_form(br, 2; verbose=true, nev = 50)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"Note that this is a multivariate polynomials. For more information, see Non-simple branch point.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You can evaluate this polynomial as follows bp2d(Val(:reducedForm),[0.1,0.2], 0.01) which returns a 2d vector or bp2d([0.1,0.2], 0.01). This last expression actually returns a vector corresponding to the PDE problem.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"You need to solve these equations to compute the bifurcation diagram in the neighborhood of the bifurcation point. In the present case, we do it using brute force. We suggest to use IntervalConstraintProgramming.jl for a more precise way.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"using ProgressMeter\nNd = 200; L = 0.9\n# sampling grid\nX = LinRange(-L,L, Nd); Y = LinRange(-L,L, Nd); P = LinRange(-0.0001,0.0001, Nd+1)\n\n# sample reduced equation on the grid for the first component\nV1a = @showprogress [bp2d(Val(:reducedForm),[x1,y1], p1)[1] for p1 in P, x1 in X, y1 in Y]\nInd1 = findall( abs.(V1a) .<= 9e-4 * maximum(abs.(V1a)))\n# intersect with second component\nV2a = @showprogress [bp2d(Val(:reducedForm),[X[ii[2]],Y[ii[3]]], P[ii[1]])[2] for ii in Ind1]\nInd2 = findall( abs.(V2a) .<= 3e-3 * maximum(abs.(V2a)))\n\n# get solutions\nresp = Float64[]; resx = Vector{Float64}[]; resnrm = Float64[]\n\t@showprogress for k in Ind2\n\t\tii = Ind1[k]\n\t\tpush!(resp, P[ii[1]])\n\t\tpush!(resnrm, sqrt(X[ii[2]]^2+Y[ii[3]]^2))\n\t\tpush!(resx, [X[ii[2]], Y[ii[3]]])\n\tend","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can now plot the local bifurcation diagram as follows","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"using LaTeXStrings\nplot(\n\tscatter(1e4resp, map(x->x[1], resx), map(x->x[2], resx); label = \"\", markerstrokewidth=0, xlabel = L\"10^4 \\cdot \\lambda\", ylabel = L\"x_1\", zlabel = L\"x_2\", zcolor = resnrm, color = :viridis,colorbar=false),\n\tscatter(1e4resp, resnrm; label = \"\", markersize =2, markerstrokewidth=0, xlabel = L\"10^4 \\cdot \\lambda\", ylabel = L\"\\|x\\|\"))","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"This looks like a Pitchfork bifurcation with D4 symmetry","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can see that there are two types of solutions. After the bifurcation point, the solutions are of the form (x_1x_2) = (pm xpm x) for some real x. Before the bifurcation point, the solutions are of the form (x_1x_2) = (pm x0) (0 pm x) for some real x. Here is an example plotsol(bp2d(resx[10], resp[10]))","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We could use the solutions saved in resp, resx as initial guesses for a call to continuation but we turn to a different method.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"tip: Solutions\nThe brute force method provided all solutions in a neighborhood of the bifurcation point.","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"info: Advanced computation\nInstead of using brute force and computing the vector field on a grid. One can rely on IntervalConstraintProgramming.jl to do better using bisection. See also this discourse post where the same example is treated by D. P. Sanders. ","category":"page"},{"location":"tutorials/mittelmann/#Branch-switching-with-deflated-newton-(manual)","page":"🟤 2d generalized Bratu–Gelfand problem","title":"Branch switching with deflated newton (manual)","text":"","category":"section"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"At this stage, we know what happens at the 2d bifurcation point of the curve of homogeneous solutions. We chose another method based on Deflated problems. We want to find all nearby solutions of the problem close to this bifurcation point. This is readily done by trying several initial guesses in a brute force manner:","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"out = zeros(Nx*Ny)\n# deflation operator to\ndeflationOp = DeflationOperator(2, 1.0, [zeros(Nx*Ny)])\n\n# options for the newton solver\noptdef = setproperties(opt_newton; tol = 1e-8, max_iterations = 100)\n\n# eigen-elements close to the second bifurcation point on the branch\n# of homogeneous solutions\nvp, ve, _, _= eigls(JFmit(out, @set par_mit.λ = br.specialpoint[2].param), 5)\n\nfor ii=1:length(ve)\n\toutdef1 = newton(\n\t\tre_make(prob,\n\t\t # initial guess for newton\n\t\t u0 = br.specialpoint[2].x .+ 0.01 .* real.(ve[ii]) .* (1 .+ 0.01 .* rand(Nx*Ny)),\n\t\t params = (@set par_mit.λ = br.specialpoint[2].param + 0.005)),\n deflationOp,\n\t\toptdef)\n\t\tBK.converged(outdef1) && push!(deflationOp, outdef1.u)\nend","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"This provides length(deflationOp) = 5 solutions as there are some symmetries in the problem. For example plotsol(deflationOp[5]) gives","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"We can continue this solution as follows in one direction","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"brdef1 = continuation(\n\tre_make(prob,\n\t u0 = deflationOp[3],\n params = (@set par_mit.λ = br.specialpoint[2].param + 0.005)),\n PALC(),\n\tsetproperties(opts_br;ds = -0.001, detect_bifurcation = 3, dsmax = 0.01, max_steps = 500);\n\tkwargsC...)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"If we repeat the above loop but before the branch point by using @set par_mit.λ = br.specialpoint[2].param + 0.005, we get 3 new solutions that we can continue","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"brdef2 = continuation(\n re_make(prob,\n u0 = deflationOp[5],\n params = (@set par_mit.λ = br.specialpoint[2].param + 0.005)),\n PALC(),\n\tsetproperties(opts_br;ds = 0.001, detect_bifurcation = 3, dsmax = 0.01);\n\tkwargsC...)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"thereby providing the following bifurcation diagram with plot(br,br1,br2,brdef1, brdef2,plotfold=false, putbifptlegend = false)","category":"page"},{"location":"tutorials/mittelmann/","page":"🟤 2d generalized Bratu–Gelfand problem","title":"🟤 2d generalized Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/#sh3d","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Pages = [\"tutorialsSH3d.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"info: Why this example?\nThis example is challenging because we cannot employ the easy to use \\ sparse linear solver which takes too much time/memory to do the LU decomposition. Hence, one has to be tricky to devise a preconditioned linear solver that does not explode the memory budget. But then, one has to also devise a specific eigensolver. This is done in this tutorial. It also shows how this can be used for automatic branch switching. Hence, if you are not happy with the linear / eigen solvers in BifurcationKit.jl, this is perhaps the example you are looking for.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We look at the following PDE on a 3d domain, e.g. a cube:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"-(I+Delta)^2 u+lcdot u +nu u^2-u^3 = 0tagE","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"with Neumann boundary conditions. We use a Sparse Matrix to express the operator L_1equiv(I+Delta)^2. However, compared to the 2d case (see 2d Swift-Hohenberg equation: snaking), we cannot use directly \\ to solve linear systems because the LU décomposition is a bit slow, it uses a lot of memory.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We start by defining the associated functional to encode (E).","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"using Revise, Parameters, KrylovKit\nusing GLMakie # must be imported before BifurcationKit to trigger some imports\nusing BifurcationKit\nusing LinearAlgebra, SparseArrays, LinearMaps, DiffEqOperators, Setfield\nconst BK = BifurcationKit\n\nfunction Laplacian3D(Nx, Ny, Nz, lx, ly, lz, bc = :Neumann)\n\tspeye(n) = sparse(I, n, n)\n\thx = 2lx/Nx; hy = 2ly/Ny; hz = 2lz/Nz\n\tD2x = CenteredDifference{1}(2, 2, hx, Nx)\n\tD2y = CenteredDifference{1}(2, 2, hy, Ny)\n\tD2z = CenteredDifference{1}(2, 2, hz, Nz)\n\tQx = Neumann0BC(hx); Qy = Neumann0BC(hy); Qz = Neumann0BC(hz)\n\n\t_A = kron(speye(Ny), sparse(D2x * Qx)[1]) + kron(sparse(D2y * Qy)[1], speye(Nx))\n\tA = kron(speye(Nz), _A) + kron(kron(sparse(D2z * Qz)[1], speye(Ny)), speye(Nx))\n\treturn sparse(A), D2x\nend\n\n# main functional\nfunction F_sh(u, p)\n\t@unpack l, ν, L1 = p\n\treturn -(L1 * u) .+ (l .* u .+ ν .* u.^2 .- u.^3)\nend\n\n# differential of the functional\nfunction dF_sh(u, p, du)\n\t@unpack l, ν, L1 = p\n\treturn -(L1 * du) .+ (l .+ 2 .* ν .* u .- 3 .* u.^2) .* du\nend\n\n# various differentials\nd2F_sh(u, p, dx1, dx2) = (2 .* p.ν .* dx2 .- 6 .* dx2 .* u) .* dx1\nd3F_sh(u, p, dx1, dx2, dx3) = (-6 .* dx2 .* dx3) .* dx1\n\n# these types are useful to switch to GPU\nTY = Float64\nAF = Array{TY}","category":"page"},{"location":"tutorials/tutorialsSH3d/#Plotting-with-Makie","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Plotting with Makie","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"In most tutorials, we have used Plots.jl for the figures. However, it appears that Makie.jl is more convenient for 3d plots. We thus define the following convenience functions to display the solutions of (E).","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"contour3dMakie(x; k...) = GLMakie.contour(x; k...)\ncontour3dMakie(x::AbstractVector; k...) = contour3dMakie(reshape(x,Nx,Ny,Nz); k...)\n\ncontour3dMakie(ax, x; k...) = (GLMakie.contour(ax, x; k...))\ncontour3dMakie(ax, x::AbstractVector; k...) = contour3dMakie(ax, reshape(x,Nx,Ny,Nz); k...)\n\ncontour3dMakie!(ax, x; k...) = (GLMakie.contour!(ax, x; k...))\ncontour3dMakie!(ax, x::AbstractVector; k...) = contour3dMakie!(ax, reshape(x,Nx,Ny,Nz); k...)","category":"page"},{"location":"tutorials/tutorialsSH3d/#Setting-up-the-problem","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Setting up the problem","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We provide the parameters defining the PDE:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Nx = Ny = Nz = 22; N = Nx*Ny*Nz\nlx = ly = lz = pi\n\nX = -lx .+ 2lx/(Nx) * collect(0:Nx-1)\nY = -ly .+ 2ly/(Ny) * collect(0:Ny-1)\nZ = -lz .+ 2lz/(Nz) * collect(0:Nz-1)\n\n# initial guess for newton\nsol0 = [(cos(x) .* cos(y )) for x in X, y in Y, z in Z]\n\tsol0 .= sol0 .- minimum(vec(sol0))\n\tsol0 ./= maximum(vec(sol0))\n\tsol0 .*= 1.7\n\n# parameters for PDE\nΔ, D2x = Laplacian3D(Nx, Ny, Nz, lx, ly, lz, :Neumann);\nL1 = (I + Δ)^2;\npar = (l = 0.1, ν = 1.2, L1 = L1);","category":"page"},{"location":"tutorials/tutorialsSH3d/#Choice-of-linear-solver","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Choice of linear solver","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Let us run a quick benchmark to evaluate the direct linear solvers:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"julia> @time cholesky(L1) \\ sol_hexa;\n 0.152849 seconds (54 allocations: 87.273 MiB)\n\njulia> @time lu(L1) \\ sol_hexa;\n 0.556157 seconds (87 allocations: 226.210 MiB, 0.49% compilation time)\n\njulia> @time qr(L1) \\ sol_hexa;\n 1.609175 seconds (8.96 k allocations: 989.285 MiB, 2.67% gc time, 0.67% compilation time)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Hence, cholesky is the big winner but it requires a positive matrix so let's see how to do that.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"As said in the introduction, the LU linear solver does not scale well with dimension N. Hence, we do something else. We note that the matrix L_1 is hermitian positive and use it as a preconditioner. Thus, we pre-factorize it using a Cholesky decomposition:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Pr = cholesky(L1);\nusing SuiteSparse\n# we need this \"hack\" to be able to use Pr as a preconditioner.\nLinearAlgebra.ldiv!(o::Vector, P::SuiteSparse.CHOLMOD.Factor{Float64}, v::Vector) = o .= -(P \\ v)\n\n# rtol must be small enough to pass the Fold points and to get precise eigenvalues\n# we know that the jacobian is symmetric so we tell the solver\nls = GMRESKrylovKit(verbose = 0, rtol = 1e-9, maxiter = 150, ishermitian = true, Pl = Pr)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"Let's try this on a Krylov-Newton computation to refine the guess sol0:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"prob = BifurcationProblem(F_sh, AF(vec(sol0)), par, (@lens _.l),\n\tJ = (x, p) -> (dx -> dF_sh(x, p, dx)),\n\tplot_solution = (ax, x, p) -> contour3dMakie(ax, x),\n\trecord_from_solution = (x, p) -> (n2 = norm(x), n8 = norm(x, 8)))\n\noptnew = NewtonPar(verbose = true, tol = 1e-8, max_iterations = 20, linsolver = ls)\nsol_hexa = @time newton(prob, optnew)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"which gives","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 2.6003e+02 │ 0 │\n│ 1 │ 1.5414e+02 │ 25 │\n│ 2 │ 2.6040e+02 │ 21 │\n│ 3 │ 7.3531e+01 │ 21 │\n│ 4 │ 2.0513e+01 │ 23 │\n│ 5 │ 6.4608e+00 │ 18 │\n│ 6 │ 1.3743e+00 │ 18 │\n│ 7 │ 1.7447e-01 │ 17 │\n│ 8 │ 4.0924e-03 │ 17 │\n│ 9 │ 2.4048e-06 │ 17 │\n│ 10 │ 1.8389e-10 │ 17 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.405419 seconds (1.22 M allocations: 205.788 MiB, 2.16% gc time, 18.84% compilation time)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"and contour3dMakie(sol_hexa) produces","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/#Continuation-and-bifurcation-points","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Continuation and bifurcation points","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We now switch gears and compute the stability of the trivial solution u=0. We will then branch from the detected bifurcation points. However, we wish to show an example of computation of eigenvalues based on a custom preconditioned Shift-Invert strategy.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We thus define our eigensolver based on the previously defined pre-conditioned linear solver ls:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"# structure to hold eigensolver\nstruct SH3dEig{Ts, Tσ} <: BK.AbstractEigenSolver\n\t# linear solver used for Shift-Invert strategy\n\tls::Ts\n\t# shift of the linear operator\n\tσ::Tσ\nend\n\n# function to extract eigenvectors, used for automatic branch switching\nBifurcationKit.geteigenvector(eigsolve::SH3dEig, vecs, n::Union{Int, Array{Int64,1}}) = vecs[n]\n\n# implementation of Shift-invert strategy\nfunction (sheig::SH3dEig)(J, nev::Int; verbosity = 0, kwargs...)\n\tσ = sheig.σ\n\tnv = 30\n\tJshift = du -> J(du) .- σ .* du\n\tA = du -> sheig.ls(Jshift, du)[1]\n\t# we adapt the krylov dimension as function of the requested eigenvalue number\n\tvals, vec, info = KrylovKit.eigsolve(A, AF(rand(Nx*Ny*Nz)), nev, :LM;\n\t\t tol = 1e-12, maxiter = 20, verbosity = verbosity, ishermitian = true,\n\t\t krylovdim = max(nv, nev + nv))\n\tvals2 = 1 ./vals .+ σ\n\tInd = sortperm(vals2, by = real, rev = true)\n\treturn vals2[Ind], vec[Ind], true, info.numops\nend","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We can then declare our eigensolver and pass it to the newton parameters","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"eigSH3d = SH3dEig((@set ls.rtol = 1e-9), 0.1)\n@set! optnew.eigsolver = eigSH3d","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We are now ready to perform continuation and detection of bifurcation points:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"optcont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= -0.001, p_max = 0.15,\n\tp_min = -.1, newton_options = setproperties(optnew; tol = 1e-9, maxIter = 15),\n\tmax_steps = 146, detect_bifurcation = 3, nev = 15, n_inversion = 4, plot_every_step = 1)\n\nbr = continuation( re_make(prob, u0 = zeros(N)),\n # we use a particular bordered linear solver to\n # take advantage of our specific linear solver\n PALC(bls = BorderingBLS(solver = optnew.linsolver, check_precision = false)),\n optcont;\n normC = x -> norm(x, Inf),\n\tplot = true, verbosity = 3)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"The following result shows the detected bifurcation points (its takes ~300s)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"julia> br\nBranch number of points: 34\nBranch of Equilibrium\nParameters l from 0.1 to -0.1\nBifurcation points:\n (ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`)\n- # 1, bp at l ≈ +0.06243495 ∈ (+0.06243495, +0.06287689), |δp|=4e-04, [converged], δ = (-1, 0), step = 8, eigenelements in eig[ 9], ind_ev = 10\n- # 2, nd at l ≈ +0.06069653 ∈ (+0.06069653, +0.06069826), |δp|=2e-06, [converged], δ = (-6, 0), step = 9, eigenelements in eig[ 10], ind_ev = 9\n- # 3, nd at l ≈ -0.00007046 ∈ (-0.00007046, +0.00015051), |δp|=2e-04, [converged], δ = (-3, 0), step = 18, eigenelements in eig[ 19], ind_ev = 3","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We get the following plot during computation:","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorialsSH3d/#Automatic-branch-switching","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"Automatic branch switching","text":"","category":"section"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"warning: Computation time\nThe following computation takes ~1.5h","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We can use Branch switching to compute the different branches emanating from the bifurcation points. For example, the following code will perform automatic branch switching from the last bifurcation point of br. Note that this bifurcation point is 3d.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"br1 = @time continuation(br, 3, setproperties(optcont; save_sol_every_step = 10,\n\tdetect_bifurcation = 0, p_max = 0.1, plot_every_step = 5, dsmax = 0.02);\n\tplot = true, verbosity = 3,\n\t# to set initial point on the branch\n\tδp = 0.01,\n\t# remove display of deflated newton iterations\n\tverbosedeflation = false,\n\talg = PALC(tangent = Bordered()),\n\tlinear_algo = BorderingBLS(solver = optnew.linsolver, check_precision = false),\n\t# to compute the normal form, so we don't have to\n\t# compute the left eigenvectors\n\tissymmetric = true,\n\tplot_solution = (ax, x, p) -> contour3dMakie(ax, x),\n\trecord_from_solution = (x, p) -> (n2 = norm(x), n8 = norm(x, 8)),\n\tnormC = x -> norm(x, Inf))","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"We can then plot the branches using BK.plotBranch(br, branches...) where green (resp. red) means stable (resp. unstable) solution.","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"There are 19 banches that were discovered. You can plot the solutions on the branches using","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"fig = Figure(resolution = (1200, 900))\n\tfor i=1:length(br1)\n\t\tix = div(i,5)+1; iy = i%5+1\n\t\t@show i, ix, iy\n\t\tax = Axis3(fig[ix, iy], title = \"$i\", aspect = (1, 1, 1))\n\t\thidedecorations!(ax, grid=false)\n\t\tcontour3dMakie!(ax, br1[i].sol[2].x)\n\t\tax.protrusions = (0, 0, 0, 10)\n\tend\n\tdisplay(fig)","category":"page"},{"location":"tutorials/tutorialsSH3d/","page":"🟠 3d Swift-Hohenberg equation, Finite differences","title":"🟠 3d Swift-Hohenberg equation, Finite differences","text":"(Image: )","category":"page"},{"location":"periodicOrbit/#Periodic-orbits-computation","page":"Introduction","title":"Periodic orbits computation","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"Consider the Cauchy problem","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"fracdudt=F(up)","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"A periodic solution with period T satisfies","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"beginalign\nfracdudt=F(up)\nu(0)=u(T)\nendalign","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"We provide 4 methods for computing periodic orbits (PO):","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"one (Trapezoid) based on finite differences to discretize a Cauchy problem,\none (Collocation) based on orthogonal collocation to discretize a Cauchy problem,\ntwo (Shooting) based on the flow associated to a Cauchy problem.","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"It is important to understand the pro and cons of each method to compute PO in large dimensions.","category":"page"},{"location":"periodicOrbit/#Trapezoid-method","page":"Introduction","title":"Trapezoid method","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The Trapezoid method (or the Collocation one) is usually faster than the ones based on Shooting but it requires more memory as it saves the whole orbit. However the main drawback of this method is that the associated linear solver is not \"nice\", being composed of a cyclic matrix for which no generic Matrix-free preconditioner is known. Hence, the Trapezoid method is often used with an ILU preconditioner which is severely constrained by memory. Also, when the period of the cycle is large, finer time discretization (or mesh adaptation which is not yet implemented) must be employed which is also a limiting factor both in term of memory and preconditioning.","category":"page"},{"location":"periodicOrbit/#Collocation-method","page":"Introduction","title":"Collocation method","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The Collocation method is (for now) the slowest of the three methods implemented for computing periodic orbits. However, it is by far the most precise one. Additionally, the mesh can be automatically adapted during the continuation. The implementation will be improved for large dimensional systems like the Trapezoid method one.","category":"page"},{"location":"periodicOrbit/#Shooting-method","page":"Introduction","title":"Shooting method","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The methods based on Shooting do not share the same drawbacks because the associated linear system is usually well conditioned, at least in the simple shooting case. There are thus often used without preconditioner at all. Even in the case of multiple shooting, this can be alleviated by a simple generic preconditioner based on deflation of eigenvalues (see Linear solvers (LS)). Also, the time stepper will automatically adapt to the stiffness of the problem, putting more time points where needed unlike the method based on finite differences which requires an adaptive (time) meshing to provide a similar property. Finally, we can use parallel Shooting to greatly increase the speed of computation.","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The main drawback of the method is to find a fast time stepper, at least to compete with the method based on finite differences. The other drawback is the precision of the method which cannot compete with the collocation method.","category":"page"},{"location":"periodicOrbit/#Important-notes","page":"Introduction","title":"Important notes","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"We regroup here some important notes which are valid for all methods above. ","category":"page"},{"location":"periodicOrbit/#.-Accessing-the-periodic-orbit","page":"Introduction","title":"1. Accessing the periodic orbit","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"In record_from_solution, plot_solution or after the computation of a branch of periodic orbits, how do I obtain the periodic orbit, for plotting purposes for example? If x is the solution from newton for the parameter p, you can obtain the periodic orbit as follows","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"xtt = get_periodic_orbit(x, p)","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"where xtt.t contains the time mesh and xtt[:,:] contains the different components. Note that for Trapezoid and collocation methods, calling get_periodic_orbit is essentially free as it is a reshape of x. However, in the case of Shooting methods, this requires recomputing the periodic orbit which can be costly for large scale problems.","category":"page"},{"location":"periodicOrbit/#.-Finaliser","page":"Introduction","title":"2. Finaliser","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"If you pass a finalise_solution function to continuation, the following occurs:","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"If the newton solve was successful, we update the phase condition every update_section_every_step\nwe call the user defined finalizer finalise_solution","category":"page"},{"location":"periodicOrbit/#.-Record-from-solution","page":"Introduction","title":"3. Record from solution","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"You can pass your own function to continuation. In the particular case of periodic orbits, the method is called like record_from_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem. You can then obtain the current periodic orbit using (see above)","category":"page"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"xtt = get_periodic_orbit(x, opt.p)","category":"page"},{"location":"periodicOrbit/#.-Plot-solution","page":"Introduction","title":"4. Plot solution","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"Similarly to record_from_solution, the method is called like plot_solution(x, opt; k...) where opt.p is the current value of the continuation parameter and opt.prob is the current state of the continuation problem.","category":"page"},{"location":"periodicOrbit/#.-Most-precise-method-for-Floquet-coefficients","page":"Introduction","title":"5. Most precise method for Floquet coefficients","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbit/#.-Misc","page":"Introduction","title":"6. Misc","text":"","category":"section"},{"location":"periodicOrbit/","page":"Introduction","title":"Introduction","text":"set_params_po generate_ci_problem generate_solution","category":"page"},{"location":"nonsimplebp/#Non-simple-branch-point","page":"Non-simple branch point","title":"Non-simple branch point","text":"","category":"section"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"unknown: References\nThe general method is exposed in Golubitsky, Martin, David G Schaeffer, and Ian Stewart. Singularities and Groups in Bifurcation Theory. New York: Springer-Verlag, 1985, VI.1.d page 295","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"tip: Example\nAn example of use of the methods presented here is provided in 2d generalized Bratu–Gelfand problem. ","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"We expose our method to study non-simple branch points. Such branch point (x_0p_0) for the problem F(xp)=0 satisfies d=dim ker dF(x_0p_0) 1 and the eigenvalues have zero imaginary part. At such point, we can apply Lyapunov-Schmidt reduction to transform the initial problem in large dimensions to a d-dimensional polynomial equation, called the reduced equation.","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"More precisely, it is possible to write x = u + v where uin ker dF(x_0p_0) and vapprox 0 belongs to a vector space complement of ker dF(x_0p_0). It can be shown that u solves Phi(udelta p)=0 with Phi(udelta p) = (I-Pi)F(u+psi(udelta p)p_0+delta p) where psi is known implicitly and Pi is the spectral projector on ker dF(x_0p_0). Fortunately, one can compute the Taylor expansion of Phi up to order 3. Computing the bifurcation diagram of this d-dimensional multivariate polynomials can be done using brute force methods.","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"Once the zeros of Phi have been located, we can use them as initial guess for continuation but for the original F !!","category":"page"},{"location":"nonsimplebp/#Reduced-equation-computation","page":"Non-simple branch point","title":"Reduced equation computation","text":"","category":"section"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"The reduced equation (E) can be automatically computed as follows","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. It returns a point with all requested information:","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"mutable struct NdBranchPoint{Tv, T, Tevl, Tevr, Tnf} <: BranchPoint\n\t\"bifurcation point\"\n\tx0::Tv\n\n\t\"Parameter value at the bifurcation point\"\n\tp::T\n\n\t\"Right eigenvectors\"\n\tζ::Tevr\n\n\t\"Left eigenvectors\"\n\tζstar::Tevl\n\n\t\"Normal form coefficients\"\n\tnf::Tnf\n\n\t\"Type of bifurcation point\"\n\ttype::Symbol\nend","category":"page"},{"location":"nonsimplebp/#Using-the-reduced-equation","page":"Non-simple branch point","title":"Using the reduced equation","text":"","category":"section"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"Once a branch point has been computed bp = get_normal_form(...), you can do all sort of things. ","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"For example, quoted from the file test/testNF.jl, you can print the 2d reduced equation as follows:","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"julia> BifurcationKit.nf(bp2d)\n2-element Array{String,1}:\n \" + (3.23 + 0.0im) * x1 * p + (-0.123 + 0.0im) * x1^3 + (-0.234 + 0.0im) * x1 * x2^2\"\n \" + (-0.456 + 0.0im) * x1^2 * x2 + (3.23 + 0.0im) * x2 * p + (-0.123 + 0.0im) * x2^3\"","category":"page"},{"location":"nonsimplebp/","page":"Non-simple branch point","title":"Non-simple branch point","text":"You can evaluate the reduced equation as bp2d(Val(:reducedForm), rand(2), 0.2). This can be used to find all the zeros of the reduced equation by sampling on a grid or using a general solver like Roots.jl. \nFinally, given a d-dimensional vector x and a parameter delta p, you can have access to an initial guess u (see above) by calling bp2d(rand(2), 0.1)","category":"page"},{"location":"tutorials/tutorials1b/#Temperature-model-with-ApproxFun,-no-AbstractArray","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"Pages = [\"tutorials1b.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We reconsider the example Temperature model by relying on the package ApproxFun.jl which allows very precise function approximation. This is an interesting example because we have to change the scalar product of PALC for the method to work well.","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"This is one example where the state space, the space of solutions to the nonlinear equation, is not a subtype of AbstractArray. See Requested methods for Custom State for more informations.","category":"page"},{"location":"tutorials/tutorials1b/#Code-for-custom-state","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"Code for custom state","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We start with some imports:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"using ApproxFun, LinearAlgebra, Parameters, Setfield\n\nusing BifurcationKit, Plots\nconst BK = BifurcationKit","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We then need to add some methods not available in ApproxFun because the state space is not a subtype of AbstractArray:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"# specific methods for ApproxFun\nimport Base: eltype, similar, copyto!, length\nimport LinearAlgebra: mul!, rmul!, axpy!, axpby!, dot, norm\n\nsimilar(x::ApproxFun.Fun, T) = (copy(x))\nsimilar(x::ApproxFun.Fun) = copy(x)\nmul!(w::ApproxFun.Fun, v::ApproxFun.Fun, α) = (w .= α * v)\n\neltype(x::ApproxFun.Fun) = eltype(x.coefficients)\nlength(x::ApproxFun.Fun) = length(x.coefficients)\n\ndot(x::ApproxFun.Fun, y::ApproxFun.Fun) = sum(x * y)\n\naxpy!(a, x::ApproxFun.Fun, y::ApproxFun.Fun) = (y .= a * x + y)\naxpby!(a::Float64, x::ApproxFun.Fun, b::Float64, y::ApproxFun.Fun) = (y .= a * x + b * y)\nrmul!(y::ApproxFun.Fun, b::Float64) = (y.coefficients .*= b; y)\nrmul!(y::ApproxFun.Fun, b::Bool) = b == true ? y : (y.coefficients .*= 0; y)\n\ncopyto!(x::ApproxFun.Fun, y::ApproxFun.Fun) = ( (x.coefficients = copy(y.coefficients);x))","category":"page"},{"location":"tutorials/tutorials1b/#Problem-formulation","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"Problem formulation","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We can easily write our functional with boundary conditions in a convenient manner using ApproxFun:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"N(x; a = 0.5, b = 0.01) = 1 + (x + a*x^2)/(1 + b*x^2)\ndN(x; a = 0.5, b = 0.01) = (1-b*x^2+2*a*x)/(1+b*x^2)^2\n\nfunction F_chan(u, p)\n\t@unpack α, β, Δ = p\n\treturn [Fun(u(0.), domain(u)) - β,\n\t\tFun(u(1.), domain(u)) - β,\n\t\tΔ * u + α * N(u, b = β)]\nend\n\nfunction Jac_chan(u, p)\n\t@unpack α, β, Δ = p\n\treturn [Evaluation(u.space, 0.),\n\t\tEvaluation(u.space, 1.),\n\t\tΔ + α * dN(u, b = β)]\nend","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We want to call a Newton solver. We first need an initial guess and the Laplacian operator:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"sol = Fun(x -> x * (1-x), Interval(0.0, 1.0))\nΔ = Derivative(sol.space, 2)\n# set of parameters\npar_af = (α = 3., β = 0.01, Δ = Δ)\n\nprob = BifurcationProblem(F_chan, sol, par_af, (@lens _.α); J = Jac_chan, plot_solution = (x, p; kwargs...) -> plot!(x; label = \"l = $(length(x))\", kwargs...))","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"Finally, we need to provide some parameters for the Newton iterations. This is done by calling","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"optnewton = NewtonPar(tol = 1e-12, verbose = true)","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We call the Newton solver:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"out = @time BK.newton(prob, optnewton, normN = x -> norm(x, Inf64))","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"and you should see","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.5707e+00 │ 0 │\n│ 1 │ 1.1546e-01 │ 1 │\n│ 2 │ 8.0149e-04 │ 1 │\n│ 3 │ 3.9038e-08 │ 1 │\n│ 4 │ 7.9049e-13 │ 1 │\n└─────────────┴──────-───────────────┴────────────────┘\n 0.103869 seconds (362.15 k allocations: 14.606 MiB)","category":"page"},{"location":"tutorials/tutorials1b/#Continuation","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"Continuation","text":"","category":"section"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"We can also perform numerical continuation with respect to the parameter alpha. Again, we need to provide some parameters for the continuation:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"optcont = ContinuationPar(dsmin = 0.0001, dsmax = 0.05, ds= 0.005, p_max = 4.1, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, max_iterations = 20, verbose = true), detect_bifurcation = 0, max_steps = 200)","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"Then, we can call the continuation routine.","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"# we need a specific bordered linear solver\n# we use the BorderingBLS one to rely on ApproxFun.\\\nbr = continuation(prob, PALC(bls = BorderingBLS(solver = optnewton.linsolver, check_precision = false)), optcont,\n\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> plot!(x; label = \"l = $(length(x))\", kwargs...),\n\tverbosity = 2,\n\tnormC = x -> norm(x, Inf64))","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"and you should see","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"However, if we do that, we'll see that it does not converge very well. The reason is that the default arc-length constraint (see Pseudo arclength continuation) is","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"N(x p)=fracthetatext length(x)leftlangle x-x_0 d x_0rightrangle+(1-theta) cdotleft(p-p_0right) cdot d p_0-d s=0","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"is tailored for vectors of fixed length. The frac1length(x) is added to properly balance the terms in the constraint. Thus, in BifurcationKit, the dot product is in fact (x,y) -> dot(x,y) / length(y).","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"But here, the vector space is provided with a custom dot product (see above) which depends on the domain, here Interval(0.0, 1.0). Hence, we want to change this constraint N for the following:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"N(x p)=thetaleftlangle x-x_0 d x_0rightrangle+(1-theta) cdotleft(p-p_0right) cdot d p_0-d s=0","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"This can be done as follows:","category":"page"},{"location":"tutorials/tutorials1b/","page":"🟡 Temperature model with ApproxFun, no AbstractArray","title":"🟡 Temperature model with ApproxFun, no AbstractArray","text":"optcont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 4.1, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, maxIter = 20, verbose = true), max_steps = 300, θ = 0.2, detect_bifurcation = 0)\n\nbr = continuation(prob, PALC(bls=BorderingBLS(solver = optnewton.linsolver, check_precision = false)), optcont,\n\tplot = true,\n\t# specify the dot product used in PALC\n\tdotPALC = BK.DotTheta(dot),\n\t# we need a specific bordered linear solver\n\t# we use the BorderingBLS one to rely on ApproxFun.\\\n\tlinear_algo = BorderingBLS(solver = DefaultLS(), check_precision = false),\n\tplot_solution = (x, p; kwargs...) -> plot!(x; label = \"l = $(length(x))\", kwargs...),\n\tverbosity = 2,\n\tnormC = x -> norm(x, Inf64))","category":"page"},{"location":"DeflatedContinuation/#Deflated-Continuation","page":"Deflated continuation","title":"Deflated Continuation","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"unknown: References\nFarrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. The Computation of Disconnected Bifurcation Diagrams. ArXiv:1603.00809 [Math], March 2, 2016. http://arxiv.org/abs/1603.00809.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"Deflated continuation allows to compute branches of solutions to the equation F(xp)=0. It is based on the Deflated Newton (see Deflated problems) algorithm.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"See DefCont for more information.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"However, unlike the regular continuation method, deflated continuation allows to compute disconnected bifurcation diagrams, something that is impossible for our Automatic Bifurcation diagram computation which is limited to the connected component of the initial point.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"You can find an example of use of the method in Carrier Problem. We reproduce below the result of the computation which shows various disconnected components arising form Fold bifurcations that are found seemingly by the method.","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"(Image: )","category":"page"},{"location":"DeflatedContinuation/#Algorithm","page":"Deflated continuation","title":"Algorithm","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"Input: Initial parameter value λmin.\nInput: Final parameter value λmax > λmin. Input: Step size ∆λ > 0.\nInput: Nonlinear residual f(u,λ).\nInput: Deflation operator M(u; u∗).\nInput: Initial solutions S(λmin) to f(·,λmin).\nλ ← λmin\nwhile λ < λmax do\n\tF(·) ← f(·,λ+∆λ) \t\t\t\t\t\t# Fix the value of λ to solve for.\n\tS(λ+∆λ) ← ∅\n\tfor u0 ∈ S(λ) do \t\t\t\t\t\t# Continue known branches.\n\t\tapply Newton’s method to F from initial guess u0.\n\t\tif solution u∗ found then\n\t\t\tS(λ + ∆λ) ← S(λ + ∆λ) ∪ {u∗} # Record success\n\t\t\tF(·) ← M(·;u∗)F(·)\t\t\t # Deflate solution\n\n\tfor u0 ∈ S(λ) do \t\t\t\t\t # Seek new branches.\n\t\tsuccess ← true\n\t\twhile success do\n\t\t\tapply Newton’s method to F from initial guess u0.\n\t\t\tif solution u∗ found then\t\t # New branch found\n\t\t\t\tS(λ + ∆λ) ← S(λ + ∆λ) ∪ {u∗} # Record success\n\t\t\t\tF(·) ← M(·;u∗)F(·)\t\t # Deflate solution\n\t\telse\n\t\t\tsuccess ← false\n\tλ←λ+∆λ\nreturn S","category":"page"},{"location":"DeflatedContinuation/#Tips","page":"Deflated continuation","title":"Tips","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"The following piece of information is valuable in order to get the algorithm working in various conditions (see also here) especially for small systems (e.g. dim<20):","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"newton is quite good and it is convenient to limit it otherwise it will be able to bypass the deflation. For example, you can use maxIter = 10 in NewtonPar\ntry to limit the newton residual by using the argument callback_newton = BifurcationKit.cbMaxNorm(1e7). This will likely remove the occurrence of ┌ Error: Same solution found for identical parameter value!!\nfinally, you can try some aggressive shift (here 0.01 in the deflation operator, like DeflationOperator(2, dot, 0.01, [sol]) but use it wisely.","category":"page"},{"location":"DeflatedContinuation/#Basic-example","page":"Deflated continuation","title":"Basic example","text":"","category":"section"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"We show a quick and simple example of use. Note in particular that the algorithm is able to find the disconnected branch. The starting points are marked with crosses","category":"page"},{"location":"DeflatedContinuation/","page":"Deflated continuation","title":"Deflated continuation","text":"using BifurcationKit, LinearAlgebra, Setfield, SparseArrays, Plots\nconst BK = BifurcationKit\n\nk = 2\nN = 1\nF(x, p) = @. p * x + x^(k+1)/(k+1) + 0.01\nJac_m(x, p) = diagm(0 => p .+ x.^k)\n\n# bifurcation problem\nprob = BifurcationProblem(F, [0.], 0.5, (@lens _), J = Jac_m)\n\n# continuation options\nopts = BK.ContinuationPar(dsmax = 0.051, dsmin = 1e-3, ds=0.001, max_steps = 140, p_min = -3., newton_options = NewtonPar(tol = 1e-8), save_eigenvectors = false)\n\n# algorithm\nalg = BK.DefCont(deflation_operator = DeflationOperator(2, .001, [[0.]]), perturb_solution = (x,p,id) -> (x .+ 0.1 .* rand(length(x))))\n\nbrdc = continuation(prob, alg,\n\tContinuationPar(opts, ds = -0.001, max_steps = 800, newton_options = NewtonPar(verbose = false, max_iterations = 6), plot_every_step = 40),\n\t; plot=true, verbosity = 0,\n\tcallback_newton = BK.cbMaxNorm(1e3) # reject newton step if residual too large\n\t)\nplot(brdc)","category":"page"},{"location":"Predictors/#Predictors-Correctors","page":"Predictors / correctors","title":"Predictors - Correctors","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"The continuation method works with the following pattern (see [Allgower1990]):","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"compute tangent\ncall predictor (based on tangent, mostly)\ncall corrector","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"[Allgower1990]: Allgower and Georg, Numerical Continuation Methods, 1990","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"There are several couples predictor-tangent/corrector which can be used in BifurcationKit.jl as we now explain. The tangent computation is formally included in the predictor whereas it is a distinct function in the code.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"info: Corrector\nNote that setting the predictor also sets the corresponding corrector: it selects the couple predictor-corrector. You don't have (in fact cannot) set them independently.","category":"page"},{"location":"Predictors/#.-Natural,-zeroth-order-predictor","page":"Predictors / correctors","title":"1. Natural, zeroth order predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This is the dumbest predictor based on the formula (x_1p_1) = (x_0 p_0 + ds) with Newton corrector ; it fails at Turning points. This is set by the algorithm Natural() in continuation. For matrix based jacobian, it is not faster than the pseudo-arclength predictor because the factorisation of the jacobian is cached. For Matrix-free methods, this predictor can be faster than the following ones until it hits a Turning point.","category":"page"},{"location":"Predictors/#.-First-order-predictor","page":"Predictors / correctors","title":"2. First order predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This predictor is based on a computation of the tangent tau = (dxdp) to the curve of solutions, it is given by (x_1p_1) = (x_0p_0) + dscdot tau. This predictor passes Turning points when used with PALC Newton corrector. BifurcationKit.jl provides two ways to compute the tangent (dx dp).","category":"page"},{"location":"Predictors/#a.-Secant-predictor","page":"Predictors / correctors","title":"2a. Secant predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This predictor is called secant and is parametrized by the algorithm PALC(tangent = Secant()) in continuation with Secant . It is computed by (dx dp) = (z_1 p_1) - (z_0 p_0) and normalized by the norm (x p)^2_theta = fracthetalength(x) langle xxrangle + (1 - theta)cdot p^2.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"warning: Parameter `θ`\nThe parameter θ in the struct ContinuationParis very important. It should be tuned for the continuation to work properly especially in the case of large problems where the langle x - x_0 dx_0rangle component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint N involves the term 1-θ.","category":"page"},{"location":"Predictors/#b.-Bordered-predictor","page":"Predictors / correctors","title":"2b. Bordered predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This predictor departs from the previous one in the way the tangent is estimated. It computes (dx dp) by solving solving the bordered linear system beginbmatrix F_x F_p\t fracthetalength(x)dx_0 (1-theta)dp_0endbmatrixbeginbmatrixdx dpendbmatrix =beginbmatrix0 1endbmatrix.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"It is set by the algorithm PALC(tangent = Bordered()) in continuation with Bordered. The linear solver for the linear problem in (dx dp) is set by the option bls in PALC: it is one of Bordered linear solvers (BLS).","category":"page"},{"location":"Predictors/#.-Polynomial-predictor","page":"Predictors / correctors","title":"3. Polynomial predictor","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"The polynomial predictor is based on a fit (least square regression) of an nth-order polynomial P on the last k solution vectors, where n k. The arclength s is used for the polynomial which then fits the solution (x_ip_is_i) as P(s_i)approx (x_ip_i). To keep s in suitable range (see [Waugh]), we rescale it as sto fracs-bar ssigma where sigma is the standard deviation of the s_i.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This algorithm is parametrized by alg = Polynomial(Fred, n, k, v0) where pred::AbstractTangentComputation is the tangent predictor used only for the first k solutions before the polynomial predictor is operational and v0 is an example of guess. More information is available in Polynomial.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"[Waugh]: Waugh, Illingworth, and Juniper, “Matrix-Free Continuation of Limit Cycles for Bifurcation Analysis of Large Thermoacoustic Systems.”","category":"page"},{"location":"Predictors/#.-Multiple-predictor-(aka-pmcont-in-pde2path)","page":"Predictors / correctors","title":"4. Multiple predictor (aka pmcont in pde2path)","text":"","category":"section"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"The predictor is designed [Uecker2014] to avoid spurious branch switching and pass singular points especially in PDE where branch point density can be quite high. It is based on the use of many predictors with increasing \"jumps\" (x_ip_i) = (x_0p_0) + icdot dscdot tau ileq nb and use a corrector (PALC Newton) with the following twist. The criterion is that in each Newton step, the residual has to decrease by a factor 0alpha1:","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":" F(u_np_n)leq alpha F(u_n-1p_n-1) ","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"otherwise the corrector fails. The solution that is returned is the one for the highest i. We refer to [Uecker2014] for an exposition of the step size adaption strategy.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"This algorithm is parametrized by alg = Multiple(pred, x0, α, nb) where τ is an initial tangent vector (used to set the types) and pred::PALC is a predictor. The default value is pred = PALC(). More information is available in Multiple.","category":"page"},{"location":"Predictors/","page":"Predictors / correctors","title":"Predictors / correctors","text":"[Uecker2014]: 1.Uecker, H. pde2path - A Matlab Package for Continuation and Bifurcation in 2D Elliptic Systems. NMTMA 7, 58–106 (2014).","category":"page"},{"location":"tutorials/tutorials3b/#bruss","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Pages = [\"tutorials3b.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"unknown: References\nThis example is taken from Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust, 1997.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"info: Goal\nThe goal of this tutorial is to show similar computations as in the previous tutorial but without using the automatic branch switching tools. This is for the experienced used who wants to dive more in the internals of the package. ","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We look at the Brusselator in 1d. The equations are as follows","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"beginaligned frac partial X partial t = frac D _ 1 l ^ 2 frac partial ^ 2 X partial z ^ 2 + X ^ 2 Y - ( β + 1 ) X + α frac partial Y partial t = frac D _ 2 l ^ 2 frac partial ^ 2 Y partial z ^ 2 + β X - X ^ 2 Y endaligned","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"with Dirichlet boundary conditions","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"beginarray l X ( t z = 0 ) = X ( t z = 1 ) = α Y ( t z = 0 ) = Y ( t z = 1 ) = β α endarray","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"These equations have been introduced to reproduce an oscillating chemical reaction. There is an obvious equilibrium (α β α). Here, we consider bifurcations with respect to the parameter l.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We start by writing the PDE","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"using Revise\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Setfield, Parameters\nconst BK = BifurcationKit\n\nf1(u, v) = u * u * v\n\nfunction Fbru!(f, x, p, t = 0)\n\t@unpack α, β, D1, D2, l = p\n\tn = div(length(x), 2)\n\th2 = 1.0 / n^2\n\tc1 = D1 / l^2 / h2\n\tc2 = D2 / l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\t# Dirichlet boundary conditions\n\tf[1] = c1 * (α\t - 2u[1] + u[2] ) + α - (β + 1) * u[1] + f1(u[1], v[1])\n\tf[end] = c2 * (v[n-1] - 2v[n] + β / α)\t\t\t + β * u[n] - f1(u[n], v[n])\n\n\tf[n] = c1 * (u[n-1] - 2u[n] + α ) + α - (β + 1) * u[n] + f1(u[n], v[n])\n\tf[n+1] = c2 * (β / α - 2v[1] + v[2])\t\t\t + β * u[1] - f1(u[1], v[1])\n\n\tfor i=2:n-1\n\t\t f[i] = c1 * (u[i-1] - 2u[i] + u[i+1]) + α - (β + 1) * u[i] + f1(u[i], v[i])\n\t\tf[n+i] = c2 * (v[i-1] - 2v[i] + v[i+1])\t\t\t + β * u[i] - f1(u[i], v[i])\n\tend\n\treturn f\nend\n\nFbru(x, p, t = 0) = Fbru!(similar(x), x, p, t)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"For computing periodic orbits, we will need a Sparse representation of the Jacobian:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"function Jbru_sp(x, p)\n\t@unpack α, β, D1, D2, l = p\n\t# compute the Jacobian using a sparse representation\n\tn = div(length(x), 2)\n\th = 1.0 / n; h2 = h*h\n\n\tc1 = D1 / p.l^2 / h2\n\tc2 = D2 / p.l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\tdiag = zeros(eltype(x), 2n)\n\tdiagp1 = zeros(eltype(x), 2n-1)\n\tdiagm1 = zeros(eltype(x), 2n-1)\n\n\tdiagpn = zeros(eltype(x), n)\n\tdiagmn = zeros(eltype(x), n)\n\n\t@. diagmn = β - 2 * u * v\n\t@. diagm1[1:n-1] = c1\n\t@. diagm1[n+1:end] = c2\n\n\t@. diag[1:n] = -2c1 - (β + 1) + 2 * u * v\n\t@. diag[n+1:2n] = -2c2 - u * u\n\n\t@. diagp1[1:n-1] = c1\n\t@. diagp1[n+1:end] = c2\n\n\t@. diagpn = u * u\n\treturn spdiagm(0 => diag, 1 => diagp1, -1 => diagm1, n => diagpn, -n => diagmn)\nend\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"tip: Tip\nWe could have used DiffEqOperators.jl like for the Swift-Hohenberg tutorial.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We shall now compute the equilibria and their stability.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"n = 500\n\n# parameters of the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\n\n# bifurcation problem\nprobBif = BK.BifurcationProblem(Fbru, sol0, par_bru, (@lens _.l);\n J = Jbru_sp,\n plot_solution = (x, p; kwargs...) -> (plotsol(x; label=\"\", kwargs... )),\n record_from_solution = (x, p) -> x[div(n,2)])\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"For the eigensolver, we use a Shift-Invert algorithm (see Eigen solvers (Eig))","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"eigls = EigArpack(1.1, :LM)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We continue the trivial equilibrium to find the Hopf points","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"opt_newton = NewtonPar(eigsolver = eigls, tol = 1e-9)\nopts_br_eq = ContinuationPar(dsmin = 0.001, dsmax = 0.01, ds = 0.001,\n\tp_max = 1.9, detect_bifurcation = 3, nev = 21,\n\tnewton_options = opt_newton, max_steps = 1000,\n\t# specific options for precise localization of Hopf points\n\tn_inversion = 6)\n\nbr = continuation(probBif, PALC(),opts_br_eq, verbosity = 0, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We obtain the following bifurcation diagram with 3 Hopf bifurcation points","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"scene = plot(br)","category":"page"},{"location":"tutorials/tutorials3b/#Normal-form-computation","page":"🟠 1d Brusselator","title":"Normal form computation","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We can compute the normal form of the Hopf points as follows","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"hopfpt = get_normal_form(br, 1)","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-Hopf-points","page":"🟠 1d Brusselator","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We use the bifurcation points guesses located in br.specialpoint to turn them into precise bifurcation points. For the second one, we have","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# index of the Hopf point in br.specialpoint\nind_hopf = 2\n\n# newton iterations to compute the Hopf point\nhopfpoint = newton(br, ind_hopf; normN = norminf)\nBK.converged(hopfpoint) && printstyled(color=:red, \"--> We found a Hopf Point at l = \", hopfpoint.u.p[1], \", ω = \", hopfpoint.u.p[2], \", from l = \", br.specialpoint[ind_hopf].param, \"\\n\")","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We now perform a Hopf continuation with respect to the parameters l, β","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"tip: Tip\nYou don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)\nbr_hopf = continuation(br, ind_hopf, (@lens _.β), optcdim2, normC = norminf, jacobian_ma = :minaug)\nscene = plot(br_hopf)","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-periodic-orbits-(Finite-differences)","page":"🟠 1d Brusselator","title":"Continuation of periodic orbits (Finite differences)","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Here, we perform continuation of periodic orbits branching from the Hopf bifurcation points.We need an educated guess for the periodic orbit which is given by guess_from_hopf:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# number of time slices\nM = 51\n\nl_hopf, Th, orbitguess2, hopfpt, vec_hopf = BK.guess_from_hopf(br, ind_hopf,\n\topts_br_eq.newton_options.eigsolver,\n\tM, 2.7; phase = 0.25)\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We wish to make two remarks at this point. The first is that an initial guess is composed of a space time solution and of the guess for the period Th of the solution. Note that the argument 2.7 is a guess for the amplitude of the orbit.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# orbit initial guess from guess_from_hopf, is not a vector, so we reshape it\norbitguess_f2 = reduce(vcat, orbitguess2)\norbitguess_f = vcat(vec(orbitguess_f2), Th) |> vec\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"The second remark concerns the phase 0.25 written above. To account for the additional unknown (i.e. the period), periodic orbit localisation using Finite Differences requires an additional constraint (see Periodic orbits based on Trapezoidal rule for more details). In the present case, this constraint is","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":" u(0) - u_hopf phi = 0","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"where u_{hopf} is the equilibrium at the Hopf bifurcation and phi is real.(vec_hopf) where vec_hopf is the eigenvector. This is akin to a Poincaré section. We do not put any constraint on u(t) albeit this is possible (see Periodic orbits based on Trapezoidal rule.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"The phase of the periodic orbit is set so that the above constraint is satisfied. We shall now use Newton iterations to find a periodic orbit.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Given our initial guess, we create a (family of) problem which encodes the functional associated to finding Periodic orbits based on Trapezoidal rule (see Periodic orbits based on Trapezoidal rule for more information):","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"poTrap = PeriodicOrbitTrapProblem(\n\tprobBif, \t\t # pass the bifurcation problem\n\treal.(vec_hopf),\t # used to set ϕ, see the phase constraint\n\thopfpt.u, # used to set uhopf, see the phase constraint\n\tM, 2n; # number of time slices\n\tjacobian = :FullSparseInplace) # jacobian of PO functional\t\t\t \n\nnothing #hide \t","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"To evaluate the functional at x, you call it like a function: poTrap(x, par) for the parameter par.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"note: Using the functional for deflation, Fold of limit cycles...\nThe functional poTrap gives you access to the underlying methods to call a regular newton. For example the functional is x -> poTrap(x, par) at parameter par. The (sparse) Jacobian at (x,p) is computed like this poTrap(Val(:JacFullSparse), x, p) while the Matrix Free version is dx -> poTrap((x, p, dx). This also allows you to call the newton deflated method (see Deflated problems) or to locate Fold point of limit cycles see PeriodicOrbitTrapProblem. You can also use preconditioners. In the case of more computationally intense problems (like the 2d Brusselator), this might be mandatory as using LU decomposition for the linear solve will use too much memory. See also the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"For convenience, we provide a simplified newton / continuation methods for periodic orbits. One has just to pass a PeriodicOrbitTrapProblem.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# we use the linear solver LSFromBLS to speed up the computations\nopt_po = NewtonPar(tol = 1e-10, verbose = true, max_iterations = 14, linsolver = BK.LSFromBLS())\n\n# we set the parameter values\npoTrap = @set poTrap.prob_vf.params = (@set par_bru.l = l_hopf + 0.01)\n\noutpo_f = @time newton(poTrap, orbitguess_f, opt_po, normN = norminf)\nBK.converged(outpo_f) && printstyled(color=:red, \"--> T = \", outpo_f.u[end], \", amplitude = \", BK.amplitude(outpo_f.u, n, M; ratio = 2),\"\\n\")\n# plot of the periodic orbit\nBK.plot_periodic_potrap(outpo_f.u, n, M; ratio = 2)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"and obtain","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.5225e-03 │ 0 │\n│ 1 │ 2.6324e-03 │ 2 │\n│ 2 │ 3.0558e-04 │ 2 │\n│ 3 │ 5.7499e-05 │ 2 │\n│ 4 │ 2.0407e-06 │ 2 │\n│ 5 │ 2.8184e-09 │ 2 │\n│ 6 │ 8.3969e-14 │ 2 │\n└─────────────┴──────────────────────┴────────────────┘\n 3.210008 seconds (77.85 k allocations: 2.497 GiB, 5.42% gc time)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Finally, we can perform continuation of this periodic orbit using the specialized call continuationPOTrap","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"opt_po = @set opt_po.eigsolver = EigArpack(; tol = 1e-5, v0 = rand(2n))\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.03, ds= 0.01,\n\tp_max = 3.0, max_steps = 20,\n\tnewton_options = opt_po, nev = 5, tol_stability = 1e-8, detect_bifurcation = 0)\n\nbr_po = continuation(poTrap,\n\toutpo_f.u, PALC(),\n\topts_po_cont;\n\tverbosity = 2,\tplot = true,\n\tplot_solution = (x, p;kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...),\n\tnormC = norminf)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/tutorials3b/#Deflation-for-periodic-orbit-problems","page":"🟠 1d Brusselator","title":"Deflation for periodic orbit problems","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Looking for periodic orbits branching of bifurcation points, it is very useful to use newton algorithm with deflation. We thus define a deflation operator (see previous example)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"deflationOp = DeflationOperator(2, (x,y) -> dot(x[1:end-1], y[1:end-1]), 1.0, [zero(orbitguess_f)])","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"which allows to find periodic orbits different from orbitguess_f. Note that the dot product removes the last component, i.e. the period of the cycle is not considered during this particular deflation. We can now use","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"outpo_f = @time newton(poTrap, orbitguess_f, deflationOp, opt_po; normN = norminf)","category":"page"},{"location":"tutorials/tutorials3b/#Floquet-coefficients","page":"🟠 1d Brusselator","title":"Floquet coefficients","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"A basic method for computing Floquet coefficients based on the eigenvalues of the monodromy operator is available (see FloquetQaD). It is precise enough to locate bifurcations. Their computation is triggered like in the case of a regular call to continuation:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"opt_po = @set opt_po.eigsolver = DefaultEig()\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.04, ds= -0.01, p_max = 3.0, max_steps = 200, newton_options = opt_po, nev = 5, tol_stability = 1e-6, detect_bifurcation = 3)\nbr_po = @time continuation(poTrap, outpo_f.u, PALC(),\n\topts_po_cont; verbosity = 3, plot = true,\n\tplot_solution = (x, p;kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...), normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"A more complete diagram can be obtained combining the methods (essentially deflation and Floquet) described above. It shows the period of the periodic orbits as function of l. See example/brusselator.jl for more information.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"danger: Floquet multipliers computation\nThe computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of the eigensolver. Nevertheless, note that for most implemented eigensolvers in the current Package, the proper option is set when the computation of Floquet multipliers is requested.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"tip: Performances\nThis example is clearly not optimized because we wanted to keep it simple. We can use a Matrix-Free version of the functional and preconditioners to speed this up. Floquet multipliers could also be computed in a Matrix-Free manner. See examples/brusselator.jl for more efficient methods. See also 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS) for a more advanced example where we introduce those methods.","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-periodic-orbits-(Standard-Shooting)","page":"🟠 1d Brusselator","title":"Continuation of periodic orbits (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Note that what follows is not really optimized on the DifferentialEquations.jl side. Indeed, we do not use automatic differentiation, we do not pass the sparsity pattern,...","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We now turn to a different method based on the flow of the Brusselator. To compute this flow (time stepper), we need to be able to solve the differential equation (actually a PDE) associated to the vector field Fbru. We will show how to do this with an implicit method Rodas4P from DifferentialEquations.jl. Note that the user can pass its own time stepper but for convenience, we use the ones in DifferentialEquations.jl. More information regarding the shooting method is contained in Periodic orbits based on the shooting method.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"n = 100\n\n# different parameters to define the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\nprobBif = re_make(probBif, u0 = sol0)\n\neigls = EigArpack(1.1, :LM)\nopts_br_eq = ContinuationPar(dsmin = 0.001, dsmax = 0.00615, ds = 0.0061, p_max = 1.9,\n\tdetect_bifurcation = 3, nev = 21, plot_every_step = 50,\n\tnewton_options = NewtonPar(eigsolver = eigls, tol = 1e-9), max_steps = 1060)\n\nbr = @time continuation(probBif, PALC(), opts_br_eq, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We need to create a guess for the periodic orbit. We proceed as previously:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# number of time slices\nM = 5\n\n# index of the Hopf point in the branch br\nind_hopf = 1\n\nl_hopf, Th, orbitguess2, hopfpt, vec_hopf = BK.guess_from_hopf(br, ind_hopf,\n\topts_br_eq.newton_options.eigsolver, M, 22*0.075)\n#\norbitguess_f2 = reduce(hcat, orbitguess2)\norbitguess_f = vcat(vec(orbitguess_f2), Th) |> vec","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Let us now initiate the Standard Shooting method. To this aim, we need to provide a guess of the periodic orbit at times TM_sh where T is the period of the cycle and M_sh is the number of slices along the periodic orbits. If M_sh = 1, this the Standard Simple Shooting and the Standard Multiple one otherwise. See ShootingProblem for more information.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"dM = 2\norbitsection = Array(orbitguess_f2[:, 1:dM:M])\n\n# the last component is an estimate of the period of the cycle.\ninitpo = vcat(vec(orbitsection), 3.0)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Finally, we need to build a problem which encodes the Shooting functional. This done as follows where we first create the time stepper. For performance reasons, we rely on SparseDiffTools","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"using DifferentialEquations, DiffEqOperators, SparseDiffTools, SparseArrays\n\nFOde(f, x, p, t) = Fbru!(f, x, p)\n\nu0 = sol0 .+ 0.01 .* rand(2n)\n\n# parameter close to the Hopf bifurcation point\npar_hopf = (@set par_bru.l = l_hopf + 0.01)\n\njac_prototype = Jbru_sp(ones(2n), @set par_bru.β = 0)\njac_prototype.nzval .= ones(length(jac_prototype.nzval))\n_colors = matrix_colors(jac_prototype)\nvf = ODEFunction(FOde; jac_prototype = jac_prototype, colorvec = _colors)\nprob = ODEProblem(vf, sol0, (0.0, 520.), par_bru)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We create the parallel standard shooting problem:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# this encodes the functional for the Shooting problem\nprobSh = ShootingProblem(\n\t# we pass the ODEProblem encoding the flow and the time stepper\n\tprob, Rodas4P(),\n\n\t# this is for the phase condition, you can pass your own section as well\n\t[orbitguess_f2[:,ii] for ii=1:dM:M];\n\n\t# enable threading\n\tparallel = true,\n\n\t# these are options passed to the ODE time stepper\n\tabstol = 1e-10, reltol = 1e-8,\n\n # parameter axis\n lens = (@lens _.l),\n\n # parameters\n par = par_hopf,\n\n # jacobian of the periodic orbit functional\n jacobian = BK.FiniteDifferencesMF())","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We are now ready to call newton","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"ls = GMRESIterativeSolvers(reltol = 1e-7, N = length(initpo), maxiter = 100)\noptn_po = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 20, linsolver = ls)\noutpo = @time newton(probSh, initpo, optn_po; normN = norminf)\nplot(initpo[1:end-1], label = \"Init guess\")\nplot!(outpo.u[1:end-1], label = \"sol\")","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"which gives (note that we did not have a really nice guess...)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.9613e-01 │ 0 │\n│ 1 │ 5.6101e-02 │ 45 │\n│ 2 │ 1.0307e-01 │ 49 │\n│ 3 │ 4.1119e-03 │ 48 │\n│ 4 │ 8.0511e-03 │ 49 │\n│ 5 │ 3.8250e-02 │ 48 │\n│ 6 │ 9.8080e-03 │ 49 │\n│ 7 │ 2.1179e+01 │ 53 │\n│ 8 │ 2.0105e+00 │ 36 │\n│ 9 │ 2.0545e+00 │ 49 │\n│ 10 │ 4.8793e-01 │ 49 │\n│ 11 │ 4.8457e-02 │ 46 │\n│ 12 │ 2.3299e-02 │ 49 │\n│ 13 │ 1.6365e-02 │ 48 │\n│ 14 │ 1.3534e-04 │ 49 │\n│ 15 │ 1.4582e-05 │ 48 │\n│ 16 │ 1.5886e-08 │ 49 │\n│ 17 │ 1.7228e-11 │ 49 │\n└─────────────┴──────────────────────┴────────────────┘\n 9.706977 seconds (7.61 M allocations: 13.964 GiB, 3.62% gc time)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"and","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Note that using Simple Shooting, the convergence is much faster. Indeed, running the code above with dM = 10 gives:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.1712e-03 │ 0 │\n│ 1 │ 3.4465e-03 │ 6 │\n│ 2 │ 1.0516e-01 │ 8 │\n│ 3 │ 7.4614e-03 │ 6 │\n│ 4 │ 1.6620e-03 │ 7 │\n│ 5 │ 3.9589e-04 │ 7 │\n│ 6 │ 4.3043e-05 │ 8 │\n│ 7 │ 1.7232e-06 │ 8 │\n│ 8 │ 8.0455e-09 │ 8 │\n│ 9 │ 3.9453e-11 │ 8 │\n└─────────────┴──────────────────────┴────────────────┘\n 0.612070 seconds (217.21 k allocations: 523.069 MiB, 4.83% gc time)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"info: Convergence and speedup\nThe convergence is much worse for the multiple shooting than for the simple one. This is reflected above in the number of linear iterations made during the newton solve. The reason for this is because of the cyclic structure of the jacobian which impedes GMRES from converging fast. This can only be resolved with an improved GMRES which we'll provide in the future.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Finally, we can perform continuation of this periodic orbit using a specialized version of continuation:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# note the eigensolver computes the eigenvalues of the monodromy matrix. Hence\n# the dimension of the state space for the eigensolver is 2n\nopts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 1.5,\n\tmax_steps = 500, newton_options = (@set optn_po.tol = 1e-7), nev = 25,\n\ttol_stability = 1e-8, detect_bifurcation = 0)\n\nbr_po = @time continuation(probSh, outpo.u, PALC(),\n\topts_po_cont; verbosity = 2,\n\t# specific bordered linear solver\n\tlinear_algo = MatrixFreeBLS(@set ls.N = ls.N+1),\n\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], length(1:dM:M); kwargs...),\n\trecord_from_solution = (u, p) -> u[end], normC = norminf)","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We can observe that simple shooting is faster but the Floquet multipliers are less accurate than for multiple shooting. Also, when the solution is very unstable, simple shooting can have spurious branch switching. Finally, note the 0=log 1 eigenvalue of the monodromy matrix in the graph below.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/#Continuation-of-periodic-orbits-(Poincaré-Shooting)","page":"🟠 1d Brusselator","title":"Continuation of periodic orbits (Poincaré Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We now turn to another Shooting method, namely the Poincaré one. We can provide this method thanks to the unique functionalities of DifferentialEquations.jl. More information is provided at PoincareShootingProblem and Periodic orbits based on the shooting method but basically, it is a shooting method between Poincaré sections Sigma_i (along the orbit) defined by hyperplanes. As a consequence, the dimension of the unknowns is M_shcdot(N-1) where N is the dimension of the phase space. Indeed, each time slice lives in an hyperplane Sigma_i. Additionally, the period T is not an unknown of the method but rather a by-product. However, the method requires the time stepper to find when the flow hits an hyperplane Sigma_i, something called event detection.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We show how to use this method, the code is very similar to the case of the Standard Shooting. We first define the functional for Poincaré Shooting Problem","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# sub-sampling factor of a initial guess for the periodic orbit\ndM = 5\n\n# vectors to define the hyperplanes Sigma_i\nnormals = [Fbru(orbitguess_f2[:,ii], par_hopf)/(norm(Fbru(orbitguess_f2[:,ii], par_hopf))) for ii = 1:dM:M]\ncenters = [orbitguess_f2[:,ii] for ii = 1:dM:M]\n\n# functional to hold the Poincare Shooting Problem\nprobHPsh = PoincareShootingProblem(\n\t# ODEProblem, ODE solver used to compute the flow\n\tprob, Rodas4P(),\n\n\t# parameters for the Poincaré sections\n\tnormals, centers;\n\n\t# enable threading\n\tparallel = true,\n\n\t# Parameters passed to the ODE solver\n\tabstol = 1e-10, reltol = 1e-8,\n\n # parameter axis\n lens = (@lens _.l),\n\n # parameters\n par = par_hopf,\n\n # jacobian of the periodic orbit functional\n jacobian = BK.FiniteDifferencesMF())","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"Let us now compute an initial guess for the periodic orbit, it must live in the hyperplanes Sigma_i. Fortunately, we provide projections on these hyperplanes.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# projection of the initial guess on the hyperplanes. We assume that the centers[ii]\n# form the periodic orbit initial guess.\ninitpo_bar = reduce(vcat, BK.projection(probHPsh, centers))","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We can now call continuation to get the first branch.","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"# eigen / linear solver\neig = EigKrylovKit(tol= 1e-12, x₀ = rand(2n-1), dim = 40)\nls = GMRESIterativeSolvers(reltol = 1e-11, N = length(vec(initpo_bar)), maxiter = 500)\n\n# newton options\noptn = NewtonPar(verbose = true, tol = 1e-9, max_iterations = 140, linsolver = ls)\n\n# continuation options\nopts_po_cont_floquet = ContinuationPar(dsmin = 0.0001, dsmax = 0.05, ds= 0.001,\n\tp_max = 2.5, max_steps = 500, nev = 10,\n\ttol_stability = 1e-5, detect_bifurcation = 3, plot_every_step = 3)\nopts_po_cont_floquet = @set opts_po_cont_floquet.newton_options =\n\tNewtonPar(linsolver = ls, eigsolver = eig, tol = 1e-9, verbose = true)\n\n# continuation run\nbr_po = @time continuation(probHPsh, vec(initpo_bar), PALC(),\n\topts_po_cont_floquet; verbosity = 3,\n\tlinear_algo = MatrixFreeBLS(@set ls.N = ls.N+1),\n\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot!(x; label=\"\", kwargs...),\n\tnormC = norminf)\t\t","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"We also obtain the following information:","category":"page"},{"location":"tutorials/tutorials3b/","page":"🟠 1d Brusselator","title":"🟠 1d Brusselator","text":"julia> br_po\nBranch number of points: 41\nBifurcation points:\n- # 1, bp at p ≈ 1.20987963 ∈ (1.20128196, 1.20987963), |δp|=9e-03, [converged], δ = ( 1, 0), step = 21, eigenelements in eig[ 22], ind_ev = 1\n- # 2, ns at p ≈ 1.78687615 ∈ (1.77831727, 1.78687615), |δp|=9e-03, [converged], δ = ( 2, 2), step = 30, eigenelements in eig[ 31], ind_ev = 3\n- # 3, pd at p ≈ 1.85103701 ∈ (1.84676466, 1.85103701), |δp|=4e-03, [converged], δ = ( 1, 1), step = 31, eigenelements in eig[ 32], ind_ev = 4\n- # 4, ns at p ≈ 1.87667870 ∈ (1.86813520, 1.87667870), |δp|=9e-03, [converged], δ = ( 2, 2), step = 32, eigenelements in eig[ 33], ind_ev = 6\n","category":"page"},{"location":"bautin/#Normal-form-of-the-Bautin-bifurcation","page":"Bautin","title":"Normal form of the Bautin bifurcation","text":"","category":"section"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"We follow the paper[Kuznetsov] and consider a Cauchy problem","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"dot x=mathbf F(xp)","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"mathbf L q=i omega_0 q quad mathbf L^T p=-i omega_0 p quad langle p qrangle=1","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"Under some conditions, x(t)approx x_0+2Re w(t)q where w satisfies the normal form:","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"dotw=i omega_0 w+frac12 G_21 ww^2+frac112 G_32 ww^4+Oleft(w^6right)tagE","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"The second Lyapunov coefficient is ","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"l_2=frac112 operatornameRe G_32","category":"page"},{"location":"bautin/#Normal-form-computation","page":"Bautin","title":"Normal form computation","text":"","category":"section"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Bautin.","category":"page"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"bautin/#References","page":"Bautin","title":"References","text":"","category":"section"},{"location":"bautin/","page":"Bautin","title":"Bautin","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"tutorials/detonationEngine/#detonation","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"Pages = [\"detonationEngine.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"This is a model of a detonation engine, a new kind of reactor developed for planes. The model[Koch] quantifies the spatio-temporal evolution of a property analogous to specific internal energy, u(xt), on a one dimensional (1D) periodic domain:","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"left\nbegingathered\nfracpartial upartial t=nu_1 fracpartial^2 upartial x^2-u fracpartial upartial x+k q(1-lambda) exp left(fracu-u_calpharight)-epsilon u^2 \nfracpartial lambdapartial t=nu_2 fracpartial^2 lambdapartial x^2+k(1-lambda) exp left(fracu-u_calpharight) -fracs u_p lambda1+exp left(rleft(u-u_pright)right)\nendgatheredright","category":"page"},{"location":"tutorials/detonationEngine/#Problem-discretization","page":"🟠 Detonation engine","title":"Problem discretization","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We start by discretizing the above PDE based on finite differences.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"using Revise, Parameters\nusing DiffEqOperators, ForwardDiff, DifferentialEquations, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\nω(u, p) = p.k * exp((u - p.uc) / p.α)\nβ(u, p) = p.s * p.up /(1 + exp(p.r * (u - p.up)) )\n\n# utilities for plotting solutions\nfunction plotsol!(x; k...)\n\tn = length(x) ÷ 2\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\tplot!(u; label=\"u\", k...)\n\tplot!(v; label=\"λ\", k...)\nend\nplotsol(x; k...) = (plot();plotsol!(x; k...))\n\n# function to build derivative operators\nfunction DiffOp(N, lx; order = 2)\n\th = lx/N\n\n\tD2 = CenteredDifference(2, order, h, N)\n\tD = CenteredDifference(1, order, h, N)\n\n\tQ = PeriodicBC(Float64)\n\n\tΔ = sparse(D2 * Q)[1]\n\tD = sparse(D * Q)[1]\n\treturn D, Δ\nend\n\n# nonlinearity of the model\nfunction NL!(dest, U, p, t = 0.)\n\tN = p.N\n\tu = @view U[1:N]\n\tλ = @view U[N+1:2N]\n\tdest[1:N] .= p.q .* (1 .- λ) .* ω.(u, Ref(p)) .- p.ϵ .* u.^2\n\tdest[N+1:2N] .= (1 .- λ) .* ω.(u, Ref(p)) .- λ .* β.(u, Ref(p))\n\treturn dest\nend\n\n# function which encodes the right hand side of the PDE\n@views function Fdet!(f, u, p, t = 0)\n\tN = p.N\n\tNL!(f, u, p) \t\t\t\t\t\t# nonlinearity\n\tmul!(f, p.Δ, u, p.ν1, 1) \t\t\t# put Laplacian\n\tf[1:p.N] .-= (p.D * u[1:N].^2) ./ 2\t# add drift a la Burger\n\treturn f\nend\nNL(U, p, t = 0.) = NL!(similar(U), U, p, t)\nJNL(U, p, t = 0.) = ForwardDiff.jacobian(x -> NL(x, p), U)\nFdet(x, p, t = 0) = Fdet!(similar(x), x, p, t)\nJdet(x, p) = sparse(ForwardDiff.jacobian(x -> Fdet(x, p), x))\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We can now instantiate the model","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"N = 300\nlx = 2pi\nX = LinRange(0, lx, N)\n\nD, Δ = DiffOp(N, lx)\n_ν1 = 0.0075\n# model parameters\npar_det = (N = N, q = 0.5, α = 0.3, up = 0.0, uc = 1.1, s = 3.5, k = 1., ϵ = 0.15, r = 5.0, ν1 = _ν1, ν2 = _ν1, Δ = blockdiag(Δ, Δ), D = D, Db = blockdiag(D, D))\n\n# initial conditions\nu0 = 0.5ones(N)\nλ0 = 0.5ones(N)\nU0 = vcat(u0, λ0)\nU0cons = vcat(copy(U0), 1.)\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/#Jacobian-with-sparsity-detection","page":"🟠 Detonation engine","title":"Jacobian with sparsity detection","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"Writing the jacobian explicitly is cumbersome. We rely on automatic differentiation to get the sparse jacobian.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"# improved jacobian with sparse coloring\nusing SparseArrays, SparseDiffTools, Test\nconst L1 = copy(Jdet(rand(2N), par_det))\nconst colors = matrix_colors(L1)\nfunction JlgvfColorsAD(J, u, p, colors)\n\tSparseDiffTools.forwarddiff_color_jacobian!(J, (out, x) -> out .= Fdet(x,p), u, colorvec = colors)\n\tJ\nend\nJdetAD(x,p) = JlgvfColorsAD(L1, x, p, colors)\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We are now ready to compute the bifurcation of the trivial (constant in space) solution:","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"# bifurcation problem\nprob = BifurcationProblem(Fdet, U0, setproperties(par_det; q = 0.5), (@lens _.up); J = JdetAD,\n\tplot_solution = (x, p; k...) -> plotsol!(x; k...),\n\trecord_from_solution = (x, p) -> (u∞ = norminf(x[1:N]), n2 = norm(x)))\n\nprob = re_make(prob, params = (@set par_det.up = 0.56))\n\n# iterative eigen solver\neig = EigArpack(0.2, :LM, tol = 1e-13, v0 = rand(2N))\neig = EigArnoldiMethod(sigma=0.2, which = BifurcationKit.LM(),x₀ = rand(2N ))\n\n# newton options\noptnew = NewtonPar(verbose = true, eigsolver = eig)\nsolhomo = newton(prob, optnew; normN = norminf)\noptcont = ContinuationPar(newton_options = setproperties(optnew, verbose = false),\n\tdetect_bifurcation = 3, nev = 50, n_inversion = 8, max_bisection_steps = 25,\n\tdsmax = 0.01, ds = 0.01, p_max = 1.4, max_steps = 1000, plot_every_step = 50)\n\nbr = continuation(\n\t\tre_make(prob, params = (@set par_det.q = 0.5), u0 = solhomo.u),\n\t\tPALC(), optcont; plot = true)\nScene = title!(\"\")","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"br","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We have detected 6 Hopf bifurcations. We now study the periodic orbits branching from them.","category":"page"},{"location":"tutorials/detonationEngine/#Computing-the-branches-of-Travelling-waves","page":"🟠 Detonation engine","title":"Computing the branches of Travelling waves","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"The periodic orbits emanating from the Hopf points look like travelling waves. This is intuitive because the equation is mostly advective as the diffusion coefficients nu_i are small. We will thus seek for travelling waves instead of periodic orbits. The advantage is that the possible Neimark-Sacker bifurcation is transformed into a regular Hopf one which allows the study of modulated travelling waves.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"As we will do the same thing 3 times, we bundle the procedure in functions. We first use the regular Hopf normal form to create a guess for the travelling wave:","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"function getGuess(br, nb; δp = 0.005)\n\tnf = get_normal_form(br, nb; verbose = false)\n\tpred = predictor(nf, δp)\n\treturn pred.p, pred.orbit(0)\nend\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"Using this guess, we can continue the travelling wave as function of a parameter. Note that in the following code, a generalized eigensolver is automatically created during the call to continuation which properly computes the stability of the wave.","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"function computeBranch(br, nb; δp = 0.005, max_steps = 190)\n\t_p, sol = getGuess(br, nb)\n\t# travelling wave problem\n\tprobTW = TWProblem(\n\t\tre_make(br.prob, params = setproperties(getparams(br); up = _p)),\n\t\tgetparams(br).Db,\n\t\tcopy(sol),\n\t\tjacobian = :AutoDiff)\n\t# newton parameters with iterative eigen solver\n\t# eig = EigArnoldiMethod(sigma=0.2, which = BifurcationKit.LM(),x₀ = rand(2N ))\n\teig = EigArpack(nev = 10, which = :LM, sigma = 0.4)\n\toptn = NewtonPar(verbose = true, eigsolver = eig)\n\t# continuation parameters\n\topt_cont_br = ContinuationPar(p_min = 0.1, p_max = 1.3, newton_options = optn, ds= -0.001, dsmax = 0.01, plot_every_step = 5, detect_bifurcation = 3, nev = 10, max_steps = max_steps)\n\t# we build a guess for the travelling wave with speed -0.9\n\ttwguess = vcat(sol, -0.9)\n\tbr_wave = continuation(probTW, twguess, PALC(), opt_cont_br;\n\t\tverbosity = 3, plot = true, bothside = true,\n\t\trecord_from_solution = (x, p) -> (u∞ = maximum(x[1:N]), s = x[end], amp = amplitude(x[1:N])),\n\t\tplot_solution = (x, p; k...) -> (plotsol!(x[1:end-1];k...);plot!(br,subplot=1, legend=false)),\n\t\tcallback_newton = BK.cbMaxNorm(1e2),\n\t\tfinalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\t\tamplitude(z.u[N+1:2N]) > 0.01\n\t\tend,\n\t\t)\nend\nnothing #hide","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"We can try this continuation as follows","category":"page"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"amplitude(x) = maximum(x) - minimum(x)\nbr_wave = computeBranch(br, 1; max_steps = 10)\nScene = title!(\"\")","category":"page"},{"location":"tutorials/detonationEngine/#Building-the-full-diagram","page":"🟠 Detonation engine","title":"Building the full diagram","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"branches = [computeBranch(br, i) for i in 1:3]\nplot(br, branches..., legend=:topleft, xlims = (0.5, 1.25), ylims=(0.5, 2.3))","category":"page"},{"location":"tutorials/detonationEngine/#References","page":"🟠 Detonation engine","title":"References","text":"","category":"section"},{"location":"tutorials/detonationEngine/","page":"🟠 Detonation engine","title":"🟠 Detonation engine","text":"[Koch]: Koch, James, Mitsuru Kurosaka, Carl Knowlen, and J. Nathan Kutz. “Multi-Scale Physics of Rotating Detonation Engines: Autosolitons and Modulational Instabilities.” ArXiv:2003.06655 [Nlin, Physics:Physics], March 14, 2020. http://arxiv.org/abs/2003.06655.","category":"page"},{"location":"tutorials/tutorials1/#temperature","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"","category":"section"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Pages = [\"tutorials1.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"This is a classical example from the Trilinos library.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"This is a simple example in which we aim at solving Delta T+alpha N(Tbeta)=0 with boundary conditions T(0) = T(1)=beta. This example is coded in examples/chan.jl. We start with some imports:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"using BifurcationKit, LinearAlgebra, Plots, Parameters\nconst BK = BifurcationKit\n\nN(x; a = 0.5, b = 0.01) = 1 + (x + a*x^2)/(1 + b*x^2)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We then write our functional:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"function F_chan(x, p)\n\t@unpack α, β = p\n\tf = similar(x)\n\tn = length(x)\n\tf[1] = x[1] - β\n\tf[n] = x[n] - β\n\tfor i=2:n-1\n\t\tf[i] = (x[i-1] - 2 * x[i] + x[i+1]) * (n-1)^2 + α * N(x[i], b = β)\n\tend\n\treturn f\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We want to call a Newton solver. We first need an initial guess:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"n = 101\nsol0 = [(i-1)*(n-i)/n^2+0.1 for i=1:n]\n\n# set of parameters\npar = (α = 3.3, β = 0.01)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Finally, we need to provide some parameters for the Newton iterations. This is done by calling","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"optnewton = NewtonPar(tol = 1e-11, verbose = true)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We call the Newton solver:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"prob = BifurcationProblem(F_chan, sol0, par, (@lens _.α),\n\t# function to plot the solution\n\tplot_solution = (x, p; k...) -> plot!(x; ylabel=\"solution\", label=\"\", k...))\nsol = newton(prob, @set optnewton.verbose=false) # hide\nsol = @time newton( prob, optnewton)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can perform numerical continuation w.r.t. the parameter alpha. This time, we need to provide additional parameters, but now for the continuation method:","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"optcont = ContinuationPar(dsmin = 0.01, dsmax = 0.2, ds= 0.1, p_min = 0., p_max = 4.2,\n\tnewton_options = NewtonPar(max_iterations = 10, tol = 1e-9))\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"Next, we call the continuation routine as follows.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"br = continuation(prob, PALC(), optcont; plot = true)\nnothing #hide\t\t","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"The parameter axis lens = @lens _.α is used to extract the component of par corresponding to α. Internally, it is used as get(par, lens) which returns 3.3.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"You should see","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"scene = title!(\"\") #hide\t\t","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"The left figure is the norm of the solution as function of the parameter p=alpha, the y-axis can be changed by passing a different recordFromSolution to BifurcationProblem. The top right figure is the value of alpha as function of the iteration number. The bottom right is the solution for the current value of the parameter. This last plot can be modified by changing the argument plotSolution to BifurcationProblem.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"note: Bif. point detection\nTwo Fold points were detected. This can be seen by looking at br.specialpoint, by the black\tdots on the continuation plots when doing plot(br, plotfold=true) or by typing br in the REPL. Note that the bifurcation points are located in br.specialpoint.","category":"page"},{"location":"tutorials/tutorials1/#Continuation-of-Fold-points","page":"🟡 Temperature model (codim 2)","title":"Continuation of Fold points","text":"","category":"section"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We get a summary of the branch by doing","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"br","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can take the first Fold point, which has been guessed during the previous continuation run and locate it precisely. However, this only works well when the jacobian is computed analytically. We use automatic differentiation for that","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"# index of the Fold bifurcation point in br.specialpoint\nindfold = 2\n\noutfold = newton(\n\t#index of the fold point\n\tbr, indfold)\nBK.converged(outfold) && printstyled(color=:red, \"--> We found a Fold Point at α = \", outfold.u.p, \", β = 0.01, from \", br.specialpoint[indfold].param,\"\\n\")","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can finally continue this fold point in the plane (α β) by performing a Fold Point continuation. In the present case, we find a Cusp point.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"tip: Tip\nWe don't need to call newton first in order to use continuation for the codim 2 curve of bifurcation points.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"outfoldco = continuation(br, indfold,\n\t# second parameter axis to use for codim 2 curve\n\t(@lens _.β),\n\t# we disable the computation of eigenvalues, it makes little sense here\n\tContinuationPar(optcont, detect_bifurcation = 0))\nscene = plot(outfoldco, plotfold = true, legend = :bottomright)","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"tip: Tip\nThe performances for computing the curve of Fold is not that great. It is because we use the default solver tailored for ODE. If you pass jacobian_ma = :minaug to the last continuation call, you should see a great improvement in performances.","category":"page"},{"location":"tutorials/tutorials1/#Using-GMRES-or-another-linear-solver","page":"🟡 Temperature model (codim 2)","title":"Using GMRES or another linear solver","text":"","category":"section"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We continue the previous example but now using Matrix Free methods. The user can pass its own solver by implementing a version of LinearSolver. Some linear solvers have been implemented from KrylovKit.jl and IterativeSolvers.jl (see Linear solvers (LS) for more information), we can use them here. Note that we can also use preconditioners as shown below. The same functionality is present for the eigensolver.","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"# derivative of N\ndN(x; a = 0.5, b = 0.01) = (1-b*x^2+2*a*x)/(1+b*x^2)^2\n\n# Matrix Free version of the differential of F_chan\n# Very easy to write since we have F_chan.\n# We could use Automatic Differentiation as well\nfunction dF_chan(x, dx, p)\n\t@unpack α, β = p\n\tout = similar(x)\n\tn = length(x)\n\tout[1] = dx[1]\n\tout[n] = dx[n]\n\tfor i=2:n-1\n\t\tout[i] = (dx[i-1] - 2 * dx[i] + dx[i+1]) * (n-1)^2 + α * dN(x[i], b = β) * dx[i]\n\tend\n\treturn out\nend\n\n# we create a new linear solver\nls = GMRESKrylovKit(dim = 100)\n\n# and pass it to the newton parameters\noptnewton_mf = NewtonPar(verbose = true, linsolver = ls, tol = 1e-10)\n\n# we change the problem with the new jacobian\nprob = re_make(prob;\n\t# we pass the differential a x,\n\t# which is a linear operator in dx\n\tJ = (x, p) -> (dx -> dF_chan(x, dx, p))\n\t)\n\n# we can then call the newton solver\nout_mf = @time newton(prob,\toptnewton_mf)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"We can improve this computation, i.e. reduce the number of Linear-Iterations, by using a preconditioner","category":"page"},{"location":"tutorials/tutorials1/","page":"🟡 Temperature model (codim 2)","title":"🟡 Temperature model (codim 2)","text":"using SparseArrays\n\n# define preconditioner which is basically Δ\nP = spdiagm(0 => -2 * (n-1)^2 * ones(n), -1 => (n-1)^2 * ones(n-1), 1 => (n-1)^2 * ones(n-1))\nP[1,1:2] .= [1, 0.];P[end,end-1:end] .= [0, 1.]\n\n# define gmres solver with left preconditioner\nls = GMRESIterativeSolvers(reltol = 1e-4, N = length(sol.u), restart = 10, maxiter = 10, Pl = lu(P))\n\toptnewton_mf = NewtonPar(verbose = true, linsolver = ls, tol = 1e-10)\n\tout_mf = @time newton(prob, optnewton_mf)\nnothing #hide","category":"page"},{"location":"PALC/#Pseudo-arclength-continuation","page":"PALC","title":"Pseudo arclength continuation","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"This is one of the various continuation methods implemented in BifurcationKit.jl. It is set by the option PALC(tangent = Bordered()) or PALC(tangent = Secant()) in continuation. See also PALC for more information.","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"For solving","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"mathbb R^nni F(xp) = 0 quadtagE","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"using a Newton algorithm, we miss an equation. The simplest way is to select an hyperplane in the space mathbb R^ntimes mathbb R passing through (x_0p_0):","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"N(x p) = fracthetan langle x - x_0 dx_0rangle + (1 - theta)cdot(p - p_0)cdot dp_0 - ds = 0tagN","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"with thetain01 and where ds is the pseudo arclength (see [Keller]).","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"warning: Parameter `θ`\nThe parameter θ in the struct ContinuationPar is very important. It should be tuned for the continuation to work properly especially in the case of large problems where the langle x - x_0 dx_0rangle component in the constraint might be favored too much. Also, large θs favour p as the corresponding term in the constraint N involves the term 1-θ.","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"(Image: )","category":"page"},{"location":"PALC/#Predictor","page":"PALC","title":"Predictor","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"The possible predictors are listed in Predictors - Correctors.","category":"page"},{"location":"PALC/#Corrector","page":"PALC","title":"Corrector","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"The corrector is the newton algorithm for finding the roots (xp) of","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"beginbmatrix F(xp) \tN(xp)endbmatrix = 0tagPALC","category":"page"},{"location":"PALC/#Linear-Algebra","page":"PALC","title":"Linear Algebra","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"Let us discuss more about the norm and dot product. First, the option normC continuation specifies the norm used to evaluate the residual in the following way: max(normC(F(xp)) N(xp))tol. It is thus used as a stopping criterion for the corrector. The dot product (resp. norm) used in N and in the (iterative) linear solvers is LinearAlgebra.dot (resp. LinearAlgebra.norm). It can be changed by importing these functions and redefining it. Note that by default, the mathcal L^2 norm is used. These details are important because of the constraint N which incorporates the factor length. For some custom composite type implementing a Vector space, the dot product could already incorporates the length factor in which case you should either redefine the dot product or change theta.","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"The linear solver for the linear problem associated to (PALC) is set by the option linear_algo in continuation: it is one of Bordered linear solvers (BLS).","category":"page"},{"location":"PALC/#Dot-product","page":"PALC","title":"Dot product","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"In the constraint N above, the scalar product is in fact saved in BifurcationKit.jl as dotp(x,y) -> dot(x,y)/length(y). This is used in the bordered linear solvers associated to PALC. If you want to use your own dot product, you can pass","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"dotPALC = BK.DotTheta(mydot),","category":"page"},{"location":"PALC/","page":"PALC","title":"PALC","text":"to continuation. Additionally, you may want to provide the linear operator P such that mydot(x,y) = dot(x, A*y), especially if you intend too use the linear solver MatrixBLS. We refer to BifurcationKit.DotTheta for more details.","category":"page"},{"location":"PALC/#Step-size-control","page":"PALC","title":"Step size control","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"Each time the corrector fails, the step size ds is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.","category":"page"},{"location":"PALC/#References","page":"PALC","title":"References","text":"","category":"section"},{"location":"PALC/","page":"PALC","title":"PALC","text":"[Keller]: Keller, Herbert B. Lectures on Numerical Methods in Bifurcation Problems. Springer, 1988","category":"page"},{"location":"iterator/#Iterator-Interface","page":"Iterator Interface","title":"Iterator Interface","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The iterator interface gives the possibility of stepping through the numerical steps of the continuation procedure. It thus allows to inject custom monitoring function (saving, plotting, bifurcation detection, ...) at will and during the continuation run. In short, it allows to completely re-write the continuation algorithm as one sees fit and this, in a straightforward manner.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The general method continuation is built upon this iterator interface and we refer to the source code for a complete example of use.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"warning: Warning\nThe iterator provided below does not compute eigenvalues nor perform bifurcations detection. ","category":"page"},{"location":"iterator/#Initialization","page":"Iterator Interface","title":"Initialization","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"More information about iterators can be found on the page of julialang.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The interface is set by defining an iterator, pretty much in the same way one calls continuation:","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"iter = ContIterable(prob, alg, opts; kwargs...)","category":"page"},{"location":"iterator/#Stepping","page":"Iterator Interface","title":"Stepping","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"Once an iterator iter has been defined, one can step through the numerical continuation using a for loop:","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"for state in iter\n\tprintln(\"Continuation step = \", state.step)\nend","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The state::ContState has the following description. It is a mutable object which holds the current state of the continuation procedure from which one can step to the next state.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"The for loop stops when done(iter, state) returns false. The condition which is implemented is basically that the number of iterations should be smaller than maxIter, that the parameters should be in (p_min, p_max)...","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"ContState","category":"page"},{"location":"iterator/#BifurcationKit.ContState","page":"Iterator Interface","title":"BifurcationKit.ContState","text":"state = ContState(ds = 1e-4,...)\n\nReturns a variable containing the state of the continuation procedure. The fields are meant to change during the continuation procedure.\n\nArguments\n\nz_pred current solution on the branch\nconverged Boolean for newton correction\nτ tangent predictor\nz previous solution\nitnewton Number of newton iteration (in corrector)\nstep current continuation step\nds step size\nstopcontinuation Boolean to stop continuation\n\nUseful functions\n\ncopy(state) returns a copy of state\ncopyto!(dest, state) returns a copy of state\ngetsolution(state) returns the current solution (x, p)\ngetx(state) returns the x component of the current solution\ngetp(state) returns the p component of the current solution\ngetpreviousp(state) returns the p component of the previous solution\nis_stable(state) whether the current state is stable\n\n\n\n\n\n","category":"type"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"tip: continuation\nYou can also call continuation(iter) to have access to the regular continuation method used throughout the tutorials.","category":"page"},{"location":"iterator/#Basic-example","page":"Iterator Interface","title":"Basic example","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"We show a quick and simple example of use. Note that it is not very optimized because of the use of global variables.","category":"page"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"using BifurcationKit, Plots\nconst BK = BifurcationKit\n\nk = 2\n\n# functional we want to study\nF(x, p) = (@. p + x - x^(k+1)/(k+1))\n\n# bifurcation problem\nprob = BifurcationProblem(F, [0.8], 1., (@lens _))\n\n# parameters for the continuation\nopts = ContinuationPar(dsmax = 0.1, dsmin = 1e-3, ds = -0.001, max_steps = 130, p_min = -3., p_max = 3., newton_options = NewtonPar(tol = 1e-8))\n\n# we define an iterator to hold the continuation routine\niter = BK.ContIterable(prob, PALC(), opts; verbosity = 2)\n\nresp = Float64[]\nresx = Float64[]\n\n# this is the PALC algorithm\nfor state in iter\n\t# we save the current solution on the branch\n\tpush!(resx, getx(state)[1])\n\tpush!(resp, getp(state))\nend\n\n# plot the result\nplot(resp, resx; label = \"\", xlabel = \"p\")","category":"page"},{"location":"iterator/#Additional-information","page":"Iterator Interface","title":"Additional information","text":"","category":"section"},{"location":"iterator/","page":"Iterator Interface","title":"Iterator Interface","text":"If you want to customize the iterator to your needs, perhaps the best source of inspiration is the code of the function continuation!(it::ContIterable, state::ContState, contRes::ContResult) where the iterator is used at its fullest. You will see how the eigen-elements and the stability are computed, how bifurcations are detected and how results are saved.","category":"page"},{"location":"tutorials/tutorials3/#brusauto","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Pages = [\"tutorials3.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"unknown: References\nThis example is taken from Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust, 1997.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We look at the Brusselator in 1d. The equations are as follows","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"beginaligned frac partial X partial t = frac D _ 1 l ^ 2 frac partial ^ 2 X partial z ^ 2 + X ^ 2 Y - ( β + 1 ) X + α frac partial Y partial t = frac D _ 2 l ^ 2 frac partial ^ 2 Y partial z ^ 2 + β X - X ^ 2 Y endaligned","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"with Dirichlet boundary conditions","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"beginarray l X ( t z = 0 ) = X ( t z = 1 ) = α Y ( t z = 0 ) = Y ( t z = 1 ) = β α endarray","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"These equations have been introduced to reproduce an oscillating chemical reaction. There is an obvious equilibrium (α β α). Here, we consider bifurcations with respect to the parameter l.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We start by writing the PDE","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"using Revise\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Setfield, Parameters\nconst BK = BifurcationKit\n\nf1(u, v) = u * u * v\n\nfunction Fbru!(f, x, p, t = 0)\n\t@unpack α, β, D1, D2, l = p\n\tn = div(length(x), 2)\n\th2 = 1.0 / n^2\n\tc1 = D1 / l^2 / h2\n\tc2 = D2 / l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\t# Dirichlet boundary conditions\n\tf[1] = c1 * (α\t - 2u[1] + u[2] ) + α - (β + 1) * u[1] + f1(u[1], v[1])\n\tf[end] = c2 * (v[n-1] - 2v[n] + β / α)\t\t\t + β * u[n] - f1(u[n], v[n])\n\n\tf[n] = c1 * (u[n-1] - 2u[n] + α ) + α - (β + 1) * u[n] + f1(u[n], v[n])\n\tf[n+1] = c2 * (β / α - 2v[1] + v[2])\t\t\t + β * u[1] - f1(u[1], v[1])\n\n\tfor i=2:n-1\n\t\t f[i] = c1 * (u[i-1] - 2u[i] + u[i+1]) + α - (β + 1) * u[i] + f1(u[i], v[i])\n\t\tf[n+i] = c2 * (v[i-1] - 2v[i] + v[i+1])\t\t\t + β * u[i] - f1(u[i], v[i])\n\tend\n\treturn f\nend\n\nFbru(x, p, t = 0) = Fbru!(similar(x), x, p, t)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"For computing periodic orbits, we will need a Sparse representation of the Jacobian:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"function Jbru_sp(x, p)\n\t@unpack α, β, D1, D2, l = p\n\t# compute the Jacobian using a sparse representation\n\tn = div(length(x), 2)\n\th = 1.0 / n; h2 = h*h\n\n\tc1 = D1 / p.l^2 / h2\n\tc2 = D2 / p.l^2 / h2\n\n\tu = @view x[1:n]\n\tv = @view x[n+1:2n]\n\n\tdiag = zeros(eltype(x), 2n)\n\tdiagp1 = zeros(eltype(x), 2n-1)\n\tdiagm1 = zeros(eltype(x), 2n-1)\n\n\tdiagpn = zeros(eltype(x), n)\n\tdiagmn = zeros(eltype(x), n)\n\n\t@. diagmn = β - 2 * u * v\n\t@. diagm1[1:n-1] = c1\n\t@. diagm1[n+1:end] = c2\n\n\t@. diag[1:n] = -2c1 - (β + 1) + 2 * u * v\n\t@. diag[n+1:2n] = -2c2 - u * u\n\n\t@. diagp1[1:n-1] = c1\n\t@. diagp1[n+1:end] = c2\n\n\t@. diagpn = u * u\n\treturn spdiagm(0 => diag, 1 => diagp1, -1 => diagm1, n => diagpn, -n => diagmn)\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"tip: Tip\nWe could have used DiffEqOperators.jl like for the Swift-Hohenberg tutorial instead of writing our laplacian ourselves.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Finally, it will prove useful to have access to the hessian and third derivative","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We shall now compute the equilibria and their stability.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"n = 300\n\n# parameters of the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\n\n# bifurcation problem\nprobBif = BK.BifurcationProblem(Fbru, sol0, par_bru, (@lens _.l);\n J = Jbru_sp,\n plot_solution = (x, p; kwargs...) -> (plotsol(x; label=\"\", kwargs... )),\n record_from_solution = (x, p) -> x[div(n,2)])\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"For the eigensolver, we use a Shift-Invert algorithm (see Eigen solvers (Eig))","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"eigls = EigArpack(1.1, :LM)\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We continue the trivial equilibrium to find the Hopf points","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"opt_newton = NewtonPar(eigsolver = eigls, tol = 1e-9)\nopts_br_eq = ContinuationPar(dsmin = 0.001, dsmax = 0.01, ds = 0.001,\n\tp_max = 1.9, detect_bifurcation = 3, nev = 21,\n\tnewton_options = opt_newton, max_steps = 1000,\n\t# specific options for precise localization of Hopf points\n\tn_inversion = 6)\n\nbr = continuation(probBif, PALC(), opts_br_eq, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We obtain the following bifurcation diagram with 3 Hopf bifurcation points","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"scene = plot(br)","category":"page"},{"location":"tutorials/tutorials3/#Normal-form-computation","page":"🟡 1d Brusselator (automatic)","title":"Normal form computation","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We can compute the normal form of the Hopf points as follows","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"hopfpt = get_normal_form(br, 1)","category":"page"},{"location":"tutorials/tutorials3/#Continuation-of-Hopf-points","page":"🟡 1d Brusselator (automatic)","title":"Continuation of Hopf points","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We use the bifurcation points guesses located in br.specialpoint to turn them into precise bifurcation points. For the second one, we have","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# index of the Hopf point in br.specialpoint\nind_hopf = 2\n\n# newton iterations to compute the Hopf point\nhopfpoint = newton(br, ind_hopf; normN = norminf)\nBK.converged(hopfpoint) && printstyled(color=:red, \"--> We found a Hopf Point at l = \", hopfpoint.u.p[1], \", ω = \", hopfpoint.u.p[2], \", from l = \", br.specialpoint[ind_hopf].param, \"\\n\")","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now perform a Hopf continuation with respect to the parameters l, β","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"tip: Tip\nYou don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)\n\nbr_hopf = continuation(br, ind_hopf, (@lens _.β),\n\toptcdim2, verbosity = 2,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\tjacobian_ma = :minaug, # specific to large dimensions\n\tnormC = norminf)\n\nscene = plot(br_hopf) \t","category":"page"},{"location":"tutorials/tutorials3/#Computation-of-the-branch-of-periodic-orbits-(Finite-differences)","page":"🟡 1d Brusselator (automatic)","title":"Computation of the branch of periodic orbits (Finite differences)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now compute the bifurcated branches of periodic solutions from the Hopf points using Periodic orbits based on Trapezoidal rule. One has just to pass a PeriodicOrbitTrapProblem.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We start by providing a linear solver and some options for the continuation to work","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# automatic branch switching from Hopf point\nopt_po = NewtonPar(tol = 1e-10, verbose = true, max_iterations = 15)\nopts_po_cont = ContinuationPar(dsmin = 0.001,\n\t\tdsmax = 0.04, ds = 0.01,\n\t\tp_max = 2.2,\n\t\tmax_steps = 20,\n\t\tnewton_options = opt_po,\n\t\tsave_sol_every_step = 2,\n\t\tplot_every_step = 1,\n\t\tnev = 11,\n\t\ttol_stability = 1e-6,\n\t\tdetect_bifurcation = 3,\n\t\tdsmin_bisection = 1e-6,\n\t\tmax_bisection_steps = 15,\n\t\tn_inversion = 4)\n\nnothing #hide","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# number of time slices for the periodic orbit\nM = 51\nprobFD = PeriodicOrbitTrapProblem(M = M;\n # specific method for solving linear system\n # of Periodic orbits with trapeze method\n # You could use the default one :FullLU (slower here)\n jacobian = :BorderedSparseInplace)\nbr_po = continuation(\n\t# arguments for branch switching from the first\n\t# Hopf bifurcation point\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont, probFD;\n\t# OPTIONAL parameters\n\t# we want to jump on the new branch at phopf + δp\n\t# ampfactor is a factor to increase the amplitude of the guess\n\tδp = 0.01, ampfactor = 1,\n\t# regular options for continuation\n\tverbosity = 3,\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...),\n\tnormC = norminf)\n\nScene = title!(\"\")","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Using the above call, it is very easy to find the first branches:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We note that there are several branch points (blue points) on the above diagram. This means that there are additional branches in the neighborhood of these points. We now turn to automatic branch switching on these branches. This functionality, as we shall see, is only provided for PeriodicOrbitTrapProblem.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Let's say we want to branch from the first branch point of the first curve pink branch. The syntax is very similar to the previous one:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"br_po2 = continuation(\n\t# arguments for branch switching\n\tbr_po, 1,\n\t# arguments for continuation\n\topts_po_cont;\n\tampfactor = 1., δp = 0.01,\n\tverbosity = 3,\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> heatmap!(reshape(x[1:end-1], 2*n, M)'; ylabel=\"time\", color=:viridis, kwargs...),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"It is now straightforward to get the following diagram","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3/#Computation-of-the-branch-of-periodic-orbits-(Standard-Shooting)","page":"🟡 1d Brusselator (automatic)","title":"Computation of the branch of periodic orbits (Standard Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"Note that what follows is not really optimized on the DifferentialEquations.jl side. Indeed, we do not use automatic differentiation, we do not pass the sparsity pattern, ...","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now turn to a different method based on the flow of the Brusselator. To compute this flow (time stepper), we need to be able to solve the differential equation (actually a PDE) associated to the vector field Fbru. We will show how to do this with an implicit method Rodas4P from DifferentialEquations.jl. Note that the user can pass its own time stepper but for convenience, we use the ones in DifferentialEquations.jl. More information regarding the shooting method is contained in Periodic orbits based on the shooting method.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We then recompute the locus of the Hopf bifurcation points using the same method as above.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"n = 100\n\n# different parameters to define the Brusselator model and guess for the stationary solution\npar_bru = (α = 2., β = 5.45, D1 = 0.008, D2 = 0.004, l = 0.3)\nsol0 = vcat(par_bru.α * ones(n), par_bru.β/par_bru.α * ones(n))\nprobBif = re_make(probBif, u0 = sol0)\n\neigls = EigArpack(1.1, :LM)\nopts_br_eq = ContinuationPar(dsmin = 0.001,\n\t\tdsmax = 0.00615, ds = 0.0061,\n\t\tp_max = 1.9,\n\t\tdetect_bifurcation = 3,\n\t\tnev = 21,\n\t\tplot_every_step = 50,\n\t\tnewton_options = NewtonPar(eigsolver = eigls,\n\t\t\ttol = 1e-9), max_steps = 200)\n\nbr = continuation(probBif, PALC(), opts_br_eq, verbosity = 0, plot = false, normC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We need to build a problem which encodes the Shooting functional. This done as follows where we first create the time stepper:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"using DifferentialEquations, DiffEqOperators\n\nFOde(f, x, p, t) = Fbru!(f, x, p, t)\n\nu0 = sol0 .+ 0.01 .* rand(2n)\n\n# we pass our jacobian function to increase performances\n# an inplace jacobian would be favoured\nvf = ODEFunction(FOde, jac = (J,u,p,t) -> J .= Jbru_sp(u, p), jac_prototype = Jbru_sp(u0, par_bru))\n\n# this is the ODE time stepper when used with `solve`\nprob = ODEProblem(vf, u0, (0., 1000.), par_bru; abstol = 1e-10, reltol = 1e-8)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"tip: Performance\nYou can really speed this up by using the improved ODEProblemusing SparseDiffTools, SparseArrays\njac_prototype = Jbru_sp(ones(2n), par_bru)\njac_prototype.nzval .= ones(length(jac_prototype.nzval))\n_colors = matrix_colors(jac_prototype)\nvf = ODEFunction(FOde; jac_prototype = jac_prototype, colorvec = _colors)\nprobsundials = ODEProblem(vf, u0, (0.0, 520.), par_bru) # gives 0.22s","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We are now ready to call the automatic branch switching. Note how similar it is to the previous section based on finite differences. This case is more deeply studied in the tutorial 1d Brusselator (advanced user). We use a parallel Shooting.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# linear solvers\nls = GMRESIterativeSolvers(reltol = 1e-7, maxiter = 100)\neig = EigKrylovKit(tol= 1e-12, x₀ = rand(2n), dim = 40)\n# newton parameters\noptn_po = NewtonPar(verbose = true, tol = 1e-7, max_iterations = 25, linsolver = ls, eigsolver = eig)\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.03, ds= 0.01, p_max = 2.5, max_steps = 10,\n\tnewton_options = optn_po, nev = 15, tol_stability = 1e-3,\n\tdetect_bifurcation = 0, plot_every_step = 2)\n\nMt = 2 # number of shooting sections\nbr_po = continuation(\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n\t# this is where we tell that we want Parallel Standard Shooting\n\tShootingProblem(Mt, prob, Rodas4P(), abstol = 1e-10, reltol = 1e-8, parallel = true, jacobian = BK.FiniteDifferencesMF());\n\tampfactor = 1.0, δp = 0.0075,\n\t# the next option is not necessary\n\t# it speeds up the newton iterations\n\t# by combining the linear solves of the bordered linear system\n\tlinear_algo = MatrixFreeBLS(@set ls.N = 2+2n*Mt),\n\tverbosity = 3,\tplot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], Mt; kwargs...),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"and you should see","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials3/#Computation-of-the-branch-of-periodic-orbits-(Poincaré-Shooting)","page":"🟡 1d Brusselator (automatic)","title":"Computation of the branch of periodic orbits (Poincaré Shooting)","text":"","category":"section"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We now turn to another Shooting method, namely the Poincaré one. We can provide this method thanks to the unique functionalities of DifferentialEquations.jl. More information is provided at PoincareShootingProblem and Periodic orbits based on the shooting method but basically, it is a shooting method between Poincaré sections Sigma_i (along the orbit) defined by hyperplanes. As a consequence, the dimension of the unknowns is M_shcdot(N-1) where N is the dimension of the phase space. Indeed, each time slice lives in an hyperplane Sigma_i. Additionally, the period T is not an unknown of the method but rather a by-product. However, the method requires the time stepper to find when the flow hits an hyperplane Sigma_i, something called event detection.","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"We show how to use this method, the code is very similar to the case of the Parallel Standard Shooting:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"# linear solvers\nls = GMRESIterativeSolvers(reltol = 1e-8, maxiter = 100)\neig = EigKrylovKit(tol= 1e-12, x₀ = rand(2n-1), dim = 50)\n# newton parameters\noptn_po = NewtonPar(verbose = true, tol = 1e-7, max_iterations = 15, linsolver = ls, eigsolver = eig)\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.03, ds= 0.005, p_max = 2.5, max_steps = 100, newton_options = optn_po, nev = 10, tol_stability = 1e-5, detect_bifurcation = 3, plot_every_step = 2)\n\n# number of time slices\nMt = 2\nbr_po = continuation(\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n PoincareShootingProblem(Mt, prob, Rodas4P(); abstol = 1e-10, reltol = 1e-8,\n jacobian = BK.FiniteDifferencesMF());\n\t# the next option is not necessary\n\t# it speeds up the newton iterations\n\t# by combining the linear solves of the bordered linear system\n\tlinear_algo = MatrixFreeBLS(@set ls.N = (2n-1)*Mt+1),\n\tampfactor = 1.0, δp = 0.005,\n\tverbosity = 3, plot = true,\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_shooting!(x[1:end-1], Mt; kwargs...),\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"and you should see:","category":"page"},{"location":"tutorials/tutorials3/","page":"🟡 1d Brusselator (automatic)","title":"🟡 1d Brusselator (automatic)","text":"(Image: )","category":"page"},{"location":"intro-abs/#Branch-switching-page","page":"Introduction","title":"Branch switching","text":"","category":"section"},{"location":"intro-abs/","page":"Introduction","title":"Introduction","text":"The precise definition of the methods are given in Branch switching (branch point) and Branch switching (Hopf point).","category":"page"},{"location":"intro-abs/#Summary-of-branching-procedures","page":"Introduction","title":"Summary of branching procedures","text":"","category":"section"},{"location":"intro-abs/","page":"Introduction","title":"Introduction","text":"We collect in the following table the list of automatic branch switching (aBS) functions. Their detailed explanation follows in this page.","category":"page"},{"location":"intro-abs/","page":"Introduction","title":"Introduction","text":"function ind-th bif. point Type T description\ncontinuation(br::ContResult{T}, ind::Int; kw...) :bp, :nd EquilibriumCont aBS from equilibria to equilibria\ncontinuation(br::ContResult{T}, ind::Int, lens2::Lens; kw...) :bp, :hopf EquilibriumCont Fold/Hopf continuation w.r.t. parameters getlens(br) and lens2\ncontinuation(br::ContResult{T}, ind::Int; kw...) :bt,:zh,:hh FoldCont,HopfCont switch to Fold/Hopf continuation from Hopf/Fold w.r.t. parameters of codim 2 br\ncontinuation(br::ContResult{T}, ind_hopf::Int, ::ContinuationPar, prob::AbstractPeriodicOrbitProblem) :hopf EquilibriumCont Branch switching from Hopf point to periodic orbits\ncontinuation(br::ContResult{T}, ind::Int, kw...) :bp,:pd PeriodicOrbitCont Branch switching from Branch / Period-doubling point of periodic orbits to curve of periodic orbits\ncontinuation(br::ContResult{T}, ind::Int, kw...) :gh,:zh,:hh TwoParamCont Branch switching from Bautin / Zero-Hopf/ Hopf-Hopf point to curve of Fold/NS of periodic orbits","category":"page"},{"location":"cusp/#Normal-form-of-the-Cusp-bifurcation","page":"Cusp","title":"Normal form of the Cusp bifurcation","text":"","category":"section"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"We follow the paper[Kuznetsov] and consider a Cauchy problem","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"dot x=mathbf F(xp)","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"mathbf L q=0 quad mathbf L^T p=0 quad langle p qrangle=1","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"Under some conditions, x(t)approx x_0+ w(t)q where w satisfies the normal form:","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"dotw=c w^3+Oleft(w^4right)tagE","category":"page"},{"location":"cusp/#Normal-form-computation","page":"Cusp","title":"Normal form computation","text":"","category":"section"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type Cusp.","category":"page"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"cusp/#References","page":"Cusp","title":"References","text":"","category":"section"},{"location":"cusp/","page":"Cusp","title":"Cusp","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"ANM/#Asymptotic-numerical-method-(ANM)","page":"ANM","title":"Asymptotic numerical method (ANM)","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"warning: Work in progress\nAutomatic branch switching is being tested, it will be available soon.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"warning: Dimensions\nThis is a method for small dimensions, less than several thousands.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"To access this algorithm, you have to use the package AsymptoticNumericalMethod.jl ","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"The method [Rubbert],[Charpentier] seeks a Taylor approximation of the solutions of","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"mathbf F(Xp)=0inmathbb R^n","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"where Xinmathbb R^n pinmathbb R. The solution is found by solving","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"F(x(s)p(s))= 0","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"langle x(s)-x(0)fracpartial upartial s(0)rangle + (p(s)-p(0))fracpartial ppartial s(0) = s","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"where","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"x(s)=sumlimits_k=0^K x_ks^kquad p(s)=sumlimits_k=0^K p_ks^k","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"for some user passed K0. It gives","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"F(x(s)p(s)) = sumlimits_k=0^K F_ks^k+hot","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"from which we deduce the equations F_k=0. We then find:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"F_1 x_1=Id p_1=1(x_kp_k) = -F_kx_k=0p_k=0","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"The validity range of the solution can be estimated by","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"r_K = left(fracepsilonlvertlvert F_Klvertlvertright)^1K","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"This allows to iterate and find a sequence of series which spans the parameter range.","category":"page"},{"location":"ANM/#Implementation","page":"ANM","title":"Implementation","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"The method is based on the package TaylorSeries.jl which makes it easy to manipulate Taylor series based on Automatic Differentiation.","category":"page"},{"location":"ANM/#Method","page":"ANM","title":"Method","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"See AsymptoticNumericalMethod.ANM for more information.","category":"page"},{"location":"ANM/#Example","page":"ANM","title":"Example","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"We provide an example of use. We define a BifurcationProblem as usual and pass the continuation algorithm ANM.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"using AsymptoticNumericalMethod, Plots, Parameters, Setfield\nusing LinearAlgebra: norm\nusing BifurcationKit\nconst BK = BifurcationKit\n\nnorminf(x) = norm(x, Inf)\n\nfunction F(x, p)\n\t@unpack α = p\n\tf = similar(x)\n\n\tf[1] = (-2x[1]+x[2]) + α * exp(x[1])\n\tf[2] = ( x[1]-2x[2]) + α * exp(x[2])\n\n\treturn f\nend\n\nsol0 = zeros(2)\npar = (α = 0.0, )\nprob = BifurcationProblem(F, sol0, par, (@lens _.α); record_from_solution = (x,p) -> norminf(x))","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"optanm = ContinuationPar(dsmin = 0.01, dsmax = 0.15, detect_bifurcation = 3, ds= 0.01, newton_options = NewtonPar(tol = 1e-9, verbose = false), n_inversion = 6, max_bisection_steps = 15, max_steps = 15, )\n\nbranm = continuation(prob, ANM(20, 1e-8), optanm, normC = norminf, verbosity = 2)","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"You can plot the result as usual:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"plot(branm)","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"You can also show the radius of convergence of each series:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"plot(branm, plotseries = true)","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"Finally, for each series, we ca evaluate the residual norm:","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"plot()\nfor ii in eachindex(branm.polU)\n\ts = LinRange(-0*branm.radius[ii], branm.radius[ii], 20)\n\tplot!([branm.polp[ii].(s)], [norminf(F(branm.polU[ii](_s), BK.setparam(prob,branm.polp[ii](_s)))) for _s in s], legend = false, linewidth=5)#, marker=:d)\nend\ntitle!(\"\")","category":"page"},{"location":"ANM/#References","page":"ANM","title":"References","text":"","category":"section"},{"location":"ANM/","page":"ANM","title":"ANM","text":"[Charpentier]: Charpentier, Isabelle, Bruno Cochelin, and Komlanvi Lampoh. “Diamanlab - An Interactive Taylor-Based Continuation Tool in MATLAB,” n.d., 12.","category":"page"},{"location":"ANM/","page":"ANM","title":"ANM","text":"[Rubbert]: Rubbert, Lennart, Isabelle Charpentier, Simon Henein, and Pierre Renaud. “Higher-Order Continuation Method for the Rigid-Body Kinematic Design of Compliant Mechanisms”, n.d., 18.","category":"page"},{"location":"ns/#Neimark-Sacker-point","page":"Neimarck-Sacker","title":"Neimark-Sacker point","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"Pages = [\"ns.md\"]\nDepth = 2","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"At a Neimark-Sacker (NS) bifurcation of a periodic orbit gamma (with period T) for parameter value p_0 for the Cauchy problem ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"fracdudt=F(up)tagE","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"the eigenvalues (Floquet coefficients) of the monodromy operator mathcal M=Y(T) solution to","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"fracdYdt=A(t)Y(t) Y(0)=I_n","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"contain the eigenvalues e^pm i theta with theta and ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"e^i q theta-1 neq 0 quad q=1234 text (no strong resonances) ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"There are two ways to compute the normal form of this bifurcation","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"using the Poincaré return map [Kuznetsov]\nusing the method of [Iooss], see also [Kuz2]","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"You can obtain the normal form of a NS bifurcation using ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"pd = get_normal_form(br, ind; prm = false)","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where prm indicates whether you want to use the method based on Poincaré return map (PRM) or the one based on Iooss method.","category":"page"},{"location":"ns/#Normal-form-based-on-Poincaré-return-map","page":"Neimarck-Sacker","title":"Normal form based on Poincaré return map","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"Given a transversal section Sigma to gamma at gamma(0), the Poincaré return map mathcal P associates to each point xinSigma close to gamma(0) the first point mathcal P(xp)inSigma where the orbit of (E) with initial condition x intersects again Sigma at mathcal P(xp). Hence, the discrete map x_n+1=mathcal P(x_np) has normal form","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"z_n+1 = z_ne^itheta(1+dz_n^2)","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where[Kuz2]","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"d=frac12 e^-i thetaleftlangle v^* mathcalC(v v barv)+2 mathcalBleft(vleft(I_n-1-mathcalAright)^-1 mathcalB(v barv)right)+mathcalBleft(barvleft(e^2 i theta I_n-1-mathcalAright)^-1 mathcalB(v v)right)rightrangle","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where mathcal C=d^3mathcal P(gamma(0)), mathcal B = d^2mathcal P(gamma(0)) and mathcal A = dmathcal P(gamma(0)). Also:","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"mathcalA v=e^i theta v mathcalA^mathrmT v^*=e^-i theta v^* text and leftlangle v^* vrightrangle=1","category":"page"},{"location":"ns/#Normal-form-based-on-Iooss-method","page":"Neimarck-Sacker","title":"Normal form based on Iooss method","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"This is based on [Iooss],[Kuz2]. Suppose that the T periodic orbit gamma(tau) has a Neimark-Sacker bifurcation for a parameter value p_0. We also assume that there are no strong resonances. Locally, the orbits can be represented by ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"x(tau) = gamma(tau)+Q_0(tau)xi+Phi(tau xi)","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"where ","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"leftbeginaligned\nfracd taud t =1+axi^2+cdots \nfracd xid t =fraci thetaT xi+d xixi^2+cdots\nendalignedright","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"with center manifold correction Phi(tau xi) being T periodic in tau and Q_0(tau) is the Floquet operator.","category":"page"},{"location":"ns/#References","page":"Neimarck-Sacker","title":"References","text":"","category":"section"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"[Kuznetsov]: Yu. A. Kuznetsov, \"Elements of Applied Bifurcation Theory\", 2nd ed., 1998.","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"[Kuz2]: Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”","category":"page"},{"location":"ns/","page":"Neimarck-Sacker","title":"Neimarck-Sacker","text":"[Iooss]: Iooss, \"Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.\", 1988","category":"page"},{"location":"overview/#Overview-of-BifurcationKit.jl","page":"Overview","title":"Overview of BifurcationKit.jl","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"The general workflow for using the package is as follows:","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Define a problem\nSolve the problem\nAnalyze the output","category":"page"},{"location":"overview/#Defining-Problems","page":"Overview","title":"Defining Problems","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"Problems are specified via a type interface. The problem types are designed to contain the necessary information to fully define their associated continuation method. For example, a bifurcation problem is defined by","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"F(u pars) = 0","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"with some parameters pars, some initial guess u0, and scalar parameter axis lens contained in pars. Therefore the BifurcationProblem is defined by those components:","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"prob = BifurcationProblem(F, u0, pars, lens)","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Note that the number types in the solution will match the types you designate in the problem. However complex types are not advised as they mess up the detection of bifurcation points.","category":"page"},{"location":"overview/#Continuing-from-the-initial-guess","page":"Overview","title":"Continuing from the initial guess","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"Each type of bifurcation problem has its own problem type which allow the solvers to dispatch to the right methods. The common interface for calling the solvers is:","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"br = continuation(prob, alg; kwargs)","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Into the command, one passes the bifurcation problem that was defined prob, choose an algorithm alg, and change the properties of the solver using keyword arguments. The solver returns a branch object br which holds all the details for the branch.","category":"page"},{"location":"overview/#Analyzing-the-branch","page":"Overview","title":"Analyzing the branch","text":"","category":"section"},{"location":"overview/","page":"Overview","title":"Overview","text":"The solution type has a common interface, which makes handling the solution similar between the different types of bifurcation problems. Tools such as interpolations are seamlessly built into the solution interface to make analysis easy. This interface is described in the ContResult.","category":"page"},{"location":"overview/","page":"Overview","title":"Overview","text":"Plotting functionality is provided by a recipe to Plots.jl. To use plot branches, simply call the plot(br) and the plotter will generate appropriate plots. Plots can be customized using all the keyword arguments provided by Plots.jl. Please see Plots.jl's documentation for more information.","category":"page"},{"location":"#BifurcationKit.jl","page":"Home","title":"BifurcationKit.jl","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This Julia package aims at performing automatic bifurcation analysis of possibly large dimensional equations F(u, λ)=0 where λ∈ℝ by taking advantage of iterative methods, dense / sparse formulation and specific hardwares (e.g. GPU).","category":"page"},{"location":"","page":"Home","title":"Home","text":"It incorporates continuation algorithms (PALC, deflated continuation, ...) based on a Newton-Krylov method to correct the predictor step and a Matrix-Free/Dense/Sparse eigensolver is used to compute stability and bifurcation points.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Despite initial focus on large scale problems, the package can easily handle low dimensional problems.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The package can also seek for periodic orbits of Cauchy problems by casting them into an equation F(up)=0 of high dimension. It is by now, one of the only softwares which provides shooting methods AND methods based on finite differences or collocation to compute periodic orbits.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Hence, large scale nonlinear problems and different hardwares are possible. The goal is to use Matrix Free methods on GPU (see PDE example and Periodic orbit example) or on a cluster to solve non linear PDE, nonlocal problems, compute sub-manifolds...","category":"page"},{"location":"","page":"Home","title":"Home","text":"One design choice is that we try not to require u to be a subtype of an AbstractArray as this would forbid the use of spectral methods like the one from ApproxFun.jl. For now, our implementation does not allow this for all methods of the package.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package requires Julia >= v1.3.0 because of the use of methods added to abstract types (see #31916).","category":"page"},{"location":"","page":"Home","title":"Home","text":"To install it, please run","category":"page"},{"location":"","page":"Home","title":"Home","text":"] add BifurcationKit","category":"page"},{"location":"","page":"Home","title":"Home","text":"To install the bleeding edge version, please run","category":"page"},{"location":"","page":"Home","title":"Home","text":"] add BifurcationKit#master","category":"page"},{"location":"#Citing-this-work","page":"Home","title":"Citing this work","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"If you use this package for your work, we ask that you cite the following paper!! Open source development strongly depends on this. It is referenced on HAL-Inria as follows:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@misc{veltz:hal-02902346,\n TITLE = {{BifurcationKit.jl}},\n AUTHOR = {Veltz, Romain},\n URL = {https://hal.archives-ouvertes.fr/hal-02902346},\n INSTITUTION = {{Inria Sophia-Antipolis}},\n YEAR = {2020},\n MONTH = Jul,\n KEYWORDS = {pseudo-arclength-continuation ; periodic-orbits ; floquet ; gpu ; bifurcation-diagram ; deflation ; newton-krylov},\n PDF = {https://hal.archives-ouvertes.fr/hal-02902346/file/354c9fb0d148262405609eed2cb7927818706f1f.tar.gz},\n HAL_ID = {hal-02902346},\n HAL_VERSION = {v1},\n}","category":"page"},{"location":"#Other-softwares","page":"Home","title":"Other softwares","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"There are many good softwares already available.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For continuation in small dimension, most softwares are listed on DSWeb. One can mention the widely used AUTO-07p, or also, XPPAUT, MATCONT, PyDSTool and COCO. All these are very reliable and some address high codimensional bifurcations.\nFor large scale problems, there is the versatile and feature full pde2path but also Trilinos-LOCA, CL_MATCONTL, COCO, GetFEM and the python libraries pyNCT and pacopy. There are also some nice lectures by D. Avitabile et al. on matrix free secant continuation based on a concise Matlab implementation which are used in the influential paper [Rankin]. At the time of initial release of BifurcationKit.jl, these lectures provided one of the only libraries for matrix-free continuation, much easier to use than Trilinos-LOCA.\nFor deflated continuation, there is defcont (by the inventor of the algo. P. E. Farrell) and this code by N. M. Evstigneev.","category":"page"},{"location":"","page":"Home","title":"Home","text":"In Julia, we also have Bifurcations.jl which is unmaintained.","category":"page"},{"location":"#A-word-on-performance","page":"Home","title":"A word on performance","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The examples which follow have not all been written with the goal of performance but rather simplicity (except maybe 2d Ginzburg-Landau equation and Langmuir–Blodgett model). One could surely turn them into more efficient codes. The intricacies of PDEs make the writing of efficient code highly problem dependent and one should take advantage of every particularity of the problem under study.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For example, in one of the simplest tutorials, Temperature model, one could use BandedMatrices.jl for the jacobian and an inplace modification when the jacobian is called ; using a composite type would be favored. Porting them to GPU could be another option.","category":"page"},{"location":"#Requested-methods-for-Custom-State","page":"Home","title":"Requested methods for Custom State","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Needless to say, if you use regular arrays, you don't need to worry about what follows.","category":"page"},{"location":"","page":"Home","title":"Home","text":"We make the same requirements as KrylovKit.jl. Hence, we refer to its docs for more information. We additionally require the following methods to be available:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Base.length(x): it is used in the constraint equation of the pseudo arclength continuation method (see continuation for more details). If length is not available for your \"vector\", define it length(x) = 1 and adjust tuning the parameter θ in PALC.\nBase.copyto!(dest, in) this is required to reduce the allocations by avoiding too many copies\nBase.eltype must be extended to your vector type. It is mainly used for branching.","category":"page"},{"location":"#Citations","page":"Home","title":"Citations","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The papers citing this work are collected on google scholar.","category":"page"},{"location":"#Reproducibility","page":"Home","title":"Reproducibility","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"
      The documentation of BifurcationKit was built using these direct dependencies,","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Pkg # hide\nPkg.status() # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      ","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      and using this machine and Julia version.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using InteractiveUtils # hide\nversioninfo() # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      ","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      A more complete overview of all dependencies and their versions is also provided.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Pkg # hide\nPkg.status(;mode = PKGMODE_MANIFEST) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"
      ","category":"page"},{"location":"","page":"Home","title":"Home","text":"You can also download the\nmanifest file and the\nproject file.","category":"page"},{"location":"#References","page":"Home","title":"References","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"[Rankin]: J. Rankin et al., \"Continuation of localized coherent structures in nonlocal neural field equations\", SIAM J. Scientific Computing 36, pp. B70–B93 (2014): https://epubs.siam.org/doi/10.1137/130918721","category":"page"},{"location":"diffeq/#Wrapper-to-the-package-DifferentialEquations.jl","page":"DiffEq wrapper","title":"Wrapper to the package DifferentialEquations.jl","text":"","category":"section"},{"location":"diffeq/","page":"DiffEq wrapper","title":"DiffEq wrapper","text":"warning: Warning\nThis is work in progress. ","category":"page"},{"location":"diffeq/","page":"DiffEq wrapper","title":"DiffEq wrapper","text":"The current package will provide basic methods to wrap some of the functionality of DifferentialEquations.jl. ","category":"page"},{"location":"diffeq/","page":"DiffEq wrapper","title":"DiffEq wrapper","text":"Basically, the ultimate idea is that you provide a prob::ODEProblem to our newton, continuation... and they will use the expression of the jacobians, the linear solvers... that you already provided for the construction of prob.","category":"page"},{"location":"NSContinuationPO/#Continuation-of-Neimark-Sacker-(NS)-bifurcations-of-periodic-orbits","page":"Neimark-Sacker continuation (2 params)","title":"Continuation of Neimark-Sacker (NS) bifurcations of periodic orbits","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"warning: Work in progress\nContinuation of NS of POs is a recent addition. It has not been thoroughly tested.","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In this page, we explain how to perform continuation of NS points of periodic orbits and detect the associated codim 2 bifurcations.","category":"page"},{"location":"NSContinuationPO/#List-of-detected-codim-2-bifurcation-points","page":"Neimark-Sacker continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"Bifurcation symbol used\nCusp cusp\nStrong resonance 1:1 bifurcation R1\nFold / Flip foldFlip\nFold / Neimark-Sacker foldNS\nDouble Niemark-Sacker nsns\nChenciner ch","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"NSContinuationPO/#Neimark-Sacker-continuation","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"The continuation of Neimark-Sacker bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation), except the Trapezoid one, for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.","category":"page"},{"location":"NSContinuationPO/#Detection-of-codim-2-bifurcation-points","page":"Neimark-Sacker continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the keyword argument detect_codim2_bifurcation in the method continuation ","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"the detection of Chenciner bifurcation is done by the the computating the NS normal form\nthe detection the above bifurcation points is done by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"NSContinuationPO/#Setting-the-jacobian","page":"Neimark-Sacker continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In order to apply the newton algorithm to the PD functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the PD functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.","category":"page"},{"location":"NSContinuationPO/#Codim-2-continuation","page":"Neimark-Sacker continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"To compute the codim 2 curve of Fold points of periodic orbits, one can call continuation with the following options","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"NSContinuationPO/#Algorithmic-details","page":"Neimark-Sacker continuation (2 params)","title":"Algorithmic details","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"The continuation of NS points is based on the formulation","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"G(upomega) = (F_po(upomega) Resigma(upomega) Imsigma(upomega))inmathbb R^n+2quadquad (mathcal F_ns)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"where F_po is the functional for locating periodic orbits and the test function sigma is solution of","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"leftbeginarraycc\nN(upomega) w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(uomegap)\nendarrayright=leftbeginarrayc\n0_n \n1\nendarrayright","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"In the case of Multiple Standard Shooting, the matrix N is based on the monodromy M(x_iT_i)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"N=left(beginarraycccccc\nM_1 -I 0 cdots 0 \n0 M_2 -I cdots 0 \nvdots cdots ddots ddots vdots \n0 cdots cdots ddots -I \ne^iomegaI cdots cdots 0 M_m \nendarrayright)","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"The jacobian of the NS functional to use for the Newton algorithm","category":"page"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"leftbeginarrayccc\npartial_uF_po partial_pF_po 0 \npartial_usigma_r partial_psigma_r partial_omegasigma_r\npartial_usigma_i partial_psigma_i partial_omegasigma_i\nendarrayright","category":"page"},{"location":"NSContinuationPO/#References","page":"Neimark-Sacker continuation (2 params)","title":"References","text":"","category":"section"},{"location":"NSContinuationPO/","page":"Neimark-Sacker continuation (2 params)","title":"Neimark-Sacker continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"abs-from-codim2-po/#From-codim-2-to-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Pages = [\"abs-from-codim2-po.md\"]\nDepth = 3","category":"page"},{"location":"abs-from-codim2-po/#From-Bautin-point-to-curve-Folds-of-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From Bautin point to curve Folds of periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"From the Bautin normal form, we know that there is a curve of Fold of periodic orbits near the bifurcation point.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"We provide an automatic branch switching method in this case which reads as follows:","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"continuation(br::HopfCont, ind_BAUTIN::Int, \n\t_contParams::ContinuationPar,\n prob::AbstractPeriodicOrbitProblem ;\n δp = nothing, ampfactor = 1, kwargs...)","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information).","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Note that the two parameters in br will be used for the continuation of Fold points of periodic orbits.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"See ODE for an example of use.","category":"page"},{"location":"abs-from-codim2-po/#From-Zero-Hopf-(ZH)-point-to-curve-NS-of-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From Zero-Hopf (ZH) point to curve NS of periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"From the Zero-Hopf normal form, we know that there is a curve of Neimark-Sacker (NS) bifurcations of periodic orbits near the bifurcation point.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"We provide an automatic branch switching method in this case which reads as follows:","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"continuation(br::TwoParamCont, ind_ZH::Int, \n\t_contParams::ContinuationPar,\n prob::AbstractPeriodicOrbitProblem ;\n δp = nothing, ampfactor = 1, kwargs...)","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information).","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Note that the two parameters in br will be used for the continuation of NS points of periodic orbits.","category":"page"},{"location":"abs-from-codim2-po/#From-Hopf-Hopf-(HH)-point-to-curve-NS-of-periodic-orbits","page":"From codim 2 to periodic orbits","title":"From Hopf-Hopf (HH) point to curve NS of periodic orbits","text":"","category":"section"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"From the Hopf-Hopf normal form, we know that there are two curves of Neimark-Sacker (NS) bifurcations of periodic orbits near the bifurcation point.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"We provide an automatic branch switching method in this case which reads as follows:","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"continuation(br::TwoParamCont, ind_HH::Int, \n\t_contParams::ContinuationPar,\n prob::AbstractPeriodicOrbitProblem ;\n δp = nothing, ampfactor = 1, \n whichns = 1,\n kwargs...)","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"where prob is a method to compute periodic orbits (see From Hopf point to periodic orbits for more information). The option whichns which belongs to {1,2} controls which NS curve you want to compute. ","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"Note that the two parameters in br will be used for the continuation of NS points of periodic orbits.","category":"page"},{"location":"abs-from-codim2-po/","page":"From codim 2 to periodic orbits","title":"From codim 2 to periodic orbits","text":"See ODE for an example of use.","category":"page"},{"location":"zh/#Normal-form-of-the-Zero-Hopf-bifurcation","page":"Zero-Hopf","title":"Normal form of the Zero-Hopf bifurcation","text":"","category":"section"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"We follow the paper[Kuznetsov],[Kuznetsov2] and consider a Cauchy problem","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"dot x=mathbf F(xp)","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"mathbf L q_0=0 quad mathbf L q_1=i omega_0 q_1","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"Under some conditions, x(t)approx x_0+2Re w_1(t)q_1+w_0(t)q_0 where w_i satisfy the normal form:","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"leftbeginaligned\ndotw_0= frac12 G_200 w_0^2+G_011leftw_1right^2+frac16 G_300 w_0^3 +G_111 w_0leftw_1right^2+Oleft(leftleft(w_0 w_1 barw_1right)right^4right) \ndotw_1= i omega_0 w_1+G_110 w_0 w_1+frac12 G_210 w_0^2 w_1+frac12 G_021 w_1leftw_1right^2 +Oleft(leftleft(w_0 w_1 barw_1right)right^4right) \nendalignedrighttagE","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"This normal form is usually computed in order to branch from a Zero-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the G_ijk is returned.","category":"page"},{"location":"zh/#Normal-form-computation","page":"Zero-Hopf","title":"Normal form computation","text":"","category":"section"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type ZeroHopf.","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"zh/#References","page":"Zero-Hopf","title":"References","text":"","category":"section"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"zh/","page":"Zero-Hopf","title":"Zero-Hopf","text":"[Kuznetsov2]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.","category":"page"},{"location":"eigensolver/#Eigen-solvers-(Eig)","page":"Eigen solvers","title":"Eigen solvers (Eig)","text":"","category":"section"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"The eigen solvers must be subtypes of AbstractEigenSolver. ","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"They provide a way of computing the eigen elements of the Jacobian J. Such eigen solver eigsolve will be called like ev, evecs, itnumber = eigsolve(J, nev; kwargs...) throughout the package, nev being the number of requested eigen elements of largest real part and kwargs being used to send information about the algorithm (perform bisection,...).","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"Here is an example of the simplest of them (see src/EigSolver.jl for the true implementation) to give you an idea:","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"struct DefaultEig <: AbstractEigenSolver end\n\nfunction (l::DefaultEig)(J, nev; kwargs...)\n\t# I put Array so we can call it on small sparse matrices\n\tF = eigen(Array(J))\n\tI = sortperm(F.values, by = real, rev = true)\n\tnev2 = min(nev, length(I))\n\treturn F.values[I[1:nev2]], F.vectors[:, I[1:nev2]], true, 1\nend","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"warning: Eigenvalues\nThe eigenvalues must be ordered by increasing real part for the detection of bifurcations to work properly.","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"warning: Eigenvectors\nYou have to implement the method geteigenvector(eigsolver, eigenvectors, i::Int) for newtonHopf to work properly.","category":"page"},{"location":"eigensolver/#Methods-for-computing-eigenvalues","page":"Eigen solvers","title":"Methods for computing eigenvalues","text":"","category":"section"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"Like for the linear solvers, computing the spectrum of operators A associated to PDE is a highly non trivial task because of the clustering of eigenvalues. Most methods are based on the so-called power method but this only yields the eigenvalues with largest modulus. In case of the Laplacian operator, this can be disastrous and it is better to apply the power method to (sigma I-A)^-1 instead. ","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"This method, called Shift-invert, is readily available for the solvers EigArpack and EigArnoldiMethod, see below. It is mostly used to compute interior eigenvalues. For the solver EigKrylovKit, one must implement its own shift invert operator, using for example GMRESKrylovKit.","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"In some cases, it may be advantageous to consider the Cayley transform (sigma I-A)^-1(tau I+A) to focus on a specific part of the spectrum. As it is mathematically equivalent to the Shift-invert method, we did not implement it.","category":"page"},{"location":"eigensolver/#List-of-implemented-eigen-solvers","page":"Eigen solvers","title":"List of implemented eigen solvers","text":"","category":"section"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"Default eigen Julia eigensolver for matrices. You can create it via eig = DefaultEig(). Note that you can also specify how the eigenvalues are ordered (by decreasing real part by default). You can then compute 3 eigenelements of J like eig(J, 3).\nEigensolver from Arpack.jl. You can create one via eigsolver = EigArpack() and pass appropriate options (see Arpack.jl). For example, you can compute eigenvalues using Shift-Invert method with shift σ by using EigArpack(σ, :LR). Note that you can specify how the eigenvalues are ordered (by decreasing real part by default). Finally, this method can be used for (sparse) matrix or Matrix-Free formulation. For a matrix J, you can compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigArpack(v0 = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3). \nEigensolver from KrylovKit.jl. You create one via eig = EigKrylovKit() and pass appropriate options (see KrylovKit.jl). This method can be used for (sparse) matrix or Matrix-Free formulation. In the case of a matrix J, you can create a solver like this eig = EigKrylovKit(). Then, you compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigKrylovKit(x₀ = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3).\nEigensolver from ArnoldiMethod.jl. You can create one via eig = EigArnoldiMethod() and pass appropriate options (see ArnoldiMethod.jl). For example, you can compute eigenvalues using the Shift-Invert method with shift σ by using EigArnoldiMethod(σ, LR()). Note that you can also specify how the eigenvalues are ordered (by decreasing real part by default). In the case of a matrix J, you can create a solver like eig = EigArnoldiMethod(). Then, you compute 3 eigen-elements using eig(J, 3). In the case of a Matrix-Free jacobian dx -> J(dx), you need to tell the eigensolver the dimension of the state space by giving an example of vector: eig = EigArnoldiMethod(x₀ = zeros(10)). You can then compute 3 eigen-elements using eig(dx -> J(dx), 3). ","category":"page"},{"location":"eigensolver/","page":"Eigen solvers","title":"Eigen solvers","text":"tip: Slow computations \nThis is probably due to iterative refinement conducted by SuiteSparse as explained in this blog post. You can disable this usingusing SuiteSparse\nSuiteSparse.UMFPACK.umf_ctrl[8] = 0","category":"page"},{"location":"interfaceLS/#Interface-for-Linear-Solvers","page":"Vector","title":"Interface for Linear Solvers","text":"","category":"section"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"The linear solver ls must be a subtype of the abstract type AbstractLinearSolver. It is then called as follows","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"Required methods Brief description\nls(J, rhs; a₀ = 0, a₁ = 1, kwargs...) Compute the solution sol of the linear problem (a₀ * I + a₁ * J) * sol = rhs where J is the jacobian. Returns (sol, success::Bool, itnumber) where itnumber is the number of iterations for solving the problem.","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"tip: Shifts\nTwo methods _axpy and _axpy_op are provided to help implementing this shift a₀ * I + a₁ * J","category":"page"},{"location":"interfaceLS/#Interface-for-Eigen-Solvers","page":"Vector","title":"Interface for Eigen Solvers","text":"","category":"section"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"The linear solver eig must be a subtype of the abstract type AbstractEigenSolver. It is then called as follows","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"Required methods Brief description\neig(J, nev::Int; kwargs...) Compute the nev eigen-elements with largest real part. Returns (eigenvalues, eigenvectors, success:Bool, itnumber) where itnumber is the number of iterations for completing the computation. kwargs can be used to send information about the algorithm (perform bisection,...).\ngeteigenvector(eig, eigenvectors, i::Int) Returns the ith eigenvectors from the set of eigenvectors.","category":"page"},{"location":"interfaceLS/#Interface-for-Bordered-Linear-Solvers","page":"Vector","title":"Interface for Bordered Linear Solvers","text":"","category":"section"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"The bordered linear solver bls must be a subtype of the abstract type AbstractBorderedLinearSolver (which is itself a subtype of AbstractLinearSolver). It is used to solve","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"tagBLSleftbeginarrayll\ntextshiftcdot I+J dR \n(xi_u cdot dz_u)^T xi_p cdot dz_p\nendarrayright cdotleftbeginarrayl\ndX \ndl\nendarrayright = leftbeginarrayl\nR \nn\nendarrayright","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"where xi_uxi_pinmathbb C and dRxi_uinmathbb C^N.","category":"page"},{"location":"interfaceLS/","page":"Vector","title":"Vector","text":"Required methods Brief description\nbls(J, dR, dzu, dzp, R, n, ξu::Number, ξp::Number; shift = nothing, kwargs...) Compute the solution dX, dl of the linear problem (BLS) where J is the jacobian and dR, dzu are vectors (not necessarily subtypes of AbstractVector). shift = nothing is used in place of saying shift=0. Returns (dX, dl, success::Bool, itnumber) where itnumber is the number of iterations for solving the problem.","category":"page"},{"location":"educational/#Educational-introduction-to-bifurcation-analysis-(contributed-by-G.-Datseris)","page":"Educational introduction","title":"Educational introduction to bifurcation analysis (contributed by G. Datseris)","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"This page is an educational introduction to bifurcation analysis and creation of bifurcation diagrams. It will show a completely self-contained approach, and its goal is to serve as an introduction to users not yet fully familiar with bifurcation analysis. ","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The text here is based on Chapter 4 of Nonlinear Dynamics: a concise introduction interlaced with code and is presented in a shortened form. It is focusing on using the simplest possible method for bifurcation continuation (the secant method) and can only address fixed points (the standard version of Newton's algorithm). Of course, this does not reflect the full features and power of BifurcationKit.jl, but it shows the basic guiding principles.","category":"page"},{"location":"educational/#Newton's-method-for-finding-fixed-points","page":"Educational introduction","title":"Newton's method for finding fixed points","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let mathbfx be a D-dimensional vector participating in the continuous dynamical system dotmathbfx = f(mathbfx p) which also depends on some arbitrary parameter pinmathbb R. To identify fixed points, we want to find the roots mathbfx^* of f. Notice that everything that follows also applies to discrete dynamical systems where mathbfx_n+1 = g(mathbfx_n). The difference is that we simply define f = g - mathbfId and find the roots of f again.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"To find the roots we can use Newton's method. Starting for some point mathbfx_0, the following sequence will (typically) converge to a root:","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"mathbfx_j+1 = mathbfx_j - delta J_f^-1(mathbfx_j) f(mathbfx_j)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"for 0le delta le 1 and with J_f the Dtimes D Jacobian matrix of f.","category":"page"},{"location":"educational/#Continuation-of-a-bifurcation-curve","page":"Educational introduction","title":"Continuation of a bifurcation curve","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"A bifurcation curve (in the simplified context of this page) is the location of fixed points versus a parameter p. The simplest, but also most brute force, way to compute such a curve would be to scan the parameter axis, and for each parameter value apply Newton's method to find the fixed point. Because there could be more than one fixed points at a given parameter, one needs several initial conditions plugged into Newton's method, to ensure all fixed points are found.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"A bit better approach would be to true and continue the curve of the fixed point mathbfx^*(p). To do this one needs two ingredients: (1) a predictor and (2) a corrector. The first estimates a new \"seed\" for Newton's method that attempts to continue the existing points we have found on the curve. The second corrects this prediction to a point in the state-parameter space that is on the bifurcation curve.","category":"page"},{"location":"educational/#The-secant-predictor","page":"Educational introduction","title":"The secant predictor","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The simplest predictor is the secant. Let mathbfz = (mathbfx p). Assuming we have found at least two points mathbfz^*_m mathbfz^*_m-1 on the bifurcation curve, we can estimate a continuation tildemathbfz = 2mathbfz^*_m - mathbfz^*_m-1 (linear extrapolation). This is called the secant predictor.","category":"page"},{"location":"educational/#The-corrector","page":"Educational introduction","title":"The corrector","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The prediction tildemathbfz of the secant needs to be corrected not only in the variable space mathbfx, which is what Newton's method currently does, but also on parameter space. To do this, we need to extend the function f to have one more element (because otherwise we would have 1 too many unknowns give the amount of equations we have to estimate the zero of f(mathbfz)). We will extend f so that its D+1 entry enforces the k-th element of the root to be the one suggested by the predictor. I.e., we define the function h","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"h(mathbfx) = (f_1(mathbfz) ldots f_D(mathbfz) mathbfzk - tildemathbfzk)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"and will try to find the zeros of h now via Newton's method. Notice that now the Jacobian J_h is D+1 dimensional, with the last column being the derivatives of f towards the parameter p.","category":"page"},{"location":"educational/#Code:-Newton's-algorithm-in-mixed-space","page":"Educational introduction","title":"Code: Newton's algorithm in mixed space","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let's first write the code that will be performing Newton's algorithm for the function h in the mixed space of mathbfz. For convenience, we would expect the user to only provide the functions f J_f as functions f(x, p), J(x,p) with x a vector and p a number. We can do everything else using automatic differentiation.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"(Notice: for simplicity, and to be in style with BifurcationKit.jl we will make everything allocate and return new Vector instances. Performance-wise, the code written in this page is as bad as it can possibly get)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"First, define a function that given f, J, the mixed state z and the index k it returns the mixed Jacobian J_h","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"using ForwardDiff # for auto-differentiation\nusing LinearAlgebra\n\nfunction mixed_jacobian(z, k, f, J)\n x = z[1:end-1]; p = z[end]\n # start creating the mixed space jacobian\n j = J(x, p)\n # to the state space jacobian add one more column, derivative towards p\n pder = ForwardDiff.derivative(p -> f(x, p), p)\n Jmixed = hcat(j, pder)\n # add the last row, which is 1 for the `k` entry, 0 everywhere else\n last_row = zeros(length(z)); last_row[k] = 1.0\n Jfinal = vcat(Jmixed, last_row')\n return Jfinal\nend","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Then we write a function that takes one step of the Newton's algorithm:","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"using LinearAlgebra\n\nfunction newton_step!(zⱼ, zpred, i, f, J, δ)\n Jfinal = mixed_jacobian(zⱼ, i, f, J)\n xⱼ = zⱼ[1:end-1]; pⱼ = zⱼ[end]\n g = f(xⱼ, pⱼ)\n gz = vcat(g, zⱼ[i] - zpred[i])\n zⱼ₊₁ = zⱼ - Jfinal \\ gz\n return zⱼ₊₁\nend","category":"page"},{"location":"educational/#Code:-Corrector-function","page":"Educational introduction","title":"Code: Corrector function","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"And with this, we are ready to compose our corrector function, that takes a guess zpred and brings it to a point that is on the bifurcation curve. The keyword arguments help us give a convergence criterion to Newton's algorithm and also catch problematic cases where convergence never happens in time.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function corrector(zpred, f, J; δ = 0.9, max_steps = 200, ε = 1e-6, k = 1)\n c = 0\n zⱼ = zpred\n zⱼ₊₁ = newton_step!(zⱼ, zpred, k, f, J, δ)\n while norm(zⱼ₊₁ - zⱼ) > ε\n zⱼ = zⱼ₊₁\n zⱼ₊₁ = newton_step!(zⱼ, zpred, k, f, J, δ)\n c += 1\n if c > max_steps\n @warn(\"Newton did not converge.\")\n return (zⱼ₊₁, false)\n end\n end\n return zⱼ₊₁, true\nend","category":"page"},{"location":"educational/#Code:-Predictor-function","page":"Educational introduction","title":"Code: Predictor function","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Coding the predictor is trivial. If we have no previous entries we start from the initial seed given by the user, otherwise we take do the linear extrapolation discussed above. A user also needs to provide an initial direction dmathbfz to go towards.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function predictor(zs, dz0)\n if length(zs) == 1\n return zs[end]\n elseif length(zs) == 2 # 1 entry is z0, 2nd entry is 1st found fixed point\n return zs[end] .+ dz0\n else\n return 2zs[end] .- zs[end-1]\n end\nend","category":"page"},{"location":"educational/#Code:-Continuation-function","page":"Educational introduction","title":"Code: Continuation function","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Alright, now we can put it all together into the a single \"continuation\" function.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function continuation!(zs, f, J; dz0, pmin, pmax)\n zpred = predictor(zs, dz0)\n (pmin ≤ zpred[end] ≤ pmax) || return false\n zˣ, success = corrector(zpred, f, J)\n push!(zs, zˣ)\n return success\nend\n\nusing LinearAlgebra: eigvals\n\n# Continuation loop: do continuation for a given amount of steps\nfunction continuation(f, J, x0, p0; pmin, pmax, dp0, dx0, N = 1000)\n\n z0 = vcat(x0, p0); zs = [z0]; dz0 = vcat(dx0, dp0)\n\n ps = [p0]\n xs = [x0]\n stability = Bool[]\n for i in 1:N\n success = continuation!(zs, f, J; dz0, pmin, pmax)\n # Stop iteration if we exceed given parameter margins\n success || break\n # Detect stability of found fixed point (needs `Array` coz of StaticArrays.jl)\n eigenvalues = eigvals(J(zs[end][1:end-1], zs[end][end]))\n isstable = maximum(real, eigenvalues) < 0\n push!(stability, isstable)\n end\n xs = [z[1:end-1] for z in zs]\n ps = [z[end] for z in zs]\n popfirst!(xs); popfirst!(ps) # remove initial guess\n return xs, ps, stability\nend","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"The code also returns the fixed point stability, although it does assume we have a continuous dynamical system. Adjusting for discrete systems is straightforward.","category":"page"},{"location":"educational/#Running-an-example","page":"Educational introduction","title":"Running an example","text":"","category":"section"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let's use the code we have defined to run an example. The following dynamical system has a single saddle node bifurcation, and a fixed point that is \"flat\" versus the parameter change.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"function maasch_rule(u, p)\n x, y, z = u\n q, r, s = 1.2, 0.8, 0.8\n dx = -x - y\n dy = -p*z + r*y + s*z^2 - z^2*y\n dz = -q*(x + z)\n return [dx, dy, dz]\nend\n\nfunction maasch_jacob(u, p)\n x, y, z = u\n q, r, s = 1.2, 0.8, 0.8\n return [-1 -1 0;\n 0 (r - z^2) (-p + 2z*s - 2z*y);\n -q 0 -q]\nend","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"We now use it to get the bifurcation curve.","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"pmin = -0.1\npmax = 2\nδ = 0.9\np0 = 0.0\nx0 = [-1.4, -1.4, -1.4]\ndp0 = 0.02\ndx0 = [0.01, 0.01, 0.01]\n\nxs, ps, stability = continuation(maasch_rule, maasch_jacob, x0, p0;\n pmin, pmax, dp0, dx0\n)","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"Let's plot this","category":"page"},{"location":"educational/","page":"Educational introduction","title":"Educational introduction","text":"using Plots\ncolors = [s ? :blue : :red for s in stability]\np = scatter(ps, [x[1] for x in xs]; color = colors, markerstrokecolor = colors, xlabel = \"p\", ylabel = \"x\", label = \"\")","category":"page"},{"location":"tutorials/ode/tutorialPP2/#pp2-example-from-AUTO07p-(aBD-Hopf-aBS)","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"","category":"section"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"Pages = [\"tutorialsPP2.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"The goal of this example is to show how to use automatic bifurcation diagram computation for a simple ODE.","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"The following equations are a model of type predator-prey. The example is taken from Auto07p:","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"beginarrayl\nu_1^prime=3 u_1left(1-u_1right)-u_1 u_2-p_1left(1-e^-5 u_1right) \nu_2^prime=-u_2+3 u_1 u_2\nendarray","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\n\n# function to record information from a solution\nrecordFromSolution(x, p) = (u1 = x[1], u2 = x[2])\n\nfunction pp2!(dz, z, p, t = 0)\n\t@unpack p1, p2, p3, p4 = p\n\tu1, u2 = z\n\tdz[1] = p2 * u1 * (1 - u1) - u1 * u2 - p1 * (1 - exp(-p3 * u1))\n\tdz[2] =\t-u2 + p4 * u1 * u2\n\tdz\nend\n\n# parameters of the model\npar_pp2 = (p1 = 1., p2 = 3., p3 = 5., p4 = 3.)\n\n# initial condition\nz0 = zeros(2)\n\n# bifurcation problem\nprob = BifurcationProblem(pp2!, z0, par_pp2,\n\t# specify the continuation parameter\n\t(@lens _.p1), record_from_solution = recordFromSolution)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialPP2/#Automatic-bifurcation-diagram-computation","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"Automatic bifurcation diagram computation","text":"","category":"section"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"We set up the options or the continuation","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = 0.1, p_max = 1.0, dsmax = 0.01,\n\t# options to detect bifurcations\n\tdetect_bifurcation = 3, n_inversion = 8, max_bisection_steps = 25,\n\t# number of eigenvalues\n\tnev = 2,\n\t# maximum number of continuation steps\n\tmax_steps = 1000,)\n\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"We are now ready to compute the diagram","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"diagram = bifurcationdiagram(prob, PALC(),\n\t# very important parameter. It specifies the maximum amount of recursion\n\t# when computing the bifurcation diagram. It means we allow computing branches of branches of branches\n\t# at most in the present case.\n\t3,\n\t(args...) -> setproperties(opts_br; ds = -0.001, dsmax = 0.01, n_inversion = 8, detect_bifurcation = 3);\n\t# δp = -0.01,\n\tverbosity = 0, plot = false)\n\nscene = plot(diagram; code = (), title=\"$(size(diagram)) branches\", legend = false)","category":"page"},{"location":"tutorials/ode/tutorialPP2/#Branch-of-periodic-orbits-with-finite-differences","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"Branch of periodic orbits with finite differences","text":"","category":"section"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"As you can see on the diagram, there is a Hopf bifurcation indicated by a red dot. Let us compute the periodic orbit branching from the Hopf point.","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"We first find the branch","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"# branch of the diagram with Hopf point\nbrH = get_branch(diagram, (2,1)).γ\n\n# newton parameters\noptn_po = NewtonPar(tol = 1e-8, max_iterations = 25)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.1, ds= -0.001, dsmin = 1e-4,\n newton_options = (@set optn_po.tol = 1e-8), tol_stability = 1e-2,\n detect_bifurcation = 1)\n\nMt = 101 # number of time sections\n\tbr_po = continuation(\n\tbrH, 1, opts_po_cont,\n\tPeriodicOrbitTrapProblem(M = Mt;\n\t # specific linear solver for ODEs\n \tjacobian = :Dense);\n\n\trecord_from_solution = (x, p) -> begin\n\t\txtt = get_periodic_orbit(p.prob, x, p.p)\n\t\treturn (max = maximum(xtt[1,:]),\n\t\t\tmin = minimum(xtt[1,:]),\n\t\t\tperiod = x[end])\n\tend,\n\tfinalise_solution = (z, tau, step, contResult; prob = nothing, kwargs...) -> begin\n\t\t# limit the period\n\t\tz.u[end] < 100\n\t\tend,\n\tnormC = norminf)\n\n\nplot(diagram); plot!(br_po, branchlabel = \"Periodic orbits\", legend = :bottomright)","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"Let us now plot an orbit","category":"page"},{"location":"tutorials/ode/tutorialPP2/","page":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","title":"🟢 pp2 example from AUTO07p (aBD + Hopf aBS)","text":"# extract the different components\norbit = get_periodic_orbit(br_po, 10)\nplot(orbit.t, orbit[1,:]; label = \"u1\", markersize = 2)\nplot!(orbit.t, orbit[2,:]; label = \"u2\", xlabel = \"time\", title = \"period = $(orbit.t[end])\")","category":"page"},{"location":"tutorials/tutorials2/#sh2dfd","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Pages = [\"tutorials2.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We study the following PDE","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"-(I+Delta)^2 u+lcdot u +nu u^2-u^3 = 0","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"with Neumann boundary conditions. This full example is in the file example/SH2d-fronts.jl. This example is also treated in the MATLAB package pde2path. We use a Sparse Matrix to express the operator L_1=(I+Delta)^2.","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"using DiffEqOperators, Setfield, Parameters\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays\nconst BK = BifurcationKit\n\n# helper function to plot solution\nheatmapsol(x) = heatmap(reshape(x,Nx,Ny)',color=:viridis)\nheatmapsol!(x; k...) = heatmap!(reshape(x,Nx,Ny)';color=:viridis, k...)\n\nNx = 151\nNy = 100\nlx = 4*2pi\nly = 2*2pi/sqrt(3)\n\n# we use DiffEqOperators to compute the Laplacian operator\nfunction Laplacian2D(Nx, Ny, lx, ly)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\tQx = Neumann0BC(hx)\n\tQy = Neumann0BC(hy)\n\n\tA = kron(sparse(I, Ny, Ny), sparse(D2x * Qx)[1]) + kron(sparse(D2y * Qy)[1], sparse(I, Nx, Nx))\n\treturn A, D2x\nend","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We also write the functional and its Jacobian which is a Sparse Matrix","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"function F_sh(u, p)\n\t@unpack l, ν, L1 = p\n\treturn -L1 * u .+ (l .* u .+ ν .* u.^2 .- u.^3)\nend\n\nfunction dF_sh(u, p)\n\t@unpack l, ν, L1 = p\n\treturn -L1 .+ spdiagm(0 => l .+ 2 .* ν .* u .- 3 .* u.^2)\nend\n\n# we compute the differentials\nd2F_sh(u, p, dx1, dx2) = (2 .* p.ν .* dx2 .- 6 .* dx2 .* u) .* dx1\nd3F_sh(u, p, dx1, dx2, dx3) = (-6 .* dx2 .* dx3) .* dx1","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We first look for hexagonal patterns. This is done with","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"X = -lx .+ 2lx/(Nx) * collect(0:Nx-1)\nY = -ly .+ 2ly/(Ny) * collect(0:Ny-1)\n\n# initial guess for hexagons\nsol0 = [(cos(x) + cos(x/2) * cos(sqrt(3) * y/2) ) for x in X, y in Y]\n\tsol0 .= sol0 .- minimum(vec(sol0))\n\tsol0 ./= maximum(vec(sol0))\n\tsol0 = sol0 .- 0.25\n\tsol0 .*= 1.7\n\theatmap(sol0',color=:viridis)\n\n# define parameters for the PDE\nΔ, _ = Laplacian2D(Nx, Ny, lx, ly);\nL1 = (I + Δ)^2;\npar = (l = -0.1, ν = 1.3, L1 = L1);\n\n# Bifurcation Problem\nprob = BifurcationProblem(F_sh, vec(sol0), par, (@lens _.l);\n\t\tJ = dF_sh,\n\t\tplot_solution = (x, p; kwargs...) -> (heatmapsol!(x; label=\"\", kwargs...)),\n\t\trecord_from_solution = (x, p) -> (n2 = norm(x), n8 = norm(x, 8)),\n\t\td2F = d2F_sh,\n\t\td3F = d3F_sh)\n\n# newton corrections of the initial guess\noptnewton = NewtonPar(verbose = true, tol = 1e-8, max_iterations = 20)\nsol_hexa = @time newton(prob, optnewton)\nprintln(\"--> norm(sol) = \",norm(sol_hexa.u, Inf64))\nheatmapsol(sol_hexa.u)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"which produces the results","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 1.7391e+02 │ 0 │\n│ 1 │ 5.0465e+03 │ 1 │\n│ 2 │ 1.4878e+03 │ 1 │\n│ 3 │ 4.3529e+02 │ 1 │\n│ 4 │ 1.2560e+02 │ 1 │\n│ 5 │ 3.5512e+01 │ 1 │\n│ 6 │ 9.5447e+00 │ 1 │\n│ 7 │ 2.1763e+00 │ 1 │\n│ 8 │ 3.3503e-01 │ 1 │\n│ 9 │ 7.7259e-02 │ 1 │\n│ 10 │ 7.4767e-03 │ 1 │\n│ 11 │ 7.9505e-05 │ 1 │\n│ 12 │ 8.8395e-09 │ 1 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.441525 seconds (1.74 k allocations: 659.488 MiB, 1.25% gc time)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"with sol_hexa being","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/#Continuation-and-bifurcation-points","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"Continuation and bifurcation points","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We can now continue this solution as follows. We want to detect bifurcations along the branches. We thus need an eigensolver. However, if we use an iterative eigensolver, like eig = EigArpack(), it has trouble computing the eigenvalues. One can see that using","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"# compute the jacobian\nJ0 = dF_sh(sol_hexa.u, par)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"The reason is that the jacobian operator is not very well conditioned unlike its inverse. We thus opt for the shift-invert method (see Eigen solvers (Eig) for more information) with shift 0.1:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"eig = EigArpack(0.1, :LM)\n\n# compute 10 eigenvalues\neig(J0, 10)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"If we want to compute the bifurcation points along the branches, we have to tell the solver by setting detect_bifurcation = 2. However, this won't be very precise and each bifurcation point will be located at best at the step size precision. We can use bisection to locate this points more precisely using the option detect_bifurcation = 3 (see Detection of bifurcation points of Equilibria for more information).","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We are now ready to compute the branches:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"optcont = ContinuationPar(dsmin = 0.0001, dsmax = 0.005, ds= -0.001, p_max = 0.00, p_min = -1.0,\n\tnewton_options = setproperties(optnewton; tol = 1e-9, max_iterations = 15), max_steps = 125,\n\tdetect_bifurcation = 3, nev = 40, detect_fold = false,\n\tdsmin_bisection =1e-7, save_sol_every_step = 4)\noptcont = @set optcont.newton_options.eigsolver = EigArpack(0.1, :LM)\n\nbr = continuation(\n\tre_make(prob, u0 = sol_hexa.u), PALC(), optcont;\n\tplot = true,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Note that we can get some information about the branch as follows. The [converged] indicates if the bisection routine was successful, otherwise it shows [guess]. Finally δ = ( 2, 0) says that the bifurcation point has been detected by 2 new eigenvalues with zero real part among which zero have non zero imaginary part. A Hopf bifurcation point would thus have δ = ( 2, 2) or δ = ( -2, 2).","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"julia> br\n ┌─ Branch number of points: 98\n ├─ Branch of Equilibrium\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter l starts at -0.1, ends at 0.0\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, bp at l ≈ -0.21554719 ∈ (-0.21554719, -0.21554706), |δp|=1e-07, [converged], δ = ( 1, 0), step = 35, eigenelements in eig[ 36], ind_ev = 1\n- # 2, bp at l ≈ -0.21551160 ∈ (-0.21552059, -0.21551160), |δp|=9e-06, [converged], δ = ( 1, 0), step = 36, eigenelements in eig[ 37], ind_ev = 2\n- # 3, bp at l ≈ -0.21498624 ∈ (-0.21505972, -0.21498624), |δp|=7e-05, [converged], δ = ( 1, 0), step = 38, eigenelements in eig[ 39], ind_ev = 3\n- # 4, bp at l ≈ -0.21288704 ∈ (-0.21296786, -0.21288704), |δp|=8e-05, [converged], δ = ( 1, 0), step = 41, eigenelements in eig[ 42], ind_ev = 4\n- # 5, nd at l ≈ -0.20991950 ∈ (-0.21014903, -0.20991950), |δp|=2e-04, [converged], δ = ( 2, 0), step = 43, eigenelements in eig[ 44], ind_ev = 6\n- # 6, nd at l ≈ -0.20625778 ∈ (-0.20683030, -0.20625778), |δp|=6e-04, [converged], δ = ( 2, 0), step = 45, eigenelements in eig[ 46], ind_ev = 8\n- # 7, bp at l ≈ -0.19979039 ∈ (-0.19988091, -0.19979039), |δp|=9e-05, [converged], δ = ( 1, 0), step = 48, eigenelements in eig[ 49], ind_ev = 9\n- # 8, bp at l ≈ -0.18865313 ∈ (-0.18887470, -0.18865313), |δp|=2e-04, [converged], δ = ( 1, 0), step = 52, eigenelements in eig[ 53], ind_ev = 10\n- # 9, bp at l ≈ -0.18102735 ∈ (-0.18105752, -0.18102735), |δp|=3e-05, [converged], δ = ( 1, 0), step = 55, eigenelements in eig[ 56], ind_ev = 11\n- # 10, bp at l ≈ -0.14472390 ∈ (-0.14531199, -0.14472390), |δp|=6e-04, [converged], δ = (-1, 0), step = 64, eigenelements in eig[ 65], ind_ev = 11\n- # 11, bp at l ≈ -0.13818496 ∈ (-0.13878446, -0.13818496), |δp|=6e-04, [converged], δ = (-1, 0), step = 66, eigenelements in eig[ 67], ind_ev = 10\n- # 12, bp at l ≈ -0.11129567 ∈ (-0.11161237, -0.11129567), |δp|=3e-04, [converged], δ = (-1, 0), step = 72, eigenelements in eig[ 73], ind_ev = 9\n- # 13, bp at l ≈ -0.08978296 ∈ (-0.09010769, -0.08978296), |δp|=3e-04, [converged], δ = (-1, 0), step = 77, eigenelements in eig[ 78], ind_ev = 8\n- # 14, bp at l ≈ -0.08976771 ∈ (-0.08977278, -0.08976771), |δp|=5e-06, [converged], δ = (-1, 0), step = 78, eigenelements in eig[ 79], ind_ev = 7\n- # 15, bp at l ≈ -0.07014208 ∈ (-0.07145756, -0.07014208), |δp|=1e-03, [converged], δ = (-1, 0), step = 82, eigenelements in eig[ 83], ind_ev = 6\n- # 16, bp at l ≈ -0.06091464 ∈ (-0.06223456, -0.06091464), |δp|=1e-03, [converged], δ = (-1, 0), step = 84, eigenelements in eig[ 85], ind_ev = 5\n- # 17, bp at l ≈ -0.05306984 ∈ (-0.05315247, -0.05306984), |δp|=8e-05, [converged], δ = (-1, 0), step = 86, eigenelements in eig[ 87], ind_ev = 4\n- # 18, bp at l ≈ -0.02468398 ∈ (-0.02534143, -0.02468398), |δp|=7e-04, [converged], δ = (-1, 0), step = 92, eigenelements in eig[ 93], ind_ev = 3\n- # 19, bp at l ≈ -0.00509751 ∈ (-0.00639292, -0.00509751), |δp|=1e-03, [converged], δ = (-1, 0), step = 96, eigenelements in eig[ 97], ind_ev = 2\n- # 20, bp at l ≈ +0.00000000 ∈ (-0.00509751, +0.00000000), |δp|=5e-03, [ guess], δ = (-1, 0), step = 97, eigenelements in eig[ 98], ind_ev = 1","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We get the following plot during computation:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"tip: Tip\nWe don't need to call newton first in order to use continuation.","category":"page"},{"location":"tutorials/tutorials2/#Snaking-computed-with-deflation","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"Snaking computed with deflation","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We know that there is snaking near the left fold. Let us look for other solutions like fronts. The problem is that if the guess is not precise enough, the newton iterations will converge to the solution with hexagons sol_hexa. We appeal to the technique initiated by P. Farrell and use a deflated problem (see DeflationOperator and DeflatedProblem for more information). More precisely, we apply the newton iterations to the following functional uto Pi_i=1^n_sleft( u-sol_hexai^-p + sigmaright)F_sh(u) which penalizes sol_hexa.","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"# this define the above penalizing factor with p=2, sigma=1, norm associated to dot\n# and the set of sol_{hexa} is of length ns=1\ndeflationOp = DeflationOperator(2, 1.0, [sol_hexa.u])\noptnewton = @set optnewton.max_iterations = 250\noutdef = newton(\n\t\t\t\tre_make(prob, u0 = 0.2vec(sol_hexa.u) .* vec([exp.(-(x+lx)^2/25) for x in X, y in Y])),\n\t\t\t\tdeflationOp,\n\t\t\t\toptnewton, normN = norminf)\nheatmapsol(outdef.u) |> display\nBK.converged(outdef) && push!(deflationOp, outdef.u)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"which gives:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Note that push!(deflationOp, outdef) deflates the newly found solution so that by repeating the process we find another one:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"outdef = newton(\n\t\t\t\tre_make(prob, u0 = 0.2vec(sol_hexa.u) .* vec([exp.(-(x)^2/25) for x in X, y in Y])),\n\t\t\t\tdeflationOp, optnewton, normN = norminf)\nheatmapsol(outdef.u) |> display\nBK.converged(outdef) && push!(deflationOp, outdef.u)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Again, repeating this from random guesses, we find several more solutions, like for example","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We can now continue the solutions located in deflationOp.roots","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"br1 = @time continuation(re_make(prob, u0 = deflationOp[2]),\n\tPALC(), optcont;\n\tplot = true)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"and using plot(br, br1), we obtain:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Note that the plot provides the stability of solutions and bifurcation points. Interested readers should consult the associated file example/SH2d-fronts.jl in the example folder.","category":"page"},{"location":"tutorials/tutorials2/#Automatic-branch-switching","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"Automatic branch switching","text":"","category":"section"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"Instead of relying on deflated newton, we can use Branch switching to compute the different branches emanating from the bifurcation point. For example, the following code will perform automatic branch switching from the second bifurcation point of br:","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"br2 = continuation(br, 2, setproperties(optcont; ds = -0.001, detect_bifurcation = 3, plot_every_step = 5, max_steps = 170); nev = 30,\n\tplot = true, verbosity = 2,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"We can then plot the branches using plot(br, br2, br3) and get","category":"page"},{"location":"tutorials/tutorials2/","page":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","title":"🟡 2d Swift-Hohenberg equation: snaking, Finite Differences","text":"(Image: )","category":"page"},{"location":"periodicOrbitShooting/#Periodic-orbits-based-on-the-shooting-method","page":"Shooting","title":"Periodic orbits based on the shooting method","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"A set of shooting algorithms is provided which are called either Simple Shooting (SS) if a single shooting is used and Multiple Shooting (MS) otherwise. For the exposition, we follow the PhD thesis[Lust] and also [Umbria].","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We aim at finding periodic orbits for the Cauchy problem ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"tag1 fracd xd t=f(x)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"and we write phi^t(x_0) the associated flow (or semigroup of solutions).","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"tip: Tip about convenience functions\nFor convenience, we provide some functions plotPeriodicShooting for plotting, get_amplitude (resp. get_maximum) for getting the amplitude (resp. maximum) of the solution encoded by a shooting problem. See the tutorials for examples of use.","category":"page"},{"location":"periodicOrbitShooting/#Standard-Shooting","page":"Shooting","title":"Standard Shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/#Simple-shooting","page":"Shooting","title":"Simple shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"A periodic orbit is found when we have a couple (x T) such that phi^T(x) = x and the trajectory is non constant. Therefore, we want to solve the equations G(xT)=0 given by","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"tagSS\nbeginarraylphi^T(x)-x=0 s(xT)=0endarray","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The section s(xT)=0 is a phase condition to remove the indeterminacy of the point on the limit cycle.","category":"page"},{"location":"periodicOrbitShooting/#Multiple-shooting","page":"Shooting","title":"Multiple shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"This case is similar to the previous one but more sections are used. To this end, we partition the unit interval with m+1 points 0=s_0s_1cdotss_m-1s_m=1 and consider the equations G(x_1cdotsx_mT)=0","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"beginaligned\nphi^delta s_1T(x_1)-x_2 =0 \nphi^delta s_2T(x_2)-x_3 =0 vdots \nphi^delta s_m-1T(x_m-1)-x_m =0 \nphi^delta s_mT(x_m)-x_1 =0 s(x_1 T) =0 \nendalignedtagMS","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"where delta s_i=s_i+1-s_i. The Jacobian of the system of equations w.r.t. (xT) is given by ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"mathcalJ=left(beginarrayccmathcal J_c partial_TG star dendarrayright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"where the cyclic matrix mathcal J_c is","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"mathcal J_c = \nleft(beginarrayccccc\nM_1 -I \n M_2 -I \n ddots -I \n-I M_m \nendarrayright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"and M_i=partial_xphi^delta s_i T(x_i).","category":"page"},{"location":"periodicOrbitShooting/#Section","page":"Shooting","title":"Section","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The periodic orbits solutions of (SS) or (MS) are not uniquely defined because of the phase invariance. A section s(xT)=0 (resp. s(x_1T)=0) for (SS) (resp. (MS)) must be provided. The default is the same for both $ s(x,T) = T\\cdot \\langle x-x_\\pi, \\phi\\rangle.$","category":"page"},{"location":"periodicOrbitShooting/#Encoding-of-the-functional","page":"Shooting","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The functional is encoded in the composite type ShootingProblem. In particular, the user can pass its own time stepper or one can use the different ODE solvers in DifferentialEquations.jl which makes it very easy to choose a solver tailored for the a specific problem. See the link ShootingProblem for more information ; for example on how to access the underlying functional, its jacobian...","category":"page"},{"location":"periodicOrbitShooting/#Poincaré-shooting","page":"Shooting","title":"Poincaré shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The algorithm is based on the one described in Newton–Krylov Continuation of Periodic Orbits for Navier–Stokes Flows., Sánchez, J., M. Net, B. Garcı́a-Archilla, and C. Simó (2004) and Matrix-Free Continuation of Limit Cycles for Bifurcation Analysis of Large Thermoacoustic Systems. Waugh, Iain, Simon Illingworth, and Matthew Juniper (2013). ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We look for periodic orbits solutions of (1) using the hyperplanes Sigma_i=x langle x-x^c_I n_irangle=0 for i=1cdotsM, centered on x^c_i, which intersect transversally an initial periodic orbit guess. We write Pi_iSigma_itoSigma_mod(i+1M), the Poincaré return map to Sigma_mod(i+1M). The main idea of the algorithm is to use the fact that the problem is (N-1)cdot M dimensional if x_iinmathbb R^N because each x_i lives in Sigma_i. Hence, one has to constrain the unknowns to these hyperplanes otherwise the Newton algorithm does not converge well.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We thus need to parametrize these hyperplanes.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"To this end, we introduce the projection operator R_imathbb R^Nto mathbb R^N-1 such that ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"R_ileft(x_1 x_2 ldots x_k_i-1 x_k_i x_k_i+1 ldots x_Nright)=left(x_1 x_2 ldots x_k_i-1 x_k_i+1 ldots x_Nright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"where k_i=argmax_p n_ip. The inverse operator E_imathbb R^N-1toSigma_i is defined by (where bar x=R_i(x))","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"E_i(bar x) = E_ileft(x_1 x_2 ldots x_k_i-1 x_k_i+1 ldots x_Nright)=\nleft(x_1 x_2 ldots x_k_i-1 x^c_ik_i-fracbarn_i cdotleft(overlinex-overlinex^c_iright)n_ik_i x_k_i+1 ldots x_Nright)","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We note that R_icirc E_i = I_mathbb R^N-1 and E_icirc R_i = I_mathbb R^N.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We then look for solutions of the following problem:","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"beginaligned \nbar x_1 - R_MPi_M(E_M(bar x_M))=0 \nbar x_2 - R_1Pi_1(E_i(bar x_1))=0 vdots \nbar x_M - R_M-1Pi_M-1(E_M-1(bar x_M-1))=0 \nendaligned","category":"page"},{"location":"periodicOrbitShooting/#Encoding-of-the-functional-2","page":"Shooting","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The functional is encoded in the composite type PoincareShootingProblem. In particular, the user can pass their own time stepper or he can use the different ODE solvers in DifferentialEquations.jl which makes it very easy to choose a tailored solver: the partial Poincaré return maps are implemented using callbacks. See the link PoincareShootingProblem for more information, in particular on how to access the underlying functional, its jacobian...","category":"page"},{"location":"periodicOrbitShooting/#Floquet-multipliers-computation","page":"Shooting","title":"Floquet multipliers computation","text":"","category":"section"},{"location":"periodicOrbitShooting/#Standard-shooting","page":"Shooting","title":"Standard shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The Floquet multipliers are computed as the eigenvalues of the monodromy matrix M=M_Mcdots M_1.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"Unlike the case with Finite differences, the matrices M_i are not sparse.","category":"page"},{"location":"periodicOrbitShooting/#Poincaré-shooting-2","page":"Shooting","title":"Poincaré shooting","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The (non trivial) Floquet exponents are eigenvalues of the Poincaré return map PiSigma_1toSigma_1. We have Pi = Pi_McircPi_M-1circcdotscircPi_2circPi_1. Its differential is thus","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"dPi(x)cdot h = dPi_M(x_M)dPi_M-1(x_M-1)cdots dPi_1(x_1)cdot h","category":"page"},{"location":"periodicOrbitShooting/#Numerical-method","page":"Shooting","title":"Numerical method","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We provide two methods to compute the Floquet coefficients.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"A not very precise algorithm for computing the Floquet multipliers is provided. The method, dubbed Quick and Dirty (QaD), is not numerically very precise for large / small Floquet exponents. ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"It amounts to computing the eigenvalues of M=M_Mcdots M_1 (resp. dPi) for the Standard (resp. Poincaré) Shooting. The method allows, nevertheless, to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. For more information, have a look at FloquetQaD.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbitShooting/#Computation-with-newton","page":"Shooting","title":"Computation with newton","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We provide a simplified call to newton to locate the periodic orbit. Have a look at the tutorial Continuation of periodic orbits (Standard Shooting) for a simple example on how to use the above methods. ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The docs for this specific newton are located at newton.","category":"page"},{"location":"periodicOrbitShooting/#Computation-with-newton-and-deflation","page":"Shooting","title":"Computation with newton and deflation","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"We also provide a simplified call to newton to locate the periodic orbit with a deflation operator:","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"newton(prob::BifurcationKit.AbstractShootingProblem,\n\t\t\t\torbitguess,\n\t\t\t\toptions::NewtonPar;\n\t\t\t\tlens::Union{Setfield.Lens, Nothing} = nothing,\n\t\t\t\tkwargs...)","category":"page"},{"location":"periodicOrbitShooting/#BifurcationKit.newton-Tuple{AbstractShootingProblem, Any, NewtonPar}","page":"Shooting","title":"BifurcationKit.newton","text":"newton(prob, orbitguess, options; lens, δ, kwargs...)\n\n\nThis is the Newton-Krylov Solver for computing a periodic orbit using the (Standard / Poincaré) Shooting method. Note that the linear solver has to be appropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is either a ShootingProblem or a PoincareShootingProblem. These two problems have specific options to be tuned, we refer to their link for more information and to the tutorials.\n\nprob a problem of type <: AbstractShootingProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit. See ShootingProblem and See PoincareShootingProblem for information regarding the shape of orbitguess.\npar parameters to be passed to the functional\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"and","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"newton(prob::BifurcationKit.AbstractShootingProblem,\n\t\t\t\torbitguess::vectype,\n\t\t\t\tdefOp::DeflationOperator{Tp, Tdot, T, vectype},\n\t\t\t\toptions::NewtonPar{T, S, E};\n\t\t\t\tlens::Union{Lens, Nothing} = nothing,\n\t\t\t\tkwargs...,\n\t\t\t) where {T, Tp, Tdot, vectype, S, E}","category":"page"},{"location":"periodicOrbitShooting/#Continuation","page":"Shooting","title":"Continuation","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"Have a look at the Continuation of periodic orbits (Standard Shooting) example for the Brusselator.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"In order to plot the orbit during continuation, one has to recompute the orbit inside a plotSolution function passed to continuation. This is simplified by the function get_periodic_orbit which returns a solution to be plotted. We refer to Period doubling in Lur'e problem for an example of use.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"The docs for this specific continuation are located at continuation.","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"continuation(probPO::BifurcationKit.AbstractShootingProblem, orbitguess,\n\t\t\t\t\t\talg::BifurcationKit.AbstractContinuationAlgorithm,\n\t\t\t\t\t\tcontParams::ContinuationPar,\n\t\t\t\t\t\tlinear_algo::BifurcationKit.AbstractBorderedLinearSolver;\n\t\t\t\t\t\tδ = convert(eltype(orbitguess), 1e-8),\n\t\t\t\t\t\tkwargs...,\n\t\t\t\t\t)","category":"page"},{"location":"periodicOrbitShooting/#BifurcationKit.continuation-Tuple{AbstractShootingProblem, Any, BifurcationKit.AbstractContinuationAlgorithm, ContinuationPar, BifurcationKit.AbstractBorderedLinearSolver}","page":"Shooting","title":"BifurcationKit.continuation","text":"continuation(\n probPO,\n orbitguess,\n alg,\n contParams,\n linear_algo;\n δ,\n eigsolver,\n record_from_solution,\n plot_solution,\n kwargs...\n)\n\n\nThis is the continuation method for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to continuation except that probPO is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.\n\nOptional arguments\n\neigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitShooting/#References","page":"Shooting","title":"References","text":"","category":"section"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"[Lust]: Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, Lust Kurt, 1997. ","category":"page"},{"location":"periodicOrbitShooting/","page":"Shooting","title":"Shooting","text":"[Umbria]: J. S. Umbría and M. Net. Numerical continuation methods for large-scale dissipative dynamical systems. The European Physical Journal Special Topics, 225(13):2465–2486, 2016.","category":"page"},{"location":"codim2Continuation/#Fold-/-Hopf-Continuation","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Pages = [\"codim2Continuation.md\"]\nDepth = 2","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"In this page, we explain how to perform continuation of Fold / Hopf points and detect the associated bifurcations.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"For this to work best, it is advised to have an analytical expression for the jacobian. See the tutorial Temperature model for more details although BifurcationProblem implement it with AD by default.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"A quite complete example for detection of codim 2 bifurcations of equilibria is Extended Lorenz-84 model (codim 2 + BT/ZH aBS).","category":"page"},{"location":"codim2Continuation/#List-of-detected-codim-2-bifurcation-points","page":"Fold / Hopf Continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Bifurcation symbol used\nBogdanov-Takens bt\nBautin gh\nCusp cusp\nZero-Hopf zh\nHopf-Hopf hh","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"codim2Continuation/#Fold-continuation","page":"Fold / Hopf Continuation (2 params)","title":"Fold continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"The continuation of Fold bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities. The continuation of Fold points is based on the formulation","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"G(up) = (F(up) sigma(up))inmathbb R^n+1quadquad (F_f)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where the test function sigma is solution of","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarraycc\ndF(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(up)\nendarrayright=leftbeginarrayc0_n 1endarrayrightquadquad (M_f)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where wv are chosen in order to have a non-singular matrix (M_f). More precisely, v (resp. w) should be close to a null vector of dF(u,p) (resp. dF(u,p)'). During continuation, the vectors wv are updated so that the matrix (M_f) remains non-singular ; this is controlled with the argument update_minaug_every_step (see below).","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"note that there are very simplified calls for this, see Newton refinement below. In particular, you don't need to set up the Fold Minimally Augmented problem yourself. This is done in the background.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"warning: Linear Method\nYou can pass the bordered linear solver to solve (M_f) using the option bdlinsolver (see below). Note that the choice bdlinsolver = BorderingBLS() can lead to singular systems. Indeed, in this case, (M_f) is solved by inverting dF(u,p) which is singular at Fold points.","category":"page"},{"location":"codim2Continuation/#Detection-of-codim-2-bifurcation-points","page":"Fold / Hopf Continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the option detect_codim2_bifurcation in the method continuation. Under the hood, the detection of these bifurcations is done by using Event detection as explained in Event Handling.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"the detection of Cusp (Cusp) is done by the detection of Fold bifurcation points along the curve of Folds by monitoring the parameter component of the tangent.\nthe detection of Bogdanov-Takens (BT) is performed using the test function[Bindel] psi_BT(p) = langle w(p)v(p)rangle\nthe detection of Zero-Hopf (ZH) is performed by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"codim2Continuation/#Hopf-continuation","page":"Fold / Hopf Continuation (2 params)","title":"Hopf continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"The continuation of Fold bifurcation points is based on a Minimally Augmented (see [Govaerts] p. 87) formulation which is an efficient way to detect singularities. The continuation of Hopf points is based on the formulation","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"G(uomegap) = (F(uomegap) Resigma(uomegap) Imsigma(uomegap))inmathbb R^n+2quadquad (F_h)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where the test function sigma is solution of","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarraycc\ndF(up)-iomega I_n w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(uomegap)\nendarrayright=leftbeginarrayc\n0_n \n1\nendarrayrightquadquad (M_h)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where wv are chosen in order to have a non-singular matrix (M_h). More precisely, w (resp. v) should be a left (resp. right) approximate null vector of dF(up)-iomega I_n. During continuation, the vectors wv are updated so that the matrix (M_h) remains non-singular ; this is controlled with the argument update_minaug_every_step (see below).","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"note that there are very simplified calls to this, see Newton refinement below. In particular, you don't need to set up the Hopf Minimally Augmented problem yourself. This is done in the background.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"warning: Linear Method\nYou can pass the bordered linear solver to solve (M_h) using the option bdlinsolver (see below). Note that the choice bdlinsolver = BorderingBLS() can lead to singular systems. Indeed, in this case, (M_h) is solved by inverting dF(u,p)-iω I_n which is singular at Hopf points.","category":"page"},{"location":"codim2Continuation/#Detection-of-codim-2-bifurcation-points-2","page":"Fold / Hopf Continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the option detect_codim2_bifurcation in the method continuation. Under the hood, the detection of these bifurcations is done by using Event detection as explained in Event Handling.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"the detection of Bogdanov-Takens (BT) is performed using the test function[Bindel],[Blank] psi_BT(p) = \tlangle w(p)v(p)rangle\nthe detection of Bautin (GH) is based on the test function psi_GH(p) = Re(l_1(p)) where l_1 is the Lyapunov coefficient defined in Simple Hopf point.\nthe detection of Zero-Hopf (ZH) is performed by monitoring the eigenvalues.\nthe detection of Hopf-Hopf (HH) is performed by monitoring the eigenvalues.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"The continuation of Hopf points is stopped at BT and when omega100epsilon where epsilon is the newton tolerance.","category":"page"},{"location":"codim2Continuation/#jac-fold","page":"Fold / Hopf Continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"In order to apply the newton algorithm to F_f or F_h, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to F_f (or F_h) and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian F_f (or F_h) and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"codim2Continuation/#Newton-refinement","page":"Fold / Hopf Continuation (2 params)","title":"Newton refinement","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Once a Fold / Hopf point has been detected after a call to br = continuation(...), it can be refined using newton iterations. Let us say that ind_bif is the index in br.specialpoint of a Fold / Hopf point. This guess can be refined as follows:","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"outfold = newton(br::AbstractBranchResult, ind_bif::Int; \n\tnormN = norm, options = br.contparams.newton_options,\n\tbdlinsolver = BorderingBLS(options.linsolver),\n\tstart_with_eigen = false, kwargs...)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"For the options parameters, we refer to Newton.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"It is important to note that for improved performances, a function implementing the expression of the hessian should be provided. This is by far the fastest. BifurcationProblem provides it by default using AD though.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Reader interested in this advanced usage should look at the code example/chan.jl of the tutorial Temperature model.","category":"page"},{"location":"codim2Continuation/#Codim-2-continuation","page":"Fold / Hopf Continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"To compute the codim 2 curve of Fold / Hopf points, one can call continuation with the following options","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"where the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"See Temperature model for an example of use.","category":"page"},{"location":"codim2Continuation/#Advanced-use","page":"Fold / Hopf Continuation (2 params)","title":"Advanced use","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"Here, we expose the solvers that are used to perform newton refinement or codim 2 continuation in case the above methods fails. This is useful in case it is too involved to expose the linear solver options. An example of advanced use is the continuation of Folds of periodic orbits, see Continuation of Fold of periodic orbits.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"newton_fold","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"newton_hopf","category":"page"},{"location":"codim2Continuation/#BifurcationKit.newton_hopf","page":"Fold / Hopf Continuation (2 params)","title":"BifurcationKit.newton_hopf","text":"newton_hopf(\n prob,\n hopfpointguess,\n par,\n eigenvec,\n eigenvec_ad,\n options;\n normN,\n bdlinsolver,\n usehessian,\n kwargs...\n)\n\n\nThis function turns an initial guess for a Hopf point into a solution to the Hopf problem based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationProblem where p is a set of parameters.\nhopfpointguess initial guess (x0, p0) for the Hopf point. It should a BorderedArray as returned by the function HopfPoint.\npar parameters used for the vector field\neigenvec guess for the iω eigenvector\neigenvec_ad guess for the -iω eigenvector\noptions::NewtonPar options for the Newton-Krylov algorithm, see NewtonPar.\n\nOptional arguments:\n\nnormN = norm\nbdlinsolver bordered linear solver for the constraint equation\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\nSimplified call:\n\nSimplified call to refine an initial guess for a Hopf point. More precisely, the call is as follows\n\nnewton_hopf(br::AbstractBranchResult, ind_hopf::Int; normN = norm, options = br.contparams.newton_options, kwargs...)\n\nThe parameters / options are as usual except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of bifurcation point in br you want to refine. You can pass newton parameters different from the ones stored in br by using the argument options.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian will be computed twice!\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\n\n\n\n\n","category":"function"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"continuation_fold","category":"page"},{"location":"codim2Continuation/#BifurcationKit.continuation_fold","page":"Fold / Hopf Continuation (2 params)","title":"BifurcationKit.continuation_fold","text":"continuation_fold(\n prob,\n alg,\n foldpointguess,\n par,\n lens1,\n lens2,\n eigenvec,\n eigenvec_ad,\n options_cont;\n update_minaug_every_step,\n normC,\n bdlinsolver,\n bdlinsolver_adjoint,\n jacobian_ma,\n compute_eigen_elements,\n usehessian,\n kind,\n record_from_solution,\n kwargs...\n)\n\n\nCodim 2 continuation of Fold points. This function turns an initial guess for a Fold point into a curve of Fold points based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationFunction\nfoldpointguess initial guess (x0, p10) for the Fold point. It should be a BorderedArray as returned by the function foldpoint\npar set of parameters\nlens1 parameter axis for parameter 1\nlens2 parameter axis for parameter 2\neigenvec guess for the right null vector\neigenvec_ad guess for the left null vector\noptions_cont arguments to be passed to the regular continuation\n\nOptional arguments:\n\njacobian_ma::Symbol = :autodiff, how the linear system of the Fold problem is solved. Can be :autodiff, :finiteDifferencesMF, :finiteDifferences, :minaug\nbdlinsolver bordered linear solver for the constraint equation with top-left block J. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nbdlinsolver_adjoint bordered linear solver for the constraint equation with top-left block J^*. Required in the linear solver for the Minimally Augmented Fold functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nupdate_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps\ncompute_eigen_elements = false whether to compute eigenelements. If options_cont.detect_event>0, it allows the detection of ZH points.\nkwargs keywords arguments to be passed to the regular continuation\n\nSimplified call\n\ncontinuation_fold(br::AbstractBranchResult, ind_fold::Int64, lens2::Lens, options_cont::ContinuationPar ; kwargs...)\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Fold point in br that you want to continue.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian would be computed twice!\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS(). This is the default setting.\n\ntip: Detection of Bogdanov-Takens and Cusp bifurcations\nIn order to trigger the detection, pass detect_event = 1 or 2 in options_cont.\n\n\n\n\n\n","category":"function"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"continuation_hopf","category":"page"},{"location":"codim2Continuation/#BifurcationKit.continuation_hopf","page":"Fold / Hopf Continuation (2 params)","title":"BifurcationKit.continuation_hopf","text":"continuation_hopf(\n prob_vf,\n alg,\n hopfpointguess,\n par,\n lens1,\n lens2,\n eigenvec,\n eigenvec_ad,\n options_cont;\n update_minaug_every_step,\n normC,\n linsolve_adjoint,\n bdlinsolver,\n bdlinsolver_adjoint,\n jacobian_ma,\n compute_eigen_elements,\n usehessian,\n kind,\n massmatrix,\n record_from_solution,\n kwargs...\n)\n\n\ncodim 2 continuation of Hopf points. This function turns an initial guess for a Hopf point into a curve of Hopf points based on a Minimally Augmented formulation. The arguments are as follows\n\nprob::AbstractBifurcationProblem\nhopfpointguess initial guess (x0, p10) for the Hopf point. It should be a Vector or a BorderedArray\npar set of parameters\nlens1 parameter axis for parameter 1\nlens2 parameter axis for parameter 2\neigenvec guess for the iω eigenvector at p1_0\neigenvec_ad guess for the -iω eigenvector at p1_0\noptions_cont keywords arguments to be passed to the regular continuation\n\nOptional arguments:\n\njacobian_ma::Symbol = :autodiff, how the linear system of the Fold problem is solved. Can be :autodiff, :finiteDifferencesMF, :finiteDifferences, :minaug\nlinsolve_adjoint solver for (J+iω)^* ⋅sol = rhs\nbdlinsolver bordered linear solver for the constraint equation with top-left block (J-iω). Required in the linear solver for the Minimally Augmented Hopf functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nbdlinsolver_adjoint bordered linear solver for the constraint equation with top-left block (J-iω)^*. Required in the linear solver for the Minimally Augmented Hopf functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.\nupdate_minaug_every_step update vectors a,b in Minimally Formulation every update_minaug_every_step steps\ncompute_eigen_elements = false whether to compute eigenelements. If options_cont.detect_event>0, it allows the detection of ZH, HH points.\nkwargs keywords arguments to be passed to the regular continuation\n\nSimplified call:\n\ncontinuation_hopf(br::AbstractBranchResult, ind_hopf::Int, lens2::Lens, options_cont::ContinuationPar ; kwargs...)\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br that you want to refine.\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS(). This is the default setting.\n\ntip: Jacobian transpose\nThe adjoint of the jacobian J is computed internally when Jᵗ = nothing by using transpose(J) which works fine when J is an AbstractArray. In this case, do not pass the jacobian adjoint like Jᵗ = (x, p) -> transpose(d_xF(x, p)) otherwise the jacobian would be computed twice!\n\ntip: Detection of Bogdanov-Takens and Bautin bifurcations\nIn order to trigger the detection, pass detect_event = 1,2 in options_cont. Note that you need to provide d3F in prob.\n\n\n\n\n\n","category":"function"},{"location":"codim2Continuation/#Algorithmic-details-(Fold)","page":"Fold / Hopf Continuation (2 params)","title":"Algorithmic details (Fold)","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"If we write (ssigma) the solution of the adjoint problem associated to (M_f), one can show[Govaerts] that the differential of sigma satisfies:","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"partial sigma + langle spartial dF cdot rrangle = 0","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"This allows to compute the jacobian of the Fold functional to use for the Newton algorithm:","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarraycc\npartial_uF(up) partial_pF(up) \npartial_xsigma(up) partial_psigma(up)\nendarrayright","category":"page"},{"location":"codim2Continuation/#Algorithmic-details-(Hopf)","page":"Fold / Hopf Continuation (2 params)","title":"Algorithmic details (Hopf)","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"We recall that the unknowns are (xpomega). The jacobian of the Hopf functional to use for the Newton algorithm is","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"leftbeginarrayccc\npartial_uF partial_pF 0 \npartial_xsigma_r partial_psigma_r partial_omegasigma_r\npartial_xsigma_i partial_psigma_i partial_omegasigma_i\nendarrayright","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"using a similar formula for partialsigma as in the Fold case.","category":"page"},{"location":"codim2Continuation/#References","page":"Fold / Hopf Continuation (2 params)","title":"References","text":"","category":"section"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Blank]: Blank, H. J. de, Yu. A. Kuznetsov, M. J. Pekkér, and D. W. M. Veldman. “Degenerate Bogdanov–Takens Bifurcations in a One-Dimensional Transport Model of a Fusion Plasma.” Physica D: Nonlinear Phenomena 331 (September 15, 2016): 13–26. https://doi.org/10.1016/j.physd.2016.05.008.","category":"page"},{"location":"codim2Continuation/","page":"Fold / Hopf Continuation (2 params)","title":"Fold / Hopf Continuation (2 params)","text":"[Bindel]: Bindel, D., M. Friedman, W. Govaerts, J. Hughes, and Yu.A. Kuznetsov. “Numerical Computation of Bifurcations in Large Equilibrium Systems in Matlab.” Journal of Computational and Applied Mathematics 261 (May 2014): 232–48. https://doi.org/10.1016/j.cam.2013.10.034.","category":"page"},{"location":"library/#Library","page":"Library","title":"Library","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"Pages = [\"library.md\"]\nDepth = 3","category":"page"},{"location":"library/#Parameters","page":"Library","title":"Parameters","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"NewtonPar","category":"page"},{"location":"library/#BifurcationKit.NewtonPar","page":"Library","title":"BifurcationKit.NewtonPar","text":"struct NewtonPar{T, L<:BifurcationKit.AbstractLinearSolver, E<:AbstractEigenSolver}\n\nReturns a variable containing parameters to affect the newton algorithm when solving F(x) = 0.\n\nArguments (with default values):\n\ntol::Any: absolute tolerance for F(x) Default: 1.0e-12\nmax_iterations::Int64: number of Newton iterations Default: 25\nverbose::Bool: display Newton iterations? Default: false\nlinsolver::BifurcationKit.AbstractLinearSolver: linear solver, must be <: AbstractLinearSolver Default: DefaultLS()\neigsolver::AbstractEigenSolver: eigen solver, must be <: AbstractEigenSolver Default: DefaultEig()\nlinesearch::Bool: Default: false\nα::Any: Default: convert(typeof(tol), 1.0)\nαmin::Any: Default: convert(typeof(tol), 0.001)\n\nArguments for line search (Armijo)\n\nlinesearch = false: use line search algorithm (i.e. Newton with Armijo's rule)\nα = 1.0: initial value of α (damping) parameter for line search algorithm\nαmin = 0.001: minimal value of the damping alpha\n\ntip: Mutating\nFor performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See the tutorials for examples.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"ContinuationPar","category":"page"},{"location":"library/#BifurcationKit.ContinuationPar","page":"Library","title":"BifurcationKit.ContinuationPar","text":"options = ContinuationPar(dsmin = 1e-4,...)\n\nReturns a variable containing parameters to affect the continuation algorithm used to solve F(x,p) = 0.\n\nArguments\n\ndsmin, dsmax are the minimum, maximum arclength allowed value. It controls the density of points in the computed branch of solutions.\nds = 0.01 is the initial arclength.\np_min, p_max allowed parameter range for p\nmax_steps = 100 maximum number of continuation steps\nnewton_options::NewtonPar: options for the Newton algorithm\nsave_to_file = false: save to file. A name is automatically generated or can be defined in continuation. This requires using JLD2.\nsave_sol_every_step::Int64 = 0 at which continuation steps do we save the current solution\nplot_every_step = 10 at which continuation steps do we plot the current solution\n\nHandling eigen elements, their computation is triggered by the argument detect_bifurcation (see below)\n\nnev = 3 number of eigenvalues to be computed. It is automatically increased to have at least nev unstable eigenvalues. To be set for proper bifurcation detection. See Detection of bifurcation points of Equilibria for more informations.\nsave_eig_every_step = 1 record eigen vectors every specified steps. Important for memory limited resource, e.g. GPU.\nsave_eigenvectors = true Important for memory limited resource, e.g. GPU.\n\nHandling bifurcation detection\n\ntol_stability = 1e-10 lower bound on the real part of the eigenvalues to test for stability of equilibria and periodic orbits\ndetect_fold = true detect Fold bifurcations? It is a useful option although the detection of Fold is cheap. Indeed, it may happen that there is a lot of Fold points and this can saturate the memory in memory limited devices (e.g. on GPU)\ndetect_bifurcation::Int ∈ {0, 1, 2, 3} If set to 0, nothing is done. If set to 1, the eigen-elements are computed. If set to 2, the bifurcations points are detected during the continuation run, but not located precisely. If set to 3, a bisection algorithm is used to locate the bifurcations points (slower). The possibility to switch off detection is a useful option. Indeed, it may happen that there are a lot of bifurcation points and this can saturate the memory of memory limited devices (e.g. on GPU)\ndsmin_bisection = 1e-16 dsmin for the bisection algorithm for locating bifurcation points\nn_inversion = 2 number of sign inversions in bisection algorithm\nmax_bisection_steps = 15 maximum number of bisection steps\ntol_bisection_eigenvalue = 1e-16 tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps\n\nHandling ds adaptation (see continuation for more information)\n\na = 0.5 aggressiveness factor. It is used to adapt ds in order to have a number of newton iterations per continuation step roughly constant. The higher a is, the larger the step size ds is changed at each continuation step.\n\nHandling event detection\n\ndetect_event::Int ∈ {0, 1, 2} If set to 0, nothing is done. If set to 1, the event locations are sought during the continuation run, but not located precisely. If set to 2, a bisection algorithm is used to locate the event (slower).\ntol_param_bisection_event = 1e-16 tolerance on parameter to locate event\n\nMisc\n\nη = 150. parameter to estimate tangent at first point with parameter p₀ + ds / η\ndetect_loop [WORK IN PROGRESS] detect loops in the branch and stop the continuation\n\ntip: Mutating\nFor performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Setfield.jl to drastically simplify the mutation of different fields. See tutorials for more examples.\n\n\n\n\n\n","category":"type"},{"location":"library/#Results","page":"Library","title":"Results","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"NonLinearSolution","category":"page"},{"location":"library/#BifurcationKit.NonLinearSolution","page":"Library","title":"BifurcationKit.NonLinearSolution","text":"Structure which holds the solution from application of Newton-Krylov algorithm to a nonlinear problem.\n\nFor example\n\nsol = newton(prob, NewtonPar())\n\nFields\n\nu::Any: solution\nprob::Any: nonlinear problem, typically a BifurcationProblem\nresiduals::Any: sequence of residuals\nconverged::Bool: has algorithm converged?\nitnewton::Int64: number of newton steps\nitlineartot::Any: total number of linear iterations\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"ContResult","category":"page"},{"location":"library/#BifurcationKit.ContResult","page":"Library","title":"BifurcationKit.ContResult","text":"struct ContResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tbr, Teigvals, Teigvec, Biftype, Tsol, Tparc, Tprob, Talg} <: BifurcationKit.AbstractResult{Tkind<:BifurcationKit.AbstractContinuationKind, Tprob}\n\nStructure which holds the results after a call to continuation.\n\nYou can see the propertynames of a result br by using propertynames(br) or propertynames(br.branch).\n\nFields\n\nbranch::StructArrays.StructArray: holds the low-dimensional information about the branch. More precisely, branch[i+1] contains the following information (record_from_solution(u, param), param, itnewton, itlinear, ds, θ, n_unstable, n_imag, stable, step) for each continuation step i.\nitnewton number of Newton iterations\nitlinear total number of linear iterations during newton (corrector)\nn_unstable number of eigenvalues with positive real part for each continuation step (to detect stationary bifurcation)\nn_imag number of eigenvalues with positive real part and non zero imaginary part at current continuation step (useful to detect Hopf bifurcation).\nstable stability of the computed solution for each continuation step. Hence, stable should match eig[step] which corresponds to branch[k] for a given k.\nstep continuation step (here equal i)\neig::Array{@NamedTuple{eigenvals::Teigvals, eigenvecs::Teigvec, converged::Bool, step::Int64}, 1} where {Teigvals, Teigvec}: A vector with eigen-elements at each continuation step.\nsol::Any: Vector of solutions sampled along the branch. This is set by the argument save_sol_every_step::Int64 (default 0) in ContinuationPar.\ncontparams::Any: The parameters used for the call to continuation which produced this branch. Must be a ContinuationPar\nkind::BifurcationKit.AbstractContinuationKind: Type of solutions computed in this branch. Default: EquilibriumCont()\nprob::Any: Bifurcation problem used to compute the branch, useful for branch switching. For example, when computing periodic orbits, the functional PeriodicOrbitTrapProblem, ShootingProblem... will be saved here. Default: nothing\nspecialpoint::Vector: A vector holding the set of detected bifurcation points. See SpecialPoint for a list of special points.\nalg::Any: Continuation algorithm used for the computation of the branch\n\nAssociated methods\n\nlength(br) number of the continuation steps\nshow(br) display information about the branch\neigenvals(br, ind) returns the eigenvalues for the ind-th continuation step\neigenvec(br, ind, indev) returns the indev-th eigenvector for the ind-th continuation step\nget_normal_form(br, ind) compute the normal form of the ind-th points in br.specialpoint\ngetlens(br) return the parameter axis used for the branch\ngetlenses(br) return the parameter two axis used for the branch when 2 parameters continuation is used (Fold, Hopf, NS, PD)\nbr[k+1] gives information about the k-th step. A typical run yields the following\n\njulia> br[1]\n(x = 0.0, param = 0.1, itnewton = 0, itlinear = 0, ds = -0.01, θ = 0.5, n_unstable = 2, n_imag = 2, stable = false, step = 0, eigenvals = ComplexF64[0.1 - 1.0im, 0.1 + 1.0im], eigenvecs = ComplexF64[0.7071067811865475 - 0.0im 0.7071067811865475 + 0.0im; 0.0 + 0.7071067811865475im 0.0 - 0.7071067811865475im])\n\nwhich provides the value param of the parameter of the current point, its stability, information on the newton iterations, etc. The fields can be retrieved using propertynames(br.branch). This information is stored in br.branch which is a StructArray. You can thus extract the vector of parameters along the branch as\n\njulia> br.param\n10-element Vector{Float64}:\n 0.1\n 0.08585786437626905\n 0.06464466094067263\n 0.03282485578727799\n-1.2623798512809007e-5\n-0.07160718539365075\n-0.17899902778635765\n-0.3204203840236672\n-0.4618417402609767\n-0.5\n\nget_solx(br, k) returns the k-th solution on the branch\nget_solp(br, k) returns the parameter value associated with k-th solution on the branch\ngetparams(br) Parameters passed to continuation and used in the equation F(x, par) = 0.\nsetparam(br, p0) set the parameter value p0 according to ::Lens for the parameters of the problem br.prob\ngetlens(br) get the lens used for the computation of the branch\ncontinuation(br, ind) performs automatic branch switching (aBS) from ind-th bifurcation point. Typically branching from equilibrium to equilibrium, or periodic orbit to periodic orbit.\ncontinuation(br, ind, lens2) performs two parameters (getLens(br), lens2) continuation of the ind-th bifurcation point.\ncontinuation(br, ind, probPO::AbstractPeriodicOrbitProblem) performs aBS from ind-th bifurcation point (which must be a Hopf bifurcation point) to branch of periodic orbits.\n\n\n\n\n\n","category":"type"},{"location":"library/#Problems","page":"Library","title":"Problems","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifFunction","category":"page"},{"location":"library/#BifurcationKit.BifFunction","page":"Library","title":"BifurcationKit.BifFunction","text":"struct BifFunction{Tf, Tdf, Tdfad, Tj, Tjad, Td2f, Td2fc, Td3f, Td3fc, Tsym, Tδ} <: BifurcationKit.AbstractBifurcationFunction\n\nStructure to hold the vector field and its derivatives. It should rarely be called directly. Also, in essence, it is very close to SciMLBase.ODEFunction.\n\nFields\n\nF::Any: Vector field. Function of type out-of-place result = f(x, p) or inplace f(result, x, p). For type stability, the types of x and result should match\ndF::Any: Differential of F with respect to x, signature dF(x,p,dx)\ndFad::Any: Adjoint of the Differential of F with respect to x, signature dFad(x,p,dx)\nJ::Any: Jacobian of F at (x, p). It can assume three forms. 1. Either J is a function and J(x, p) returns a ::AbstractMatrix. In this case, the default arguments of contparams::ContinuationPar will make continuation work. 2. Or J is a function and J(x, p) returns a function taking one argument dx and returning dr of the same type as dx. In our notation, dr = J * dx. In this case, the default parameters of contparams::ContinuationPar will not work and you have to use a Matrix Free linear solver, for example GMRESIterativeSolvers, 3. Or J is a function and J(x, p) returns a variable j which can assume any type. Then, you must implement a linear solver ls as a composite type, subtype of AbstractLinearSolver which is called like ls(j, rhs) and which returns the solution of the jacobian linear system. See for example examples/SH2d-fronts-cuda.jl. This linear solver is passed to NewtonPar(linsolver = ls) which itself passed to ContinuationPar. Similarly, you have to implement an eigensolver eig as a composite type, subtype of AbstractEigenSolver.\nJᵗ::Any: jacobian adjoint, it should be implemented in an efficient manner. For matrix-free methods, transpose is not readily available and the user must provide a dedicated method. In the case of sparse based jacobian, Jᵗ should not be passed as it is computed internally more efficiently, i.e. it avoids recomputing the jacobian as it would be if you pass Jᵗ = (x, p) -> transpose(dF(x, p)).\nd2F::Any: Second Differential of F with respect to x, signature d2F(x,p,dx1,dx2)\nd3F::Any: Third Differential of F with respect to x, signature d3F(x,p,dx1,dx2,dx3)\nd2Fc::Any: [internal] Second Differential of F with respect to x which accept complex vectors dxi\nd3Fc::Any: [internal] Third Differential of F with respect to x which accept complex vectors dxi\nisSymmetric::Any: Whether the jacobian is auto-adjoint.\nδ::Any: used internally to compute derivatives (with finite differences), for example for normal form computation and codim 2 continuation.\ninplace::Bool: optionally sets whether the function is inplace or not\n\nMethods\n\nresidual(pb::BifFunction, x, p) calls pb.F(x,p)\njacobian(pb::BifFunction, x, p) calls pb.J(x, p)\ndF(pb::BifFunction, x, p, dx) calls pb.dF(x,p,dx)\netc\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationProblem","category":"page"},{"location":"library/#BifurcationKit.BifurcationProblem","page":"Library","title":"BifurcationKit.BifurcationProblem","text":"struct BifurcationProblem{Tvf, Tu, Tp, Tl<:Lens, Tplot, Trec} <: BifurcationKit.AbstractAllJetBifProblem\n\nStructure to hold the bifurcation problem.\n\nFields\n\nVF::Any: Vector field, typically a BifFunction\nu0::Any: Initial guess\nparams::Any: parameters\nlens::Lens: Typically a Setfield.Lens. It specifies which parameter axis among params is used for continuation. For example, if par = (α = 1.0, β = 1), we can perform continuation w.r.t. α by using lens = (@lens _.α). If you have an array par = [ 1.0, 2.0] and want to perform continuation w.r.t. the first variable, you can use lens = (@lens _[1]). For more information, we refer to SetField.jl.\nplotSolution::Any: user function to plot solutions during continuation. Signature: plot_solution(x, p; kwargs...) for Plot.jl and plot_solution(ax, x, p; kwargs...) for the Makie package(s).\nrecordFromSolution::Any: record_from_solution = (x, p) -> norm(x) function used record a few indicators about the solution. It could be norm or (x, p) -> x[1]. This is also useful when saving several huge vectors is not possible for memory reasons (for example on GPU). This function can return pretty much everything but you should keep it small. For example, you can do (x, p) -> (x1 = x[1], x2 = x[2], nrm = norm(x)) or simply (x, p) -> (sum(x), 1). This will be stored in contres.branch where contres::ContResult is the continuation curve of the bifurcation problem. Finally, the first component is used for plotting in the continuation curve.\n\nMethods\n\nre_make(pb; kwargs...) modify a bifurcation problem\ngetu0(pb) calls pb.u0\ngetparams(pb) calls pb.params\ngetlens(pb) calls pb.lens\ngetparam(pb) calls get(pb.params, pb.lens)\nsetparam(pb, p0) calls set(pb.params, pb.lens, p0)\nrecord_from_solution(pb) calls pb.recordFromSolution\nplot_solution(pb) calls pb.plotSolution\nis_symmetric(pb) calls is_symmetric(pb.prob)\n\nConstructors\n\nBifurcationProblem(F, u0, params, lens) all derivatives are computed using ForwardDiff.\nBifurcationProblem(F, u0, params, lens; J, Jᵗ, d2F, d3F, kwargs...) and kwargs are the fields above. You can pass your own jacobian with J (see BifFunction for description of the jacobian function) and jacobian adjoint with Jᵗ. For example, this can be used to provide finite differences based jacobian using BifurcationKit.finiteDifferences.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"DeflationOperator","category":"page"},{"location":"library/#BifurcationKit.DeflationOperator","page":"Library","title":"BifurcationKit.DeflationOperator","text":"struct DeflationOperator{Tp<:Real, Tdot, T<:Real, vectype} <: BifurcationKit.AbstractDeflationFactor\n\nStructure for defining a custom distance.\n\nThis operator allows to handle the following situation. Assume you want to solve F(x)=0 with a Newton algorithm but you want to avoid the process to return some already known solutions roots_i. The deflation operator penalizes these roots. You can create a DeflationOperator to define a scalar function M(u) used to find, with Newton iterations, the zeros of the following function F(u) cdot Π_i(u - root_i^-2p + alpha) = F(u) cdot M(u) where u^2 = dot(u u). The fields of the struct DeflationOperator are as follows:\n\npower::Real: power p. You can use an Int for example\ndot::Any: function, this function has to be bilinear and symmetric for the linear solver to work well\nα::Real: shift\nroots::Vector: roots\ntmp::Any\nautodiff::Bool\nδ::Real\n\nGiven defOp::DeflationOperator, one can access its roots via defOp[n] as a shortcut for defOp.roots[n]. Note that you can also use defOp[end].\n\nAlso, one can add (resp. remove) a new root by using push!(defOp, newroot) (resp. pop!(defOp)). Finally length(defOp) is a shortcut for length(defOp.roots)\n\nConstructors\n\nDeflationOperator(p::Real, α::Real, roots::Vector{vectype}; autodiff = false)\nDeflationOperator(p::Real, dt, α::Real, roots::Vector{vectype}; autodiff = false)\nDeflationOperator(p::Real, α::Real, roots::Vector{vectype}, v::vectype; autodiff = false)\n\nThe option autodiff triggers the use of automatic differentiation for the computation of the gradient of the scalar function M. This works only on AbstractVector for now.\n\nCustom distance\n\nYou are asked to pass a scalar product like dot to build a DeflationOperator. However, in some cases, you may want to pass a custom distance dist(u, v). You can do this using\n\n`DeflationOperator(p, CustomDist(dist), α, roots)`\n\nNote that passing CustomDist(dist, true) will trigger the use of automatic differentiation for the gradient of M.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"DeflatedProblem","category":"page"},{"location":"library/#BifurcationKit.DeflatedProblem","page":"Library","title":"BifurcationKit.DeflatedProblem","text":"pb = DeflatedProblem(prob, M::DeflationOperator, jactype)\n\nCreate a DeflatedProblem.\n\nThis creates a deflated functional (problem) M(u) cdot F(u) = 0 where M is a DeflationOperator which encodes the penalization term. prob is an AbstractBifurcationProblem which encodes the functional. It is not meant not be used directly albeit by advanced users.\n\n\n\n\n\n","category":"type"},{"location":"library/#Periodic-orbits","page":"Library","title":"Periodic orbits","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"PeriodicOrbitTrapProblem","category":"page"},{"location":"library/#BifurcationKit.PeriodicOrbitTrapProblem","page":"Library","title":"BifurcationKit.PeriodicOrbitTrapProblem","text":"This composite type implements Finite Differences based on a Trapezoidal rule (Order 2 in time) to locate periodic orbits. More details (maths, notations, linear systems) can be found here.\n\nFields\n\nprob a bifurcation problem\nM::Int number of time slices\nϕ used to set a section for the phase constraint equation, of size N*M\nxπ used in the section for the phase constraint equation, of size N*M\nlinsolver: = DefaultLS() linear solver for each time slice, i.e. to solve J⋅sol = rhs. This is only needed for the computation of the Floquet multipliers in a full matrix-free setting.\nongpu::Bool whether the computation takes place on the gpu (Experimental)\nmassmatrix a mass matrix. You can pass for example a sparse matrix. Default: identity matrix.\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).\n\nThe scheme is as follows. We first consider a partition of 01 given by 0s_0cdotss_m=1 and one looks for T = x[end] such that\n\nM_acdotleft(x_i - x_i-1right) - fracTcdot h_i2 left(F(x_i) + F(x_i-1)right) = 0 i=1cdotsm-1\n\nwith u_0 = u_m-1 and the periodicity condition u_m - u_1 = 0 and\n\nwhere h_1 = s_i-s_i-1. M_a is a mass matrix. Finally, the phase of the periodic orbit is constrained by using a section (but you could use your own)\n\nsum_ilangle x_i - x_pii phi_irangle=0\n\nConstructors\n\nThe structure can be created by calling PeriodicOrbitTrapProblem(;kwargs...). For example, you can declare such a problem without vector field by doing\n\nPeriodicOrbitTrapProblem(M = 100)\n\nOrbit guess\n\nYou will see below that you can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be a vector of size M * N + 1 where N is the number of unknowns in the state space and orbitguess[M*N+1] is an estimate of the period T of the limit cycle. More precisely, using the above notations, orbitguess must be orbitguess = x_1x_2cdotsx_M T.\n\nNote that you can generate this guess from a function solution using generateSolution.\n\nFunctional\n\nA functional, hereby called G, encodes this problem. The following methods are available\n\npb(orbitguess, p) evaluates the functional G on orbitguess\npb(orbitguess, p, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du\npb(Val(:JacFullSparse), orbitguess, p) return the sparse matrix of the jacobian dG(orbitguess) at orbitguess without the constraints. It is called A_γ in the docs.\npb(Val(:JacFullSparseInplace), J, orbitguess, p). Same as pb(Val(:JacFullSparse), orbitguess, p) but overwrites J inplace. Note that the sparsity pattern must be the same independently of the values of the parameters or of orbitguess. In this case, this is significantly faster than pb(Val(:JacFullSparse), orbitguess, p).\npb(Val(:JacCyclicSparse), orbitguess, p) return the sparse cyclic matrix Jc (see the docs) of the jacobian dG(orbitguess) at orbitguess\npb(Val(:BlockDiagSparse), orbitguess, p) return the diagonal of the sparse matrix of the jacobian dG(orbitguess) at orbitguess. This allows to design Jacobi preconditioner. Use blockdiag.\n\nJacobian\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\nnote: GPU call\nFor these methods to work on the GPU, for example with CuArrays in mode allowscalar(false), we face the issue that the function extract_period_fdtrap won't be well defined because it is a scalar operation. Note that you must pass the option ongpu = true for the functional to be evaluated efficiently on the gpu.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"PeriodicOrbitOCollProblem","category":"page"},{"location":"library/#BifurcationKit.PeriodicOrbitOCollProblem","page":"Library","title":"BifurcationKit.PeriodicOrbitOCollProblem","text":"pb = PeriodicOrbitOCollProblem(kwargs...)\n\nThis composite type implements an orthogonal collocation (at Gauss points) method of piecewise polynomials to locate periodic orbits. More details (maths, notations, linear systems) can be found here.\n\nArguments\n\nprob a bifurcation problem\nϕ::AbstractVector used to set a section for the phase constraint equation\nxπ::AbstractVector used in the section for the phase constraint equation\nN::Int dimension of the state space\nmesh_cache::MeshCollocationCache cache for collocation. See docs of MeshCollocationCache\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian = DenseAnalytical() describes the type of jacobian used in Newton iterations. Can only be AutoDiffDense(), DenseAnalytical(), FullSparse(), FullSparseInplace().\nmeshadapt::Bool = false whether to use mesh adaptation\nverbose_mesh_adapt::Bool = true verbose mesh adaptation information\nK::Float64 = 500 parameter for mesh adaptation, control new mesh step size. More precisely, we set max(hᵢ) / min(hᵢ) ≤ K if hᵢ denotes the time steps.\n\nMethods\n\nHere are some useful methods you can apply to pb\n\nlength(pb) gives the total number of unknowns\nsize(pb) returns the triplet (N, m, Ntst)\ngetmesh(pb) returns the mesh 0 = τ0 < ... < τNtst+1 = 1. This is useful because this mesh is born to vary during automatic mesh adaptation\nget_mesh_coll(pb) returns the (static) mesh 0 = σ0 < ... < σm+1 = 1\nget_times(pb) returns the vector of times (length 1 + m * Ntst) at the which the collocation is applied.\ngenerate_solution(pb, orbit, period) generate a guess from a function t -> orbit(t) which approximates the periodic orbit.\nPOSolution(pb, x) return a function interpolating the solution x using a piecewise polynomials function\n\nOrbit guess\n\nYou can evaluate the residual of the functional (and other things) by calling pb(orbitguess, p) on an orbit guess orbitguess. Note that orbitguess must be of size 1 + N * (1 + m * Ntst) where N is the number of unknowns in the state space and orbitguess[end] is an estimate of the period T of the limit cycle.\n\nConstructors\n\nPeriodicOrbitOCollProblem(Ntst::Int, m::Int; kwargs) creates an empty functional with Ntst and m.\n\nNote that you can generate this guess from a function using generate_solution.\n\nFunctional\n\nA functional, hereby called G, encodes this problem. The following methods are available\n\npb(orbitguess, p) evaluates the functional G on orbitguess\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"ShootingProblem","category":"page"},{"location":"library/#BifurcationKit.ShootingProblem","page":"Library","title":"BifurcationKit.ShootingProblem","text":"pb = ShootingProblem(flow::Flow, ds, section; parallel = false)\n\nCreate a problem to implement the Standard Simple / Parallel Multiple Standard Shooting method to locate periodic orbits. More details (maths, notations, linear systems) can be found here. The arguments are as follows\n\nflow::Flow: implements the flow of the Cauchy problem though the structure Flow.\nds: vector of time differences for each shooting. Its length is written M. If M == 1, then the simple shooting is implemented and the multiple one otherwise.\nsection: implements a phase condition. The evaluation section(x, T) must return a scalar number where x is a guess for one point on the periodic orbit and T is the period of the guess. Also, the method section(x, T, dx, dT) must be available and which returns the differential of section. The type of x depends on what is passed to the newton solver. See SectionSS for a type of section defined as a hyperplane.\nparallel whether the shooting is computed in parallel (threading). Available through the use of Flows defined by EnsembleProblem (this is automatically set up for you).\npar parameters of the model\nlens parameter axis\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).\n\nA functional, hereby called G, encodes the shooting problem. For example, the following methods are available:\n\npb(orbitguess, par) evaluates the functional G on orbitguess\npb(orbitguess, par, du) evaluates the jacobian dG(orbitguess)⋅du functional at orbitguess on du.\npb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.\npb(Val(:JacobianMatrix), x, par) same as above but out-of-place.\n\nYou can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N + 1 where N is the number of unknowns of the state space and orbitguess[M * N + 1] is an estimate of the period T of the limit cycle. This form of guess is convenient for the use of the linear solvers in IterativeSolvers.jl (for example) which only accept AbstractVectors. Another accepted guess is of the form BorderedArray(guess, T) where guess[i] is the state of the orbit at the ith time slice. This last form allows for non-vector state space which can be convenient for 2d problems for example, use GMRESKrylovKit for the linear solver in this case.\n\nNote that you can generate this guess from a function solution using generate_solution.\n\nJacobian\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\nSimplified constructors\n\nThe first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points:\n\npb = ShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)\n\nA convenient way to build the functional is to use:\n\npb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, centers::AbstractVector; kwargs...)\n\nwhere prob is an ODEProblem (resp. EnsembleProblem) which is used to create a flow using the ODE solver alg (for example Tsit5()). centers is list of M points close to the periodic orbit, they will be used to build a constraint for the phase. parallel = false is an option to use Parallel simulations (Threading) to simulate the multiple trajectories in the case of multiple shooting. This is efficient when the trajectories are relatively long to compute. Finally, the arguments kwargs are passed to the ODE solver defining the flow. Look at DifferentialEquations.jl for more information. Note that, in this case, the derivative of the flow is computed internally using Finite Differences.\n\nAnother way to create a Shooting problem with more options is the following where in particular, one can provide its own scalar constraint section(x)::Number for the phase:\n\npb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; parallel = false, kwargs...)\n\nor\n\npb = ShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, ds, section; parallel = false, kwargs...)\n\nThe next way is an elaboration of the previous one\n\npb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, M::Int, section; parallel = false, kwargs...)\n\nor\n\npb = ShootingProblem(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, ds, section; parallel = false, kwargs...)\n\nwhere we supply now two ODEProblems. The first one prob1, is used to define the flow associated to F while the second one is a problem associated to the derivative of the flow. Hence, prob2 must implement the following vector field tilde F(xyp) = (F(xp) dF(xp)cdot y).\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"PoincareShootingProblem","category":"page"},{"location":"library/#BifurcationKit.PoincareShootingProblem","page":"Library","title":"BifurcationKit.PoincareShootingProblem","text":"pb = PoincareShootingProblem(flow::Flow, M, sections; δ = 1e-8, interp_points = 50, parallel = false)\n\nThis composite type implements the Poincaré Shooting method to locate periodic orbits by relying on Poincaré return maps. More details (maths, notations, linear systems) can be found here. The arguments are as follows\n\nflow::Flow: implements the flow of the Cauchy problem though the structure Flow.\nM: the number of Poincaré sections. If M == 1, then the simple shooting is implemented and the multiple one otherwise.\nsections: function or callable struct which implements a Poincaré section condition. The evaluation sections(x) must return a scalar number when M == 1. Otherwise, one must implement a function section(out, x) which populates out with the M sections. See SectionPS for type of section defined as a hyperplane.\nδ = 1e-8 used to compute the jacobian of the functional by finite differences. If set to 0, an analytical expression of the jacobian is used instead.\ninterp_points = 50 number of interpolation point used to define the callback (to compute the hitting of the hyperplane section)\nparallel = false whether the shooting are computed in parallel (threading). Only available through the use of Flows defined by EnsembleProblem.\npar parameters of the model\nlens parameter axis\nupdate_section_every_step updates the section every update_section_every_step step during continuation\njacobian::Symbol symbol which describes the type of jacobian used in Newton iterations (see below).\n\nJacobian\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\nSimplified constructors\n\nThe first important constructor is the following which is used for branching to periodic orbits from Hopf bifurcation points pb = PoincareShootingProblem(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)\nA convenient way is to create a functional is\n\npb = PoincareShootingProblem(prob::ODEProblem, alg, section; kwargs...)\n\nfor simple shooting or\n\npb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; kwargs...)\n\nfor multiple shooting . Here prob is an Union{ODEProblem, EnsembleProblem} which is used to create a flow using the ODE solver alg (for example Tsit5()). Finally, the arguments kwargs are passed to the ODE solver defining the flow. We refer to DifferentialEquations.jl for more information.\n\nAnother convenient call is\n\npb = PoincareShootingProblem(prob::Union{ODEProblem, EnsembleProblem}, alg, normals::AbstractVector, centers::AbstractVector; δ = 1e-8, kwargs...)\n\nwhere normals (resp. centers) is a list of normals (resp. centers) which defines a list of hyperplanes Sigma_i. These hyperplanes are used to define partial Poincaré return maps.\n\nComputing the functionals\n\nA functional, hereby called G encodes this shooting problem. You can then call pb(orbitguess, par) to apply the functional to a guess. Note that orbitguess::AbstractVector must be of size M * N where N is the number of unknowns in the state space and M is the number of Poincaré maps. Another accepted guess is such that guess[i] is the state of the orbit on the ith section. This last form allows for non-vector state space which can be convenient for 2d problems for example.\n\nNote that you can generate this guess from a function solution using generate_solution.\n\npb(orbitguess, par) evaluates the functional G on orbitguess\npb(orbitguess, par, du) evaluates the jacobian dG(orbitguess).du functional at orbitguess on du\npb(Val(:JacobianMatrixInplace), J, x, par)` compute the jacobian of the functional analytically. This is based on ForwardDiff.jl. Useful mainly for ODEs.\npb(Val(:JacobianMatrix), x, par) same as above but out-of-place.\n\ntip: Tip\nYou can use the function getperiod(pb, sol, par) to get the period of the solution sol for the problem with parameters par.\n\n\n\n\n\n","category":"type"},{"location":"library/#Waves","page":"Library","title":"Waves","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.TWProblem","category":"page"},{"location":"library/#BifurcationKit.TWProblem","page":"Library","title":"BifurcationKit.TWProblem","text":"TWProblem(prob, ∂::Tuple, u₀; DAE = 0, jacobian::Symbol = :AutoDiff)\n\nThis composite type implements a functional for freezing symmetries in order, for example, to compute travelling waves (TW). Note that you can freeze many symmetries, not just one, by passing many Lie generators. When you call pb(x, par), it computes:\n\n ┌ ┐\n │ f(x, par) - s⋅∂⋅x │\n │ │\n └ ┘\n\nArguments\n\nprob bifurcation problem with continuous symmetries\n∂::Tuple = (T1, T2, ⋯) tuple of Lie generators. In effect, each of these is an (differential) operator which can be specified as a (sparse) matrix or as an operator implementing LinearAlgebra.mul!.\nu₀ reference solution\n\nAdditional Constructor(s)\n\npb = TWProblem(prob, ∂, u₀; kw...)\n\nThis simplified call handles the case where a single symmetry needs to be frozen.\n\nUseful function\n\nupdatesection!(pb::TWProblem, u0) updates the reference solution of the problem using u0.\nnb_constraints(::TWProblem) number of constraints (or Lie generators)\n\n\n\n\n\n","category":"type"},{"location":"library/#Newton","page":"Library","title":"Newton","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"newton","category":"page"},{"location":"library/#BifurcationKit.newton","page":"Library","title":"BifurcationKit.newton","text":" newton(prob::AbstractBifurcationProblem, options::NewtonPar; normN = norm, callback = (;x, fx, J, residual, step, itlinear, options, x0, residuals; kwargs...) -> true, kwargs...)\n\nThis is the Newton-Krylov Solver for F(x, p0) = 0 with Jacobian w.r.t. x written J(x, p0) and initial guess x0. The function normN allows to specify a norm for the convergence criteria. It is important to set the linear solver options.linsolver properly depending on your problem. This linear solver is used to solve J(x p_0)u = -F(x p_0) in the Newton step. You can for example use linsolver = DefaultLS() which is the operator backslash: it works well for Sparse / Dense matrices. See Linear solvers (LS) for more informations.\n\nArguments:\n\nprob a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.\noptions::NewtonPar variable holding the internal parameters used by the newton method\ncallback function passed by the user which is called at the end of each iteration. The default one is the following cb_default((x, fx, J, residual, step, itlinear, options, x0, residuals); k...) = true. Can be used to update a preconditionner for example. You can use for example cbMaxNorm to limit the residuals norms. If yo want to specify your own, the arguments passed to the callback are as follows\nx current solution\nfx current residual\nJ current jacobian\nresidual current norm of the residual\nstep current newton step\nitlinear number of iterations to solve the linear system\noptions a copy of the argument options passed to newton\nresiduals the history of residuals\nkwargs kwargs arguments, contain your initial guess x0\nkwargs arguments passed to the callback. Useful when newton is called from continuation\n\nOutput:\n\nsolution::NonLinearSolution, we refer to NonLinearSolution for more information.\n\nwarning: Linear solver\nMake sure that the linear solver (Matrix-Free...) corresponds to your jacobian (Matrix-Free vs. Matrix based).\n\n\n\n\n\nnewton(prob, defOp, options; ...)\nnewton(prob, defOp, options, _linsolver; kwargs...)\n\n\nThis is the deflated version of the Krylov-Newton Solver for F(x, p0) = 0.\n\nWe refer to the regular newton for more information. It penalises the roots saved in defOp.roots. The other arguments are as for newton. See DeflationOperator for more information on defOp.\n\nArguments\n\nCompared to newton, the only different arguments are\n\ndefOp::DeflationOperator deflation operator\nlinsolver linear solver used to invert the Jacobian of the deflated functional.\ncustom solver DeflatedProblemCustomLS() which requires solving two linear systems J⋅x = rhs.\nFor other linear solvers <: AbstractLinearSolver, a matrix free method is used for the deflated functional.\nif passed Val(:autodiff), then ForwardDiff.jl is used to compute the jacobian Matrix of the deflated problem\nif passed Val(:fullIterative), then a full matrix free method is used for the deflated problem.\n\n\n\n\n\nThis specific Newton-Krylov method first tries to converge to a solution sol0 close the guess x0. It then attempts to converge from the guess x1 while avoiding the previous converged solution close to sol0. This is very handy for branch switching. The method is based on a deflated Newton-Krylov solver.\n\n\n\n\n\nnewton(\n br,\n ind_bif;\n normN,\n options,\n start_with_eigen,\n lens2,\n kwargs...\n)\n\n\nThis function turns an initial guess for a Fold / Hopf point into a solution to the Fold / Hopf problem based on a Minimally Augmented formulation.\n\nArguments\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\n\nOptional arguments:\n\noptions::NewtonPar, default value br.contparams.newton_options\nnormN = norm\noptions You can pass newton parameters different from the ones stored in br by using this argument options.\nbdlinsolver bordered linear solver for the constraint equation\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements.\nkwargs keywords arguments to be passed to the regular Newton-Krylov solver\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\ntip: start_with_eigen\nIt is recommended that you use the option start_with_eigen=true\n\n\n\n\n\nnewton(prob, orbitguess, options; lens, δ, kwargs...)\n\n\nThis is the Newton-Krylov Solver for computing a periodic orbit using the (Standard / Poincaré) Shooting method. Note that the linear solver has to be appropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is either a ShootingProblem or a PoincareShootingProblem. These two problems have specific options to be tuned, we refer to their link for more information and to the tutorials.\n\nprob a problem of type <: AbstractShootingProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit. See ShootingProblem and See PoincareShootingProblem for information regarding the shape of orbitguess.\npar parameters to be passed to the functional\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\nnewton(prob, orbitguess, defOp, options; lens, kwargs...)\n\n\nThis is the deflated Newton-Krylov Solver for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to newton except that prob is either a ShootingProblem or a PoincareShootingProblem.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\nOutput:\n\nsolution::NonLinearSolution, see NonLinearSolution\n\n\n\n\n\nnewton(probPO, orbitguess, options; kwargs...)\n\n\nThis is the Krylov-Newton Solver for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.\n\nArguments:\n\nprob a problem of type PeriodicOrbitTrapProblem encoding the functional G\norbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It should be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.\npar parameters to be passed to the functional\noptions same as for the regular newton method\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\n\n\n\n\nnewton(probPO, orbitguess, defOp, options; kwargs...)\n\n\nThis function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.\n\n\n\n\n\nnewton(probPO, orbitguess, options; kwargs...)\n\n\nThis is the Newton Solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be apropriately set up in options.\n\nArguments\n\nSimilar to newton except that prob is a PeriodicOrbitOCollProblem.\n\nprob a problem of type <: PeriodicOrbitOCollProblem encoding the shooting functional G.\norbitguess a guess for the periodic orbit.\noptions same as for the regular newton method.\n\nOptional argument\n\njacobian Specify the choice of the linear algorithm, which must belong to (AutoDiffDense(), ). This is used to select a way of inverting the jacobian dG\nFor AutoDiffDense(). The jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one using options. The jacobian is formed inplace.\nFor DenseAnalytical() Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\n\n\n\n\n\nnewton(probPO, orbitguess, defOp, options; kwargs...)\n\n\nThis function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.\n\n\n\n\n\n","category":"function"},{"location":"library/#Library-Continuation","page":"Library","title":"Continuation","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.DotTheta","category":"page"},{"location":"library/#BifurcationKit.DotTheta","page":"Library","title":"BifurcationKit.DotTheta","text":"struct DotTheta{Tdot, Ta}\n\ndot::Any: dot product used in pseudo-arclength constraint\napply!::Any: Linear operator associated with dot product, i.e. dot(x, y) = , where <,> is the standard dot product on R^N. You must provide an inplace function which evaluates A. For example x -> rmul!(x, 1/length(x)).\n\nThis parametric type allows to define a new dot product from the one saved in dt::dot. More precisely:\n\ndt(u1, u2, p1::T, p2::T, theta::T) where {T <: Real}\n\ncomputes, the weighted dot product langle (u_1p_1) (u_2p_2)rangle_theta = theta Re langle u_1u_2rangle +(1-theta)p_1p_2 where u_iinmathbb R^N. The Re factor is put to ensure a real valued result despite possible complex valued arguments.\n\ninfo: Info\nThis is used in the pseudo-arclength constraint with the dot product frac1N langle u_1 u_2ranglequad u_iinmathbb R^N\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"continuation","category":"page"},{"location":"library/#BifurcationKit.continuation","page":"Library","title":"BifurcationKit.continuation","text":"continuation(\n prob,\n alg,\n contparams;\n linear_algo,\n bothside,\n kwargs...\n)\n\n\nCompute the continuation curve associated to the functional F which is stored in the bifurcation problem prob. General information is available in Continuation methods: introduction.\n\nArguments:\n\nprob::AbstractBifurcationFunction a ::AbstractBifurcationProblem, typically a BifurcationProblem which holds the vector field and its jacobian. We also refer to BifFunction for more details.\nalg continuation algorithm, for example Natural(), PALC(), Multiple(),.... See algos\ncontparams::ContinuationPar parameters for continuation. See ContinuationPar\n\nOptional Arguments:\n\nplot = false whether to plot the solution/branch/spectrum while computing the branch\nbothside = true compute the branches on the two sides of the initial parameter value p0, merge them and return it.\nfinalise_solution = (z, tau, step, contResult; kwargs...) -> true Function called at the end of each continuation step. Can be used to alter the continuation procedure (stop it by returning false), save personal data, plot... The notations are z = BorderedArray(x p) where x (resp. p) is the current solution (resp. parameter value), tau::BorderedArray is the tangent at z, step::Int is the index of the current continuation step and contResult is the current branch. For advanced use:\nthe current state::ContState of the continuation is passed in kwargs. \nthe switch bisection::Bool is passed whenever finalise_solution is called during bisection for locating bifurcation points / events. This allows to escape some personal code in this case.\n\nNote that you can have a better control over the continuation procedure by using an iterator, see Iterator Interface.\n\nverbosity::Int = 0 controls the amount of information printed during the continuation process. Must belong to {0,1,2,3}. In case contparams.newton_options.verbose = false, the following is valid (otherwise the newton iterations are shown). Each case prints more information than the previous one:\ncase 0: print nothing\ncase 1: print basic information about the continuation: used predictor, step size and parameter values\ncase 2: print newton iterations number, stability of solution, detected bifurcations / events\ncase 3: print information during bisection to locate bifurcations / events\nnormC = norm norm used in the Newton solves\nfilename to save the computed branch during continuation. The identifier .jld2 will be appended to this filename. This requires using JLD2.\ncallback_newton callback for newton iterations. See docs of newton. For example, it can be used to change the preconditioners.\nkind::AbstractContinuationKind [Internal] flag to describe continuation kind (equilibrium, codim 2, ...). Default = EquilibriumCont()\n\nOutput:\n\ncontres::ContResult composite type which contains the computed branch. See ContResult for more information.\n\ntip: Continuing the branch in the opposite direction\nJust change the sign of ds in ContinuationPar.\n\ntip: Debug mode\nUse debug mode to access more irformation about the progression of the continuation run, like iterative solvers convergence, problem update, ...\n\n\n\n\n\ncontinuation(\n prob,\n algdc,\n contParams;\n verbosity,\n plot,\n linear_algo,\n dot_palc,\n callback_newton,\n filename,\n normC,\n kwcont...\n)\n\n\nThis function computes the set of curves of solutions γ(s) = (x(s), p(s)) to the equation F(x,p) = 0 based on the algorithm of deflated continuation as described in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. “The Computation of Disconnected Bifurcation Diagrams.” ArXiv:1603.00809 [Math], March 2, 2016. http://arxiv.org/abs/1603.00809.\n\nDepending on the options in contParams, it can locate the bifurcation points on each branch. Note that you can specify different predictors using alg.\n\nArguments:\n\nprob::AbstractBifurcationProblem bifurcation problem\nalg::DefCont, deflated continuation algorithm, see DefCont\ncontParams parameters for continuation. See ContinuationPar for more information about the options\n\nOptional Arguments:\n\nplot = false whether to plot the solution while computing,\ncallback_newton callback for newton iterations. see docs for newton. Can be used to change preconditioners or affect the newton iterations. In the deflation part of the algorithm, when seeking for new branches, the callback is passed the keyword argument fromDeflatedNewton = true to tell the user can it is not in the continuation part (regular newton) of the algorithm,\nverbosity::Int controls the amount of information printed during the continuation process. Must belong to {0,⋯,5},\nnormC = norm norm used in the Newton solves,\ndot_palc = (x, y) -> dot(x, y) / length(x), dot product used to define the weighted dot product (resp. norm) (x p)^2_theta in the constraint N(x p) (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...),\n\nOutputs:\n\ncontres::DCResult composite type which contains the computed branches. See ContResult for more information,\n\n\n\n\n\ncontinuation(br, ind_bif, lens2; ...)\ncontinuation(\n br,\n ind_bif,\n lens2,\n options_cont;\n prob,\n start_with_eigen,\n detect_codim2_bifurcation,\n kwargs...\n)\n\n\nCodimension 2 continuation of Fold / Hopf points. This function turns an initial guess for a Fold / Hopf point into a curve of Fold / Hopf points based on a Minimally Augmented formulation. The arguments are as follows\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\nlens2 second parameter used for the continuation, the first one is the one used to compute br, e.g. getlens(br)\noptions_cont = br.contparams arguments to be passed to the regular continuation\n\nOptional arguments:\n\nbdlinsolver bordered linear solver for the constraint equation\nupdate_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements\ndetect_codim2_bifurcation ∈ {0,1,2} whether to detect Bogdanov-Takens, Bautin and Cusp. If equals 1 non precise detection is used. If equals 2, a bisection method is used to locate the bifurcations.\nkwargs keywords arguments to be passed to the regular continuation\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br you want to refine.\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\ntip: start_with_eigen\nIt is recommended that you use the option start_with_eigen = true\n\n\n\n\n\ncontinuation(\n prob,\n x0,\n par0,\n x1,\n p1,\n alg,\n lens,\n contParams;\n bothside,\n kwargs...\n)\n\n\n[Internal] This function is not meant to be called directly.\n\nThis function is the analog of continuation when the first two points on the branch are passed (instead of a single one). Hence x0 is the first point on the branch (with palc s=0) with parameter par0 and x1 is the second point with parameter set(par0, lens, p1).\n\n\n\n\n\ncontinuation(br, ind_bif; ...)\ncontinuation(\n br,\n ind_bif,\n options_cont;\n alg,\n δp,\n ampfactor,\n nev,\n usedeflation,\n verbosedeflation,\n max_iter_deflation,\n perturb,\n plot_solution,\n Teigvec,\n scaleζ,\n tol_fold,\n kwargs...\n)\n\n\nAutomatic branch switching at branch points based on a computation of the normal form. More information is provided in Branch switching. An example of use is provided in 2d generalized Bratu–Gelfand problem.\n\nArguments\n\nbr branch result from a call to continuation\nind_bif index of the bifurcation point in br from which you want to branch from\noptions_cont options for the call to continuation\n\nOptional arguments\n\nalg = br.alg continuation algorithm to be used, default value: br.alg\nδp used to specify a specific value for the parameter on the bifurcated branch which is otherwise determined by options_cont.ds. This allows to use a step larger than options_cont.dsmax.\nampfactor = 1 factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\nnev number of eigenvalues to be computed to get the right eigenvector\nusedeflation = false whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated\nverbosedeflation print deflated newton iterations\nmax_iter_deflation number of newton steps in deflated newton\nperturb = identity which perturbation function to use during deflated newton\nTeigvec = getvectortype(br) type of the eigenvector. Useful when br was loaded from a file and this information was lost\nscaleζ = norm pass a norm to normalize vectors during normal form computation\nplot_solution change plot solution method in the problem br.prob\nkwargs optional arguments to be passed to continuation, the regular continuation one and to get_normal_form.\n\ntip: Advanced use\nIn the case of a very large model and use of special hardware (GPU, cluster), we suggest to discouple the computation of the reduced equation, the predictor and the bifurcated branches. Have a look at methods(BifurcationKit.multicontinuation) to see how to call these versions. These methods has been tested on GPU with very high memory pressure.\n\n\n\n\n\ncontinuation(\n probPO,\n orbitguess,\n alg,\n contParams,\n linear_algo;\n δ,\n eigsolver,\n record_from_solution,\n plot_solution,\n kwargs...\n)\n\n\nThis is the continuation method for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to continuation except that probPO is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.\n\nOptional arguments\n\neigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\ncontinuation(\n prob,\n orbitguess,\n alg,\n _contParams;\n linear_algo,\n kwargs...\n)\n\n\nThis is the continuation routine for computing a periodic orbit using a (Standard / Poincaré) Shooting method.\n\nArguments\n\nSimilar to continuation except that prob is either a ShootingProblem or a PoincareShootingProblem. By default, it prints the period of the periodic orbit.\n\nOptional argument\n\nlinear_algo::AbstractBorderedLinearSolver\njacobian Specify the choice of the linear algorithm, which must belong to [AutoDiffMF(), MatrixFree(), AutodiffDense(), AutoDiffDenseAnalytical(), FiniteDifferences(), FiniteDifferencesMF()]. This is used to select a way of inverting the jacobian dG\nFor MatrixFree(), matrix free jacobian, the jacobian is specified by the user in prob. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutoDiffMF(), we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of x -> prob(x, p) using a directional derivative. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system\nFor AutodiffDense(). Same as for AutoDiffMF but the jacobian is formed as a dense Matrix. You can use a direct solver or an iterative one.\nFor FiniteDifferences(), same as for AutoDiffDense but we use Finite Differences to compute the jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\nFor AutoDiffDenseAnalytical(). Same as for AutoDiffDense but the jacobian is formed using a mix of AD and analytical formula.\nFor FiniteDifferencesMF(), use Finite Differences to compute the matrix-free jacobian of x -> prob(x, p) using the δ = 1e-8 which can be passed as an argument.\n\n\n\n\n\ncontinuation(\n br,\n ind_bif,\n _contParams,\n pbPO;\n prob_vf,\n alg,\n δp,\n ampfactor,\n usedeflation,\n nev,\n kwargs...\n)\n\n\nPerform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.\n\nArguments\n\nbr branch result from a call to continuation\nind_hopf index of the bifurcation point in br\ncontParams parameters for the call to continuation\nprobPO problem used to specify the way the periodic orbit is computed. It can be PeriodicOrbitTrapProblem, ShootingProblem or PoincareShootingProblem .\n\nOptional arguments\n\nalg = br.alg continuation algorithm\nδp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.\nampfactor = 1 factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\nusedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch\nnev number of eigenvalues to be computed to get the right eigenvector\nall kwargs from continuation\n\nA modified version of prob is passed to plot_solution and finalise_solution.\n\nnote: Linear solver\nYou have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.\n\n\n\n\n\ncontinuation(\n br,\n ind_bif,\n _contParams;\n alg,\n δp,\n ampfactor,\n usedeflation,\n linear_algo,\n detailed,\n prm,\n kwargs...\n)\n\n\nBranch switching at a bifurcation point on a branch of periodic orbits (PO) specified by a br::AbstractBranchResult. The functional used to compute the PO is br.prob. A deflated Newton-Krylov solver can be used to improve the branch switching capabilities.\n\nArguments\n\nbr branch of periodic orbits computed with a PeriodicOrbitTrapProblem\nind_bif index of the branch point\n_contParams parameters to be used by a regular continuation\n\nOptional arguments\n\nδp = 0.1 used to specify a particular guess for the parameter in the branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.\nampfactor = 1 factor which alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\ndetailed = false whether to fully compute the normal form. The normal form is only used to collect the eigenvector for now.\nusedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch\nrecord_from_solution = (u, p) -> u[end], record method used in the bifurcation diagram, by default this records the period of the periodic orbit.\nlinear_algo = BorderingBLS(), same as for continuation\nkwargs keywords arguments used for a call to the regular continuation and the ones specific to periodic orbits (POs).\n\n\n\n\n\ncontinuation(\n prob,\n orbitguess,\n alg,\n _contParams;\n record_from_solution,\n linear_algo,\n kwargs...\n)\n\n\nThis is the continuation routine for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.\n\nArguments\n\nprob::PeriodicOrbitTrapProblem encodes the functional G\norbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It could be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.\nalg continuation algorithm\ncontParams same as for the regular continuation method\n\nKeyword arguments\n\nlinear_algo same as in continuation\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\nNote that by default, the method prints the period of the periodic orbit as function of the parameter. This can be changed by providing your record_from_solution argument.\n\n\n\n\n\ncontinuation(\n probPO,\n orbitguess,\n alg,\n _contParams,\n linear_algo;\n δ,\n eigsolver,\n record_from_solution,\n plot_solution,\n kwargs...\n)\n\n\nThis is the continuation method for computing a periodic orbit using an orthogonal collocation method.\n\nArguments\n\nSimilar to continuation except that prob is a PeriodicOrbitOCollProblem. By default, it prints the period of the periodic orbit.\n\nKeywords arguments\n\neigsolver specify an eigen solver for the computation of the Floquet exponents, defaults to FloquetQaD\n\n\n\n\n\ncontinuation(\n prob,\n alg,\n contParams;\n linear_algo,\n plot,\n normC,\n finalise_solution,\n callback_newton,\n kind,\n verbosity,\n kwargs...\n)\n\n\nArguments\n\nprob::BifurcationProblem\nalg:: ANM continuation algorithm. See ANM.\ncontParams see BK.ContinuationPar\n\n\n\n\n\n","category":"function"},{"location":"library/#Continuation-algorithms","page":"Library","title":"Continuation algorithms","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"Natural","category":"page"},{"location":"library/#BifurcationKit.Natural","page":"Library","title":"BifurcationKit.Natural","text":"Natural continuation algorithm. The predictor is the constant predictor and the parameter is incremented by `ContinuationPar().ds` at each continuation step.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Secant","category":"page"},{"location":"library/#BifurcationKit.Secant","page":"Library","title":"BifurcationKit.Secant","text":"Secant Tangent predictor\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Bordered","category":"page"},{"location":"library/#BifurcationKit.Bordered","page":"Library","title":"BifurcationKit.Bordered","text":"Bordered Tangent predictor\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Polynomial","category":"page"},{"location":"library/#BifurcationKit.Polynomial","page":"Library","title":"BifurcationKit.Polynomial","text":"Polynomial Tangent predictor\n\nn::Int64: Order of the polynomial\nk::Int64: Length of the last solutions vector used for the polynomial fit\nA::Matrix{T} where T<:Real: Matrix for the interpolation\ntangent::BifurcationKit.AbstractTangentComputation: Algo for tangent when polynomial predictor is not possible\nsolutions::DataStructures.CircularBuffer: Vector of solutions\nparameters::DataStructures.CircularBuffer{T} where T<:Real: Vector of parameters\narclengths::DataStructures.CircularBuffer{T} where T<:Real: Vector of arclengths\ncoeffsSol::Vector: Coefficients for the polynomials for the solution\ncoeffsPar::Vector{T} where T<:Real: Coefficients for the polynomials for the parameter\nupdate::Bool: Update the predictor by adding the last point (x, p)? This can be disabled in order to just use the polynomial prediction. It is useful when the predictor is called mutiple times during bifurcation detection using bisection.\n\nConstructor(s)\n\nPolynomial(pred, n, k, v0)\n\nPolynomial(n, k, v0)\n\nn order of the polynomial\nk length of the last solutions vector used for the polynomial fit\nv0 example of solution to be stored. It is only used to get the eltype of the tangent.\n\nCan be used like\n\nPALC(tangent = Polynomial(Bordered(), 2, 6, rand(1)))\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"Multiple","category":"page"},{"location":"library/#BifurcationKit.Multiple","page":"Library","title":"BifurcationKit.Multiple","text":"Multiple Tangent continuation algorithm.\n\nalg::PALC: Tangent predictor used Default: PALC()\nτ::Any: Save the current tangent\nα::Real: Damping in Newton iterations, 0 < α < 1\nnb::Int64: Number of predictors\ncurrentind::Int64: Index of the largest converged predictor Default: 0\npmimax::Int64: Index for lookup in residual history Default: 1\nimax::Int64: Maximum index for lookup in residual history Default: 4\ndsfact::Real: Factor to increase ds upon successful step Default: 1.5\n\nConstructor(s)\n\nMultiple(alg, x0, α, n)\n\nMultiple(pred, x0, α, n)\n\nMultiple(x0, α, n)\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"PALC","category":"page"},{"location":"library/#BifurcationKit.PALC","page":"Library","title":"BifurcationKit.PALC","text":"struct PALC{Ttang<:BifurcationKit.AbstractTangentComputation, Tbls<:BifurcationKit.AbstractLinearSolver, T, Tdot} <: BifurcationKit.AbstractContinuationAlgorithm\n\nPseudo-arclength continuation algorithm.\n\nAdditional information is available on the website.\n\nFields\n\ntangent::BifurcationKit.AbstractTangentComputation: Tangent predictor, must be a subtype of AbstractTangentComputation. For example Secant() or Bordered(), Default: Secant()\nθ::Any: θ is a parameter in the arclength constraint. It is very important to tune it. It should be tuned for the continuation to work properly especially in the case of large problems where the < x - x0, dx0 > component in the constraint equation might be favoured too much. Also, large thetas favour p as the corresponding term in N involves the term 1-theta. Default: 0.5\n_bothside::Bool: [internal], Default: false\nbls::BifurcationKit.AbstractLinearSolver: Bordered linear solver used to invert the jacobian of the newton bordered problem. It is also used to compute the tangent for the predictor Bordered(), Default: MatrixBLS()\ndoArcLengthScaling::Bool: Unused for now, Default: false\ngGoal::Any: Unused for now, Default: 0.5\ngMax::Any: Unused for now, Default: 0.8\nθMin::Any: Unused for now, Default: 0.001\ndotθ::Any: dotθ = DotTheta(), this sets up a dot product (x, y) -> dot(x, y) / length(x) used to define the weighted dot product (resp. norm) (x p)^2_theta in the constraint N(x p) (see online docs on PALC). This argument can be used to remove the factor 1/length(x) for example in problems where the dimension of the state space changes (mesh adaptation, ...) Default: DotTheta()\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"MoorePenrose","category":"page"},{"location":"library/#BifurcationKit.MoorePenrose","page":"Library","title":"BifurcationKit.MoorePenrose","text":"Moore-Penrose predictor / corrector\n\nMoore-Penrose continuation algorithm.\n\nAdditional information is available on the website.\n\nConstructors\n\nalg = MoorePenrose()\n\nalg = MoorePenrose(tangent = PALC())\n\nFields\n\ntangent::Any: Tangent predictor, example PALC()\nmethod::MoorePenroseLS: Use a direct linear solver. Can be BifurcationKit.direct, BifurcationKit.pInv or BifurcationKit.iterative\nls::BifurcationKit.AbstractLinearSolver: (Bordered) linear solver\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.DefCont","category":"page"},{"location":"library/#BifurcationKit.DefCont","page":"Library","title":"BifurcationKit.DefCont","text":"struct DefCont{Tdo, Talg, Tps, Tas, Tud, Tk} <: BifurcationKit.AbstractContinuationAlgorithm\n\nStructure which holds the parameters specific to Deflated continuation.\n\nFields\n\ndeflation_operator::Any: Deflation operator, ::DeflationOperator Default: nothing\nalg::Any: Used as a predictor, ::AbstractContinuationAlgorithm. For example PALC(), Natural(),... Default: PALC()\nmax_branches::Int64: maximum number of (active) branches to be computed Default: 100\nseek_every_step::Int64: whether to seek new (deflated) solution at every step Default: 1\nmax_iter_defop::Int64: maximum number of deflated Newton iterations Default: 5\nperturb_solution::Any: perturb function Default: _perturbSolution\naccept_solution::Any: accept (solution) function Default: _acceptSolution\nupdate_deflation_op::Any: function to update the deflation operator, ie pushing new solutions Default: _updateDeflationOp\njacobian::Any: jacobian for deflated newton. Can be DeflatedProblemCustomLS(), or Val(:autodiff), Val(:fullIterative) Default: DeflatedProblemCustomLS()\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"AsymptoticNumericalMethod.ANM","category":"page"},{"location":"library/#AsymptoticNumericalMethod.ANM","page":"Library","title":"AsymptoticNumericalMethod.ANM","text":"Continuation algorithm based on Asymptotic Numerical Method. It can be used from the package https://github.com/bifurcationkit/AsymptoticNumericalMethod.jl\n\nFields\n\norder::Int64: order of the polynomial approximation\ntol::Any: tolerance which is used to estimate the neighbourhood on which the polynomial approximation is valid\n\nReferences\n\nCharpentier, Isabelle, Bruno Cochelin, and Komlanvi Lampoh. “Diamanlab - An Interactive Taylor-Based Continuation Tool in MATLAB,” n.d., 12.\nRubbert, Lennart, Isabelle Charpentier, Simon Henein, and Pierre Renaud. “Higher-Order Continuation Method for the Rigid-Body Kinematic Design of Compliant Mechanisms”, n.d., 18.\n\n\n\n\n\n","category":"type"},{"location":"library/#Events","page":"Library","title":"Events","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.DiscreteEvent","category":"page"},{"location":"library/#BifurcationKit.DiscreteEvent","page":"Library","title":"BifurcationKit.DiscreteEvent","text":"struct DiscreteEvent{Tcb, Tl} <: BifurcationKit.AbstractDiscreteEvent\n\nStructure to pass a DiscreteEvent function to the continuation algorithm. A discrete call back returns a discrete value and we seek when it changes.\n\nnb::Int64: number of events, ie the length of the result returned by the callback function\ncondition::Any: = (iter, state) -> NTuple{nb, Int64} callback function which at each continuation state, returns a tuple. For example, to detect a value change.\ncomputeEigenElements::Bool: whether the event requires to compute eigen elements\nlabels::Any: Labels used to display information. For example labels[1] is used to qualify an event occurring in the first component. You can use labels = (\"hopf\",) or labels = (\"hopf\", \"fold\"). You must have labels::Union{Nothing, NTuple{N, String}}.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.ContinuousEvent","category":"page"},{"location":"library/#BifurcationKit.ContinuousEvent","page":"Library","title":"BifurcationKit.ContinuousEvent","text":"struct ContinuousEvent{Tcb, Tl, T} <: BifurcationKit.AbstractContinuousEvent\n\nStructure to pass a ContinuousEvent function to the continuation algorithm. A continuous call back returns a tuple/scalar value and we seek its zeros.\n\nnb::Int64: number of events, ie the length of the result returned by the callback function\ncondition::Any: , (iter, state) -> NTuple{nb, T} callback function which, at each continuation state, returns a tuple. For example, to detect crossing 1.0 and -2.0, you can pass (iter, state) -> (getp(state)+2, getx(state)[1]-1)),. Note that the type T should match the one of the parameter specified by the ::Lens in continuation.\ncomputeEigenElements::Bool: whether the event requires to compute eigen elements\nlabels::Any: Labels used to display information. For example labels[1] is used to qualify an event of the type (0, 1.3213, 3.434). You can use labels = (\"hopf\",) or labels = (\"hopf\", \"fold\"). You must have labels::Union{Nothing, NTuple{N, String}}.\ntol::Any: Tolerance on event value to declare it as true event.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.SetOfEvents","category":"page"},{"location":"library/#BifurcationKit.SetOfEvents","page":"Library","title":"BifurcationKit.SetOfEvents","text":"struct SetOfEvents{Tc<:Tuple, Td<:Tuple} <: BifurcationKit.AbstractEvent\n\nMultiple events can be chained together to form a SetOfEvents. A SetOfEvents is constructed by passing to the constructor ContinuousEvent, DiscreteEvent or other SetOfEvents instances:\n\nSetOfEvents(cb1, cb2, cb3)\n\nExample\n\n BifurcationKit.SetOfEvents(BK.FoldDetectCB, BK.BifDetectCB)\n\nYou can pass as many events as you like.\n\neventC::Tuple: Continuous event\neventD::Tuple: Discrete event\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.PairOfEvents","category":"page"},{"location":"library/#BifurcationKit.PairOfEvents","page":"Library","title":"BifurcationKit.PairOfEvents","text":"struct PairOfEvents{Tc<:BifurcationKit.AbstractContinuousEvent, Td<:BifurcationKit.AbstractDiscreteEvent} <: BifurcationKit.AbstractEvent\n\nStructure to pass a PairOfEvents function to the continuation algorithm. It is composed of a pair ContinuousEvent / DiscreteEvent. A PairOfEvents is constructed by passing to the constructor a ContinuousEvent and a DiscreteEvent:\n\nPairOfEvents(contEvent, discreteEvent)\n\nFields\n\neventC::BifurcationKit.AbstractContinuousEvent: Continuous event\neventD::BifurcationKit.AbstractDiscreteEvent: Discrete event\n\n\n\n\n\n","category":"type"},{"location":"library/#Branch-switching-(branch-point)","page":"Library","title":"Branch switching (branch point)","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar ; kwargs...)","category":"page"},{"location":"library/#Branch-switching-(Hopf-point)","page":"Library","title":"Branch switching (Hopf point)","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int, _contParams::ContinuationPar, prob::BifurcationKit.AbstractPeriodicOrbitProblem ; kwargs...)","category":"page"},{"location":"library/#BifurcationKit.continuation-Tuple{BifurcationKit.AbstractBranchResult, Int64, ContinuationPar, BifurcationKit.AbstractPeriodicOrbitProblem}","page":"Library","title":"BifurcationKit.continuation","text":"continuation(\n br,\n ind_bif,\n _contParams,\n pbPO;\n prob_vf,\n alg,\n δp,\n ampfactor,\n usedeflation,\n nev,\n kwargs...\n)\n\n\nPerform automatic branch switching from a Hopf bifurcation point labelled ind_bif in the list of the bifurcated points of a previously computed branch br::ContResult. It first computes a Hopf normal form.\n\nArguments\n\nbr branch result from a call to continuation\nind_hopf index of the bifurcation point in br\ncontParams parameters for the call to continuation\nprobPO problem used to specify the way the periodic orbit is computed. It can be PeriodicOrbitTrapProblem, ShootingProblem or PoincareShootingProblem .\n\nOptional arguments\n\nalg = br.alg continuation algorithm\nδp used to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined by contParams.ds. This allows to use a step larger than contParams.dsmax.\nampfactor = 1 factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.\nusedeflation = true whether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branch\nnev number of eigenvalues to be computed to get the right eigenvector\nall kwargs from continuation\n\nA modified version of prob is passed to plot_solution and finalise_solution.\n\nnote: Linear solver\nYou have to be careful about the options contParams.newton_options.linsolver. In the case of Matrix-Free solver, you have to pass the right number of unknowns N * M + 1. Note that the options for the preconditioner are not accessible yet.\n\n\n\n\n\n","category":"method"},{"location":"library/#Bifurcation-diagram","page":"Library","title":"Bifurcation diagram","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"bifurcationdiagram","category":"page"},{"location":"library/#BifurcationKit.bifurcationdiagram","page":"Library","title":"BifurcationKit.bifurcationdiagram","text":"bifurcationdiagram(prob, alg, level, options; kwargs...)\n\n\nCompute the bifurcation diagram associated with the problem F(x, p) = 0 recursively.\n\nArguments\n\nprob::AbstractBifurcationProblem bifurcation problem\nalg continuation algorithm\nlevel maximum branching (or recursion) level for computing the bifurcation diagram\noptions = (x, p, level) -> contparams this function allows to change the continuation options depending on the branching level. The argument x, p denotes the current solution to F(x, p)=0.\nkwargs optional arguments. Look at bifurcationdiagram! for more details.\n\nSimplified call:\n\nWe also provide the method\n\nbifurcationdiagram(prob, br::ContResult, level::Int, options; kwargs...)\n\nwhere br is a branch computed after a call to continuation from which we want to compute the bifurcating branches recursively.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"bifurcationdiagram!","category":"page"},{"location":"library/#BifurcationKit.bifurcationdiagram!","page":"Library","title":"BifurcationKit.bifurcationdiagram!","text":"bifurcationdiagram!(\n prob,\n node,\n maxlevel,\n options;\n code,\n usedeflation,\n halfbranch,\n verbosediagram,\n kwargs...\n)\n\n\nSimilar to bifurcationdiagram but you pass a previously computed node from which you want to further compute the bifurcated branches. It is usually used with node = get_branch(diagram, code) from a previously computed bifurcation diagram.\n\nArguments\n\nnode::BifDiagNode a node in the bifurcation diagram\nmaxlevel = 1 required maximal level of recursion.\noptions = (x, p, level) -> contparams this function allows to change the continuation options depending on the branching level. The argument x, p denotes the current solution to F(x, p)=0.\n\nOptional arguments\n\ncode = \"0\" code used to display iterations\nusedeflation = false\nhalfbranch = false for Pitchfork / Transcritical bifurcations, compute only half of the branch. Can be useful when there are symmetries.\nverbosediagram verbose specific to bifurcation diagram. Print information about the branches as they are being computed.\nkwargs optional arguments as for continuation but also for the different versions listed in Continuation.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"get_branch","category":"page"},{"location":"library/#BifurcationKit.get_branch","page":"Library","title":"BifurcationKit.get_branch","text":"get_branch(tree, code)\n\n\nReturn the part of the tree (bifurcation diagram) by recursively descending down the tree using the Int valued tuple code. For example get_branch(tree, (1,2,3,)) returns tree.child[1].child[2].child[3].\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"get_branches_from_BP","category":"page"},{"location":"library/#BifurcationKit.get_branches_from_BP","page":"Library","title":"BifurcationKit.get_branches_from_BP","text":"get_branches_from_BP(tree, indbif)\n\n\nReturn the part of the tree corresponding to the indbif-th bifurcation point on the root branch.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"BifurcationKit.SpecialPoint","category":"page"},{"location":"library/#BifurcationKit.SpecialPoint","page":"Library","title":"BifurcationKit.SpecialPoint","text":"struct SpecialPoint{T, Tp, Tv, Tvτ} <: BifurcationKit.AbstractBifurcationPoint\n\nStructure to record special points on a curve. There are two types of special points that are recorded in this structure: bifurcation points and events (see https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/EventCallback/).\n\ntype::Symbol: Description of the special points. In case of Events, this field records the user passed named to the event, or the default :userD, :userC. In case of bifurcation points, it can be one of the following:\n- :bp Bifurcation point, simple eigenvalue crossing the imaginary axis\n- :fold Fold point\n- :hopf Hopf point\n- :nd not documented bifurcation point. Detected by multiple eigenvalues crossing. Generally occurs in problems with symmetries or in cases where the continuation step size is too large and merge two different bifurcation points.\n- :cusp Cusp point\n- :gh Generalized Hopf point (also called Bautin point)\n- :bt Bogdanov-Takens point\n- :zh Zero-Hopf point\n- :hh Hopf-Hopf point\n- :ns Neimark-Sacker point\n- :pd Period-doubling point\n- :R1 Strong resonance 1:1 of periodic orbits\n- :R2 Strong resonance 1:2 of periodic orbits\n- :R3 Strong resonance 1:3 of periodic orbits\n- :R4 Strong resonance 1:4 of periodic orbits\n- :foldFlip Fold / Flip of periodic orbits\n- :foldNS Fold / Neimark-Sacker of periodic orbits\n- :pdNS Period-Doubling / Neimark-Sacker of periodic orbits\n- :gpd Generalized Period-Doubling of periodic orbits\n- :nsns Double Neimark-Sacker of periodic orbits\n- :ch Chenciner bifurcation of periodic orbits\n Default: :none\nidx::Int64: Index in br.branch or br.eig (see ContResult) for which the bifurcation occurs. Default: 0\nparam::Any: Parameter value at the special point (this is an estimate). Default: 0.0\nnorm::Any: Norm of the equilibrium at the special point Default: 0.0\nprintsol::Any: printsol = record_from_solution(x, param) where record_from_solution is one of the arguments to continuation Default: 0.0\nx::Any: Equilibrium at the special point Default: Vector{T}(undef, 0)\nτ::BorderedArray{Tvτ, T} where {T, Tvτ}: Tangent along the branch at the special point Default: BorderedArray(x, T(0))\nind_ev::Int64: Eigenvalue index responsible for detecting the special point (if applicable) Default: 0\nstep::Int64: Continuation step at which the special occurs Default: 0\nstatus::Symbol: status ∈ {:converged, :guess, :guessL} indicates whether the bisection algorithm was successful in detecting the special (bifurcation) point. If status == :guess, the bissection algorithm failed to meet the requirements given in ::ContinuationPar. Same for status == :guessL but the bissection algorithm stopped on the left of the bifurcation point. Default: :guess\nδ::Tuple{Int64, Int64}: δ = (δr, δi) where δr indicates the change in the number of unstable eigenvalues and δi indicates the change in the number of unstable eigenvalues with nonzero imaginary part. abs(δr) is thus an estimate of the dimension of the kernel of the Jacobian at the special (bifurcation) point. Default: (0, 0)\nprecision::Any: Precision in the location of the special point Default: -1\ninterval::Tuple{T, T} where T: Interval parameter containing the special point Default: (0, 0)\n\n\n\n\n\n","category":"type"},{"location":"library/#Utils-for-periodic-orbits","page":"Library","title":"Utils for periodic orbits","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"getperiod","category":"page"},{"location":"library/#BifurcationKit.getperiod","page":"Library","title":"BifurcationKit.getperiod","text":"getperiod(, x)\ngetperiod(, x, par)\n\n\nCompute the period of the periodic orbit associated to x.\n\n\n\n\n\ngetperiod(prob, x, p)\n\n\nCompute the period of the periodic orbit associated to x.\n\n\n\n\n\ngetperiod(psh, x_bar, par)\n\n\nCompute the period of the periodic orbit associated to x_bar.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"getamplitude","category":"page"},{"location":"library/#BifurcationKit.getamplitude","page":"Library","title":"BifurcationKit.getamplitude","text":"getamplitude(prob, x, p; ratio)\n\n\nCompute the amplitude of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = 1 + ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\ngetamplitude(prob, x, p; ratio)\n\n\nCompute the amplitude of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"getmaximum","category":"page"},{"location":"library/#BifurcationKit.getmaximum","page":"Library","title":"BifurcationKit.getmaximum","text":"getmaximum(prob, x, p; ratio)\n\n\nCompute the maximum of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = 1 + ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\ngetmaximum(prob, x, p)\n\n\nCompute the maximum of the periodic orbit associated to x.\n\n\n\n\n\ngetmaximum(prob, x, p; ratio)\n\n\nCompute the maximum of the periodic orbit associated to x. The keyword argument ratio = 1 is used as follows. If length(x) = ratio * n, the call returns the amplitude over x[1:n].\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"SectionSS","category":"page"},{"location":"library/#BifurcationKit.SectionSS","page":"Library","title":"BifurcationKit.SectionSS","text":"struct SectionSS{Tn, Tc} <: BifurcationKit.AbstractSection\n\nThis composite type (named for Section Standard Shooting) encodes a type of section implemented by a single hyperplane. It can be used in conjunction with ShootingProblem. The hyperplane is defined by a point center and a normal.\n\nnormal::Any: Normal to define hyperplane\ncenter::Any: Representative point on hyperplane\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"SectionPS","category":"page"},{"location":"library/#BifurcationKit.SectionPS","page":"Library","title":"BifurcationKit.SectionPS","text":"struct SectionPS{Tn, Tc, Tnb, Tcb, Tr} <: BifurcationKit.AbstractSection\n\nThis composite type (named for SectionPoincaréShooting) encodes a type of Poincaré sections implemented by hyperplanes. It can be used in conjunction with PoincareShootingProblem. Each hyperplane is defined par a point (one example in centers) and a normal (one example in normals).\n\nM::Int64\nnormals::Any\ncenters::Any\nindices::Vector{Int64}\nnormals_bar::Any\ncenters_bar::Any\nradius::Any\n\nConstructor(s)\n\nSectionPS(normals::Vector{Tv}, centers::Vector{Tv})\n\n\n\n\n\n","category":"type"},{"location":"library/#Misc.","page":"Library","title":"Misc.","text":"","category":"section"},{"location":"library/","page":"Library","title":"Library","text":"PrecPartialSchurKrylovKit","category":"page"},{"location":"library/#BifurcationKit.PrecPartialSchurKrylovKit","page":"Library","title":"BifurcationKit.PrecPartialSchurKrylovKit","text":"PrecPartialSchurKrylovKit(J, x0, nev, which = :LM; krylovdim = max(2nev, 20), verbosity = 0)\n\nBuilds a preconditioner based on deflation of nev eigenvalues chosen according to which. A partial Schur decomposition is computed (Matrix-Free), using the package KrylovKit.jl, from which a projection is built. The options are similar to the ones of EigKrylovKit().\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"PrecPartialSchurArnoldiMethod","category":"page"},{"location":"library/#BifurcationKit.PrecPartialSchurArnoldiMethod","page":"Library","title":"BifurcationKit.PrecPartialSchurArnoldiMethod","text":"PrecPartialSchurArnoldiMethod(J, N, nev, which = LM(); tol = 1e-9, kwargs...)\n\nBuilds a preconditioner based on deflation of nev eigenvalues chosen according to which. A partial Schur decomposition is computed (Matrix-Free), using the package ArnoldiMethod.jl, from which a projection is built. See the package ArnoldiMethod.jl for how to pass the proper options.\n\n\n\n\n\n","category":"function"},{"location":"library/","page":"Library","title":"Library","text":"Flow","category":"page"},{"location":"library/#BifurcationKit.Flow","page":"Library","title":"BifurcationKit.Flow","text":"struct Flow{TF, Tf, Tts, Tff, Td, Tad, Tse, Tprob, TprobMono, Tfs, Tcb, Tδ} <: BifurcationKit.AbstractFlow\n\nF::Any: The vector field (x, p) -> F(x, p) associated to a Cauchy problem. Used for the differential of the shooting problem. Default: nothing\nflow::Any: The flow (or semigroup) (x, p, t) -> flow(x, p, t) associated to the Cauchy problem. Only the last time point must be returned in the form (u = ...) Default: nothing\nflowTimeSol::Any: Flow which returns the tuple (t, u(t)). Optional, mainly used for plotting on the user side. Default: nothing\nflowFull::Any: [Optional] The flow (or semigroup) associated to the Cauchy problem (x, p, t) -> flow(x, p, t). The whole solution on the time interval [0,t] must be returned. It is not strictly necessary to provide this, it is mainly used for plotting on the user side. Please use nothing as default. Default: nothing\njvp::Any: The differential dflow of the flow w.r.t. x, (x, p, dx, t) -> dflow(x, p, dx, t). One important thing is that we require dflow(x, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = dflow(x, p, dx, t)), the last component being the value of the derivative of the flow. Default: nothing\nvjp::Any: The adjoint differential vjpflow of the flow w.r.t. x, (x, p, dx, t) -> vjpflow(x, p, dx, t). One important thing is that we require vjpflow(x, p, dx, t) to return a Named Tuple: (t = t, u = flow(x, p, t), du = vjpflow(x, p, dx, t)), the last component being the value of the derivative of the flow. Default: nothing\njvpSerial::Any: [Optional] Serial version of dflow. Used internally when using parallel multiple shooting. Please use nothing as default. Default: nothing\nprob::Any: [Internal] store the ODEProblem associated to the flow of the Cauchy problem Default: nothing\nprobMono::Any: [Internal] store the ODEProblem associated to the flow of the variational problem Default: nothing\nflowSerial::Any: [Internal] Serial version of the flow Default: nothing\ncallback::Any: [Internal] Store possible callback Default: nothing\ndelta::Any: [Internal] Default: 1.0e-8\n\nSimplified constructor(s)\n\nWe provide a simple constructor where you only pass the vector field F, the flow ϕ and its differential dϕ:\n\nfl = Flow(F, ϕ, dϕ)\n\nSimplified constructors for DifferentialEquations.jl\n\nThese are some simple constructors for which you only have to pass a prob::ODEProblem or prob::EnsembleProblem (for parallel computation) from DifferentialEquations.jl and an ODE time stepper like Tsit5(). Hence, you can do for example\n\nfl = Flow(prob, Tsit5(); kwargs...)\n\nwhere kwargs is passed to SciMLBase::solve. If your vector field depends on parameters p, you can define a Flow using\n\nfl = Flow(prob, Tsit5(); kwargs...)\n\nFinally, you can pass two ODEProblem where the second one is used to compute the variational equation:\n\nfl = Flow(prob1::ODEProblem, alg1, prob2::ODEProblem, alg2; kwargs...)\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"FloquetQaD","category":"page"},{"location":"library/#BifurcationKit.FloquetQaD","page":"Library","title":"BifurcationKit.FloquetQaD","text":"floquet = FloquetQaD(eigsolver::AbstractEigenSolver)\n\nThis composite type implements the computation of the eigenvalues of the monodromy matrix in the case of periodic orbits problems (based on the Shooting method or Finite Differences (Trapeze method)), also called the Floquet multipliers. The method, dubbed Quick and Dirty (QaD), is not numerically very precise for large / small Floquet exponents when the number of time sections is large because of many matrix products. It allows, nevertheless, to detect bifurcations. The arguments are as follows:\n\neigsolver::AbstractEigenSolver solver used to compute the eigenvalues.\n\nIf eigsolver == DefaultEig(), then the monodromy matrix is formed and its eigenvalues are computed. Otherwise, a Matrix-Free version of the monodromy is used.\n\ndanger: Floquet multipliers computation\nThe computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver eigsolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of eigsolver. Nevertheless, note that for most implemented eigensolvers in the current Package, the proper option is set.\n\n\n\n\n\n","category":"type"},{"location":"library/","page":"Library","title":"Library","text":"guess_from_hopf(br, ind_hopf, eigsolver::AbstractEigenSolver, M, amplitude; phase = 0)","category":"page"},{"location":"library/#BifurcationKit.guess_from_hopf-Tuple{Any, Any, AbstractEigenSolver, Any, Any}","page":"Library","title":"BifurcationKit.guess_from_hopf","text":"guess_from_hopf(\n br,\n ind_hopf,\n eigsolver,\n M,\n amplitude;\n phase\n)\n\n\nThis function returns several useful quantities regarding a Hopf bifurcation point. More precisely, it returns:\n\nthe parameter value at which a Hopf bifurcation occurs\nthe period of the bifurcated periodic orbit\na guess for the bifurcated periodic orbit\nthe equilibrium at the Hopf bifurcation point\nthe eigenvector at the Hopf bifurcation point.\n\nThe arguments are\n\nbr: the continuation branch which lists the Hopf bifurcation points\nind_hopf: index of the bifurcation branch, as in br.specialpoint\neigsolver: the eigen solver used to find the eigenvectors\nM number of time slices in the periodic orbit guess\namplitude: amplitude of the periodic orbit guess\n\n\n\n\n\n","category":"method"},{"location":"library/","page":"Library","title":"Library","text":"get_normal_form","category":"page"},{"location":"library/#BifurcationKit.get_normal_form","page":"Library","title":"BifurcationKit.get_normal_form","text":"get_normal_form(\n prob,\n br,\n id_bif;\n nev,\n verbose,\n ζs,\n ζs_ad,\n lens,\n Teigvec,\n scaleζ,\n detailed,\n autodiff,\n bls,\n bls_adjoint,\n bls_block\n)\n\n\nCompute the normal form of the bifurcation point located at br.specialpoint[ind_bif].\n\nArguments\n\nprob::AbstractBifurcationProblem\nbr result from a call to continuation\nind_bif index of the bifurcation point in br.specialpoint\n\nOptional arguments\n\nnev number of eigenvalues used to compute the spectral projection. This number has to be adjusted when used with iterative methods.\nverbose whether to display information\nζs list of vectors spanning the kernel of dF at the bifurcation point. Useful to enforce the basis for the normal form.\nlens::Lens specify which parameter to take the partial derivative ∂pF\nscaleζ function to normalise the kernel basis. Indeed, when used with large vectors and norm, it results in ζs and the normal form coefficient being super small.\nautodiff = true whether to use ForwardDiff for the differentiations w.r.t the parameters that are required to compute the normal form. Used for example for Bogdanov-Takens point. You can set to autodiff = false if you wish.\ndetailed = true whether to compute only a simplified normal form. Used for example for Bogdanov-Takens point.\nbls = MatrixBLS() specify Bordered linear solver. Used for example for Bogdanov-Takens point.\n\nAvailable method\n\nYou can directly call \n\nget_normal_form(br, ind_bif ; kwargs...)\n\nwhich is a shortcut for get_normal_form(getProb(br), br, ind_bif ; kwargs...).\n\nOnce the normal form nf has been computed, you can call predictor(nf, δp) to obtain an estimate of the bifurcating branch.\n\n\n\n\n\nget_normal_form(\n prob,\n br,\n id_bif;\n nev,\n verbose,\n ζs,\n lens,\n Teigvec,\n scaleζ,\n prm,\n δ,\n detailed\n)\n\n\nCompute the normal form of periodic orbits. Same arguments as the function get_normal_form for equilibria. We detail the additional keyword arguments specific to periodic orbits\n\nOptional arguments\n\nprm = true compute the normal form using Poincaré return map. For collocation, there will be another way to compute the normal form in the future.\n\n\n\n\n\n","category":"function"},{"location":"newton/#Krylov-Newton-algorithm","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"BifurcationKit is built upon the newton algorithm for solving (large-dimensional) nonlinear equations ","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"F(x)=0inmathbb R^nquad xinmathbb R^n","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Writing J(x)inmathcal L(mathbb R^n) the jacobian, the algorithm reads","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"x_n+1 = x_n - J(x_n)^-1F(x_n)","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"with initial guess x_0.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"The crux of the algorithm is to solve the linear system in y:","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"J(x_n)cdot y = F(x_n)","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"To this end, we never form J^-1 like with pinv(J) but solve the linear system directly. ","category":"page"},{"location":"newton/#Space-of-solutions","page":"Krylov-Newton algorithm","title":"Space of solutions","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"For the algorithm to be defined, a certain number of operations on x need to be available. If you pass x::AbstractArray, you should not have any problem. Otherwise, your x must comply with the requirements listed in Requested methods for Custom State.","category":"page"},{"location":"newton/#Different-Jacobians","page":"Krylov-Newton algorithm","title":"Different Jacobians","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"There are basically two ways to specify the jacobian:","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Matrix based\nMatrix-free.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"In case you pass a matrix (in effect an AbstractMatrix like a sparse one,...), you can use the default linear solver from LinearAlgebra termed the backslash operator \\. This is a direct method. This is the case 1 above.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Another possibility is to pass a function J(dx) and to use iterative linear solvers. In this case, this is termed a Krylov-Newton method. This is the case 2 above. In comparison to the Matrix-based case, there is no restriction to the number of unknowns n.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"The available linear solvers are explained in the section Linear solvers (LS).","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"One can find a full description of the Krylov-Newton method in the API. ","category":"page"},{"location":"newton/#Simple-example","page":"Krylov-Newton algorithm","title":"Simple example","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"Here is a quick example to show how the basics work. In particular, the problem generates a matrix based jacobian using automatic differentiation.","category":"page"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"using BifurcationKit\nF(x, p) = x.^3 .- 1\nx0 = rand(10)\nprob = BifurcationProblem(F, x0, nothing)\nsol = newton(prob, NewtonPar(verbose = true))","category":"page"},{"location":"newton/#Example","page":"Krylov-Newton algorithm","title":"Example","text":"","category":"section"},{"location":"newton/","page":"Krylov-Newton algorithm","title":"Krylov-Newton algorithm","text":"The (basic) tutorial Temperature model presents all cases (direct and iterative ones).","category":"page"},{"location":"tutorials/Langmuir/#langmuir","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"In this tutorial, we try to replicate some of the results of the amazing paper [Köpf]. This example is quite a marvel in the realm of bifurcation analysis, featuring a harp-like bifurcation diagram. The equations of the thin film are as follows:","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"partial_t c=-partial_x^2leftpartial_x^2 c-c^3+c-mu zeta(x)right-V partial_x c","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"with boundary conditions","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"c(0)=c_0 quad partial_x x c(0)=partial_x c(L)=partial_x x c(L)=0","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"and where","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"zeta(x)=-frac12left1+tanh left(fracx-x_sl_sright)right","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"As can be seen in the reference above, the bifurcation diagram is significantly more involved as L increases. So we set up for the \"simple\" case L=50.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"using Revise\nusing Parameters, Setfield, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, ForwardDiff\nconst BK = BifurcationKit\n\n# norms\nnormL2(x; r = sqrt(par.Δx / L)) = norm(x, 2) * r\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"Let us define the parameters of the model","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# domain size\nL = 50.0\n\n# number of unknowns\nN = 390*3/2 |> Int\nΔx = L/(N+1)\nX = ((1:N) |> collect) .* Δx\n\n# define the (laplacian of) g function\nxs = 10.0; ls = 2.0\nΔg = @. tanh((X - xs)/ls) * (1 - tanh((X - xs)/ls)^2)/ls^2\n\n# define the parameters of the model\npar = (N = N, Δx = Δx, c0 = -0.9, σ = 1.0, μ = 0.5, ν = 0.08, Δg = Δg)\n\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/#Encoding-the-PDE","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Encoding the PDE","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# function to enforce the boundary condition\nfunction putBC!(c, c0, N)\n\t# we put boundary conditions using ghost points\n\t# this boundary condition u''(0) = 0 = c1 -2c0 + c-1 gives c-1:\n\tc[1] = 2c0-c[3]\n\t# c(0) = c0, we would like to write x[0]\n\tc[2] = c0\n\t# the boundary conditions u'(L) = u''(L) = 0 imply the ghost points values.\n\t# c'(L) = 0 = cN+2 - cN and c''(L) = 0 = cN+2 -2cN+1 + cN\n\tc[N+3] = c[N+2]\n\tc[N+4] = c[N+2]\n\treturn c\nend\n\n# implementation of the right hand side of the PDE\nfunction Flgvf!(out, x, p, t = 0.)\n\t@unpack c0, N, Δx, σ, μ, Δg, ν = p\n\tdx4 = Δx^4\n\tdx2 = Δx^2\n\t# we declare the residual\n\t# we enforce the BC\n\tc = similar(x, length(x) + 4)\n\tc[3:N+2] .= x\n\tputBC!(c, c0, N)\n\n\tfor i=3:N+2\n\t\tout[i-2] = -(σ * (c[i-2] - 4c[i-1] + 6c[i] - 4c[i+1] + c[i+2]) / dx4 +\n\t\t\t\t\t(c[i-1] - 2c[i] + c[i+1]) / (dx2) -\n\t\t\t\t\t(c[i-1]^3 - 2c[i]^3 + c[i+1]^3) / (dx2) -\n\t\t\t\t\tΔg[i-2] * μ +\n\t\t\t\t\tν * (c[i+1] - c[i-1]) / (2Δx)\n\t\t\t\t\t)\n\tend\n\treturn out\nend\nFlgvf(x, p, t = 0) = Flgvf!(similar(x), x, p, t)\n\n# compute the jacobian of the PDE at position x\n@views function JanaSP(x, p)\n\t# 63.446 μs (61 allocations: 137.97 KiB) pour N = 400\n\t# 62.807 μs (44 allocations: 168.58 KiB) pour sparse(Jana(x, p))\n\t@unpack N, Δx, σ, ν = p\n\td0 = @. (-6σ/ Δx^4 + 2/ Δx^2*(1-3x^2))\n\td0[1] += σ/ Δx^4\n\td0[end] = -(3σ/ Δx^4 - 1/ Δx^2*(1-3x[N]^2) + ν/ (2Δx))\n\td1 = @. (4σ/ Δx^4 - 1/ Δx^2*(1-3x[2:N]^2) - ν/ (2Δx))\n\tdm1 = @. (4σ/ Δx^4 - 1/ Δx^2*(1-3x[1:N-1]^2) + ν/ (2Δx))\n\td1[end] -= σ/ Δx^4\n\td2 = @. (-σ/ Δx^4) * ones(N-2)\n\tJ = spdiagm( 0 => d0,\n\t\t\t\t 1 => d1,\n\t\t\t\t -1 => dm1,\n\t\t\t\t 2 => d2,\n\t\t\t\t -2 => d2)\n\treturn J\nend\n\n# we thus define a bifurcation problem\nprob = BifurcationProblem(Flgvf, 0X .-0.9, par, (@lens _.ν );\n\t\tJ = JanaSP,\n\t\trecord_from_solution = (x, p) -> normL2(x),\n\t\tplot_solution = (x, p; kwargs...) -> plot!(X, x, subplot = 3, xlabel = \"Nx = $(length(x))\", label = \"\"))\n\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/#Continuation-of-stationary-states","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Continuation of stationary states","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We call the Krylov-Newton method to find a stationary solution. Note that for this to work, the guess has to satisfy the boundary conditions approximately.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# newton iterations to refine the guess\nopt_new = NewtonPar(tol = 1e-9, verbose = true, max_iterations = 10)\nout = newton(prob, opt_new)\nnothing #hide","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"scene = plot(X, out.u)","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We then continue the previous guess and find this very nice folded structure with many Hopf bifurcation points.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# careful here, in order to use Arpack.eig, you need rather big space\n# or compute ~100 eigenvalues\nopts_cont = ContinuationPar(\n\tp_min = -0.01, p_max = 10.1,\n\tdsmin = 1e-5, dsmax = 0.04, ds= -0.001,\n\ta = 0.75, max_steps = 600,\n\tnewton_options = setproperties(opt_new; verbose = false),\n\tnev = 10, save_eigenvectors = true, tol_stability = 1e-5, detect_bifurcation = 3,\n\tdsmin_bisection = 1e-8, max_bisection_steps = 15, n_inversion = 6, tol_bisection_eigenvalue = 1e-9, save_sol_every_step = 50)\n\n# we opt for a fast Shift-Invert eigen solver\n@set! opts_cont.newton_options.eigsolver = EigArpack(0.1, :LM)\n\nbr = @time continuation(\n\tre_make(prob, params = (@set par.ν = 0.06), u0 = out.u),\n\t# we form a sparse matrix for the bordered linear problem\n\t# and we adjust θ so that the continuation steps are larger\n\tPALC(θ = 0.4, bls = MatrixBLS()), opts_cont,\n\tplot = true, verbosity = 2,\n\tnormC = normL2)\n\nscene = plot(br, title=\"N=$N\")\t\t","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"plot(layout = grid(4, 3))\nfor (ii, s) in pairs(br.sol)\n\tplot!(X, s.x, xlabel = \"ν = $(round(s.p,digits=3))\", subplot = ii, label=\"\",tickfont = (7, :black), ylims=(-1,1.5))\nend\ntitle!(\"\")","category":"page"},{"location":"tutorials/Langmuir/#Continuation-of-Hopf-and-Fold-points","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Continuation of Hopf and Fold points","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"Let us study the continuation of Hopf and Fold points and show that they merge at a Bogdanov-Takens bifurcation point:","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# compute branch of Fold points from 7th bifurcation point on br\nsn_codim2 = continuation(br, 7, (@lens _.Δx),\n\tContinuationPar(opts_cont, p_min = -2, p_max = 0.12, ds = -0.01, dsmax = 0.01, tol_stability = 1e-8, max_steps = 325, nev=23) ;\n\t# start the problem with information from eigen elements\n\tstart_with_eigen = true,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we update the Fold problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# compute both sides of the initial condition\n\tbothside = true,\n\t# we invert the Fold linear problem using Min. Aug.\n\tjacobian_ma = :minaug,\n\t)\n\n# compute branch of Hopf points from 5th bifurcation point on br\nhp_codim2 = continuation(br, 5, (@lens _.Δx), ContinuationPar(opts_cont, p_max = 0.1, ds = -0.01, dsmax = 0.01, max_steps = 230, tol_stability = 1e-8) ;\n\t# start the problem with information from eigen elements\n\tstart_with_eigen = true,\n\t# we update the Hopf problem at every continuation step\n\tupdate_minaug_every_step = 1,\n\t# detection of codim 2 bifurcations with bisection\n\tdetect_codim2_bifurcation = 2,\n\t# we invert the Hopf linear problem using Min. Aug.\n\tjacobian_ma = :minaug,\n\t)\n\n# plot the branches\nplot(sn_codim2, vars = (:Δx, :ν), branchlabel = \"Fold\")\n\nplot!(hp_codim2, vars = (:Δx, :ν), branchlabel = \"Hopf\", plotcirclesbif=true, legend = :bottomright, color = :green)","category":"page"},{"location":"tutorials/Langmuir/#Continuation-of-periodic-orbits-(FD)","page":"🟠 1d Langmuir–Blodgett transfer model","title":"Continuation of periodic orbits (FD)","text":"","category":"section"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We would like to compute the branches of periodic solutions from the Hopf points. We do this automatic branch switching as follows","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"# parameters for newton\nopt_po = NewtonPar(tol = 1e-10, verbose = true, max_iterations = 50)\n\n# parameters for continuation\nopts_po_cont = ContinuationPar(dsmin = 1e-5, dsmax = 0.35, ds= -0.001,\n\tp_max = 1.0, max_steps = 3, detect_bifurcation = 0,\n\tnewton_options = setproperties(opt_po; max_iterations = 15, tol = 1e-6), plot_every_step = 1)\n\n# spatio-temporal norm\nnormL2T(x; r = sqrt(par.Δx / L), M = 1) = norm(x, 2) * r * sqrt(1/M)\n\nM = 100 # number of time sections\nbr_potrap = continuation(\n\t# arguments for branch switching\n\tbr, 5,\n\t# arguments for continuation\n\topts_po_cont, PeriodicOrbitTrapProblem(M = M, jacobian = :FullSparseInplace, update_section_every_step = 1);\n\t# parameter value used for branching\n\tδp = 1e-5,\n\t# use deflated Newton to find non-trivial solutions\n\tusedeflation = true,\n\t# algorithm to solve linear associated with periodic orbit problem\n\t# tangent algorithm along the branch, linear algo specific to PALC\n\talg = PALC(tangent = Bordered(), bls = BorderingBLS(solver = DefaultLS(), check_precision = false)),\n\tverbosity = 3, plot = true,\n\trecord_from_solution = (x, p) -> normL2T(x[1:end-1], M = M),\n\tplotSolution = (x, p; kwargs...) -> begin\n\t\t\theatmap!(reshape(x[1:end-1], N, M)'; ylabel=\"T=$(round(x[end]))\", color=:viridis, kwargs...)\n\t\t\tplot!(br, subplot=1, label=\"\")\n\t\tend,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"and we obtain the following graph. It is interesting to note that the periodic solutions converge to an homoclinic orbit here with a very large period. (Image: )","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"We can do this for the other Hopf points as well. Note that, we have to increase the number of time sections M to improve the convergence to the homoclinic orbits.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"(Image: )","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"Here are some examples of periodic solutions.","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"(Image: )","category":"page"},{"location":"tutorials/Langmuir/","page":"🟠 1d Langmuir–Blodgett transfer model","title":"🟠 1d Langmuir–Blodgett transfer model","text":"[Köpf]: Köpf and Thiele, Emergence of the Bifurcation Structure of a Langmuir–Blodgett Transfer Model., 2014","category":"page"},{"location":"faq/#FAQ","page":"Frequently asked questions","title":"FAQ","text":"","category":"section"},{"location":"faq/#How-can-I-save-a-solution-every-n-steps,-or-at-specific-parameter-values?","page":"Frequently asked questions","title":"How can I save a solution every n steps, or at specific parameter values?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can use the callback finalise_solution in the function call continuation. For example, you can use something like this to save all steps","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"function mySave(u, tau, step, contResult, personaldata)\n\tpush!(personaldata, u)\nend","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"and pass it like continuation(prob, alg, opts; finalise_solution = (z, tau, step, contResult; k...) -> mySave(z, tau, step, contResult, myData))","category":"page"},{"location":"faq/#The-Fold-/-Hopf-Continuation-does-not-work,-why?","page":"Frequently asked questions","title":"The Fold / Hopf Continuation does not work, why?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"This requires some precise computations. Have you tried passing the expression of the Jacobian instead of relying on finite differences.","category":"page"},{"location":"faq/#What-is-the-parameter-theta-about-in-ContinuationPar?","page":"Frequently asked questions","title":"What is the parameter theta about in ContinuationPar?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"See the description of continuation on the page Library.","category":"page"},{"location":"faq/#How-can-I-change-the-preconditioner-during-computations?","page":"Frequently asked questions","title":"How can I change the preconditioner during computations?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"The easiest way to achieve this is by using the callbacks provided by newton and continuation. See the documentation about these two methods. See also the example 2d Ginzburg-Landau equation","category":"page"},{"location":"faq/#How-can-I-implement-my-own-bifurcation-detection-method?","page":"Frequently asked questions","title":"How can I implement my own bifurcation detection method?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can use the callback finalise_solution but the best way is probably to use the Iterator Interface to inject your code anywhere in the continuation procedure.","category":"page"},{"location":"faq/#How-do-I-dissociate-the-computation-of-eigenvalues-from-the-jacobian-that-I-passed?","page":"Frequently asked questions","title":"How do I dissociate the computation of eigenvalues from the jacobian that I passed?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Sometimes, for example when implementing boundary conditions, you pass a jacobian J but the eigenvalues, and the bifurcation points are not simply related to J. One way to bypass this issue is to define a new eigensolver <: AbstractEigenSolver and pass it to the NewtonPar field eigsolver. This is done for example in example/SH2d-fronts-cuda.jl.","category":"page"},{"location":"faq/#How-can-I-print-the-eigenvalues-during-continuation?","page":"Frequently asked questions","title":"How can I print the eigenvalues during continuation?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can print the eigenvalues using the following callback:","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"finalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\tBK.haseigenvalues(contResult) && Base.display(contResult.eig[end].eigenvals)\n\t\treturn true\n\tend,","category":"page"},{"location":"faq/#How-can-I-reject-a-Newton-Step?","page":"Frequently asked questions","title":"How can I reject a Newton Step?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"You can reject a newton step by passing to continuation the argument callback_newton","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"function mycallback((x, f, J, res, iteration, itlinear, options); kwargs...)\n\t# stop Newton algo if residual too large\n\tif res > 1e2\n\t\t@warn \"Reject Newton step!!\"\n\t\treturn false\n\tend\n\treturn true\nend","category":"page"},{"location":"faq/#How-do-I-stop-continuation?","page":"Frequently asked questions","title":"How do I stop continuation?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Using the argument finalise_solution in continuation. Simply make this function finalise_solution return false.","category":"page"},{"location":"faq/#How-do-I-compute-both-sides-of-a-branch?","page":"Frequently asked questions","title":"How do I compute both sides of a branch?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Instead of using two calls to continuation, you can pass the keyword bothside=true to continuation","category":"page"},{"location":"faq/#How-do-I-compute-period-orbits-for-non-autonomous-problems","page":"Frequently asked questions","title":"How do I compute period orbits for non-autonomous problems","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"The package does not yet allow to compute periodic orbits solutions of non-autonomous Cauchy problems like","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"fracdudt = F(u par t)","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"On certain cases, one can still go away with the following trick. Say one is interested (dummy example!) to study","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"dot u = cos(u) + cos(omega cdot t)","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"Then one can use the following autonomous vector field","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"function vectorField(U, par)\n\tu, x, y = U\n\tout = similar(U)\n\tout[1] = cos(u) + x\n\tx2 = x^2+y^2\n\tout[2] = x + par.ω * y - x * x2\n\tout[3] = y - par.ω * x - y * x2\n\tout\nend","category":"page"},{"location":"faq/#Arpack-is-slow-in-computing-eigenvalues","page":"Frequently asked questions","title":"Arpack is slow in computing eigenvalues","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"This is probably due to iterative refinement conducted by SuiteSparse as explained in this blog post. You can disable this using","category":"page"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"using SuiteSparse\nSuiteSparse.UMFPACK.umf_ctrl[8] = 0","category":"page"},{"location":"faq/#Should-I-use-CVODE_BDF?","page":"Frequently asked questions","title":"Should I use CVODE_BDF?","text":"","category":"section"},{"location":"faq/","page":"Frequently asked questions","title":"Frequently asked questions","text":"SciML is now able to match the performance of the Sundials solver CVODE_BDF. Check the news for more information.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/#sh1d","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"","category":"section"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Pages = [\"Swift-Hohenberg1d.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"In this tutorial, we will see how to compute automatically the bifurcation diagram of the 1d Swift-Hohenberg equation. This example is treated in pde2path.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"-(I+Delta)^2 u+lambdacdot u +nu u^3-u^5 = 0tagE","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"with Dirichlet boundary conditions. We use a Sparse Matrix to express the operator L_1=(I+Delta)^2. We start by loading the packages:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"using Revise\nusing SparseArrays, LinearAlgebra, DiffEqOperators, Setfield, Parameters\nusing BifurcationKit\nusing Plots\nconst BK = BifurcationKit","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We then define a discretization of the problem","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"# discretisation\nN = 200\nl = 6.\nX = -l .+ 2l/N*(0:N-1) |> collect\nh = X[2]-X[1]\n\n# define a norm\nconst _weight = rand(N)\nnormweighted(x) = norm(_weight .* x)\n\n# boundary condition\nQ = Dirichlet0BC(h |> typeof)\nΔ = sparse(CenteredDifference(2, 2, h, N) * Q)[1]\nL1 = -(I + Δ)^2\n\n# functional of the problem\nfunction R_SH(u, par)\n\t@unpack λ, ν, L1 = par\n\tout = similar(u)\n\tout .= L1 * u .+ λ .* u .+ ν .* u.^3 - u.^5\nend\n\n# jacobian\nJac_sp(u, par) = par.L1 + spdiagm(0 => par.λ .+ 3 .* par.ν .* u.^2 .- 5 .* u.^4)\n\n# second derivative\nd2R(u,p,dx1,dx2) = @. p.ν * 6u*dx1*dx2 - 5*4u^3*dx1*dx2\n\n# third derivative\nd3R(u,p,dx1,dx2,dx3) = @. p.ν * 6dx3*dx1*dx2 - 5*4*3u^2*dx1*dx2*dx3\n\n# parameters associated with the equation\nparSH = (λ = -0.7, ν = 2., L1 = L1)\n\n# initial condition\nsol0 = zeros(N)\n\n# Bifurcation Problem\nprob = BifurcationProblem(R_SH, sol0, parSH, (@lens _.λ); J = Jac_sp,\n\trecord_from_solution = (x, p) -> (n2 = norm(x), nw = normweighted(x), s = sum(x), s2 = x[end ÷ 2], s4 = x[end ÷ 4], s5 = x[end ÷ 5]),\n\tplot_solution = (x, p;kwargs...)->(plot!(X, x; ylabel=\"solution\", label=\"\", kwargs...)))","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We then choose the parameters for continuation with precise detection of bifurcation points by bisection:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"optnew = NewtonPar(verbose = false, tol = 1e-12)\nopts = ContinuationPar(dsmin = 0.0001, dsmax = 0.01, ds = 0.01, p_max = 1.,\n\tnewton_options = setproperties(optnew; max_iterations = 30, tol = 1e-8),\n\tmax_steps = 300, plot_every_step = 40,\n\tdetect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-17, dsmin_bisection = 1e-7)","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Before we continue, it is useful to define a callback (see continuation) for newton to avoid spurious branch switching. It is not strictly necessary for what follows.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"function cb(state; kwargs...)\n\t_x = get(kwargs, :z0, nothing)\n\tfromNewton = get(kwargs, :fromNewton, false)\n\tif ~fromNewton\n\t\t# if the residual is too large or if the parameter jump\n\t\t# is too big, abort continuation step\n\t\treturn norm(_x.u - state.x) < 20.5 && abs(_x.p - state.p) < 0.05\n\tend\n\ttrue\nend","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Next, we specify the arguments to be used during continuation, such as plotting function, tangent predictors, callbacks...","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"args = (verbosity = 0,\n\tplot = true,\n\tcallback_newton = cb, halfbranch = true,\n\t)","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Depending on the level of recursion in the bifurcation diagram, we change a bit the options as follows","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"function optrec(x, p, l; opt = opts)\n\tlevel = l\n\tif level <= 2\n\t\treturn setproperties(opt; max_steps = 300, detect_bifurcation = 3,\n\t\t\tnev = N, detect_loop = false)\n\telse\n\t\treturn setproperties(opt; max_steps = 250, detect_bifurcation = 3,\n\t\t\tnev = N, detect_loop = true)\n\tend\nend","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"tip: Tuning\nThe function optrec modifies the continuation options opts as function of the branching level. It can be used to alter the continuation parameters inside the bifurcation diagram.","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We are now in position to compute the bifurcation diagram","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"diagram = @time bifurcationdiagram(re_make(prob, params = @set parSH.λ = -0.1),\n\tPALC(),\n\t# here we specify a maximum branching level of 4\n\t4, optrec; args...)","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"After ~700s, you can plot the result ","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"plot(diagram; plotfold = false, \n\tmarkersize = 2, putspecialptlegend = false, xlims=(-1,1))\ntitle!(\"#branches = $(size(diagram))\")","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"Et voilà!","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/#Exploration-of-the-diagram","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"Exploration of the diagram","text":"","category":"section"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"The bifurcation diagram diagram is stored as tree:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"julia> diagram\n[Bifurcation diagram]\n ┌─ From 0-th bifurcation point.\n ├─ Children number: 5\n └─ Root (recursion level 1)\n ┌─ Number of points: 82\n ├─ Branch of EquilibriumCont\n ├─ Type of vectors: Vector{Float64}\n ├─ Parameter l starts at -0.1, ends at 1.0\n ├─ Algo: PALC\n └─ Special points:\n\nIf `br` is the name of the branch,\nind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`\n\n- # 1, bp at λ ≈ +0.00739184 ∈ (+0.00694990, +0.00739184), |δp|=4e-04, [converged], δ = ( 1, 0), step = 8, eigenelements in eig[ 9], ind_ev = 1\n- # 2, bp at λ ≈ +0.15163058 ∈ (+0.15157533, +0.15163058), |δp|=6e-05, [converged], δ = ( 1, 0), step = 19, eigenelements in eig[ 20], ind_ev = 2\n- # 3, bp at λ ≈ +0.48386330 ∈ (+0.48386287, +0.48386330), |δp|=4e-07, [converged], δ = ( 1, 0), step = 43, eigenelements in eig[ 44], ind_ev = 3\n- # 4, bp at λ ≈ +0.53115107 ∈ (+0.53070912, +0.53115107), |δp|=4e-04, [converged], δ = ( 1, 0), step = 47, eigenelements in eig[ 48], ind_ev = 4\n- # 5, bp at λ ≈ +0.86889123 ∈ (+0.86887742, +0.86889123), |δp|=1e-05, [converged], δ = ( 1, 0), step = 71, eigenelements in eig[ 72], ind_ev = 5\n- # 6, endpoint at λ ≈ +1.00000000, step = 81","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"We can access the different branches with BK.getBranch(diagram, (1,)). Alternatively, you can plot a specific branch:","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"plot(diagram; code = (1,), plotfold = false, markersize = 2, putspecialptlegend = false, xlims=(-1,1))","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"🟡 1d Swift-Hohenberg equation (Automatic)","text":"(Image: )","category":"page"},{"location":"tutorials/Swift-Hohenberg1d/#References","page":"🟡 1d Swift-Hohenberg equation (Automatic)","title":"References","text":"","category":"section"},{"location":"simplehopf/#Simple-Hopf-point","page":"Simple Hopf","title":"Simple Hopf point","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"At a Hopf branch point (x_0p_0) for the problem F(xp)=0, the spectrum of the linear operator dF(x_0p_0) contains two purely imaginary pm iomega omega 0 which are simple. At such point, we can compute the normal form to transform the initial Cauchy problem","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"dot x = mathbfF(xp)","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"in large dimensions to a complex polynomial vector field (delta pequiv p-p_0):","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"dot z = zleft(a cdotdelta p + iomega + l_1z^2right)quadtext(E)","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"whose solutions give access to the solutions of the Cauchy problem in a neighborhood of (xp).","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"More precisely, if mathbfJ equiv dmathbfF(x_0p_0), then we have mathbfJzeta = iomegazeta and mathbfJbarzeta = -iomegabarzeta for some complex eigenvector zeta. It can be shown that x(t) approx x_0 + 2Re(z(t)zeta) when p=p_0+delta p.","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"tip: Coefficient $l_1$\nThe coefficient l_1 above is called the Lyapunov coefficient","category":"page"},{"location":"simplehopf/#Expression-of-the-coefficients","page":"Simple Hopf","title":"Expression of the coefficients","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"The coefficients ab above are computed as follows[Haragus]:","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"a=leftlanglemathbfF_11(zeta)+2 mathbfF_20left(zeta Psi_001right) zeta^*rightrangle","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"l_1=leftlangle 2 mathbfF_20left(zeta Psi_110right)+2 mathbfF_20left(barzeta Psi_200right)+3 mathbfF_30(zeta zeta barzeta) zeta^*rightrangle","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"where","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"beginaligned\n-mathbfJ Psi_001 =mathbfF_01 \n(2 i omega-mathbfJ) Psi_200 =mathbfF_20(zeta zeta) \n-mathbfJ Psi_110 =2 mathbfF_20(zeta barzeta)\nendaligned","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"and where","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"$","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"\\mathbf{F}(x,p)-\\mathbf{J}x := \\sum{1\\leq q+l\\leq p}\\mathbf{F}{ql}(x^{(q)},p^{(l)})+o(\\|u\\|+\\|p\\|)^p. $","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"with mathbfF_ql a (q+l)-linear map ","category":"page"},{"location":"simplehopf/#Normal-form-computation","page":"Simple Hopf","title":"Normal form computation","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"The normal form (E) is automatically computed as follows","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"get_normal_form(br::ContResult, ind_bif::Int ;\n\tverbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The above call returns an object of type Hopf.","category":"page"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"simplehopf/#References","page":"Simple Hopf","title":"References","text":"","category":"section"},{"location":"simplehopf/","page":"Simple Hopf","title":"Simple Hopf","text":"[Haragus]: Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.","category":"page"},{"location":"detectionBifurcationPO/#Detection-of-bifurcation-points-of-periodic-orbits","page":"Bifurcation detection (1 param)","title":"Detection of bifurcation points of periodic orbits","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"contParams.detect_bifurcation = 2","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The Floquet exponent λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint. ","category":"page"},{"location":"detectionBifurcationPO/#Precise-detection-of-bifurcation-points-using-Bisection","page":"Bifurcation detection (1 param)","title":"Precise detection of bifurcation points using Bisection","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"n_inversion: number of sign inversions in the bisection algorithm\nmax_bisection_steps maximum number of bisection steps\ntol_bisection_eigenvalue tolerance on real part of Floquet exponent to detect bifurcation points in the bisection steps","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"tip: Bisection mode\nDuring the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.","category":"page"},{"location":"detectionBifurcationPO/#Large-scale-computations","page":"Bifurcation detection (1 param)","title":"Large scale computations","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"[1]: In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation. ","category":"page"},{"location":"detectionBifurcationPO/#List-of-detected-bifurcation-points","page":"Bifurcation detection (1 param)","title":"List of detected bifurcation points","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Bifurcation index used\nBifurcation point (single eigenvalue stability change, Fold or branch point) bp\nNeimark-Sacker ns\nPeriod doubling pd\nNot documented nd","category":"page"},{"location":"detectionBifurcationPO/#Eigensolver","page":"Bifurcation detection (1 param)","title":"Eigensolver","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"danger: Floquet multipliers computation\nThe computation of Floquet multipliers is necessary for the detection of bifurcations of periodic orbits (which is done by analyzing the Floquet exponents obtained from the Floquet multipliers). Hence, the eigensolver needs to compute the eigenvalues with largest modulus (and not with largest real part which is their default behavior). This can be done by changing the option which = :LM of the eigensolver. Nevertheless, note that for most implemented eigensolvers in BifurcationKit, the proper option is automatically set. ","category":"page"},{"location":"detectionBifurcationPO/#Generic-bifurcation","page":"Bifurcation detection (1 param)","title":"Generic bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. ","category":"page"},{"location":"detectionBifurcationPO/#Fold-bifurcation","page":"Bifurcation detection (1 param)","title":"Fold bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Fold point is done by monitoring the monotonicity of the parameter.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.","category":"page"},{"location":"detectionBifurcationPO/#Neimark-Sacker-bifurcation","page":"Bifurcation detection (1 param)","title":"Neimark-Sacker bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Neimark-Sacker point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Neimark-Sacker point is detected, a point is added to br.specialpoint.","category":"page"},{"location":"detectionBifurcationPO/#Period-doubling-bifurcation","page":"Bifurcation detection (1 param)","title":"Period-doubling bifurcation","text":"","category":"section"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Period-doubling point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcationPO/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Period-doubling point is detected, a point is added to br.specialpoint.","category":"page"},{"location":"abs-from-hopf/#From-Hopf-/-PD-/-Branch-point-to-periodic-orbits","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf / PD / Branch point to periodic orbits","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"Pages = [\"abs-from-hopf.md\"]\nDepth = 3","category":"page"},{"location":"abs-from-hopf/#From-Hopf-point-to-periodic-orbits","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf point to periodic orbits","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"In order to compute the bifurcated branch of periodic solutions at a Hopf bifurcation point, you need to choose a method to compute periodic orbits among:","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"Periodic orbits based on Trapezoidal rule\nPeriodic orbits based on orthogonal collocation\nPeriodic orbits based on the shooting method","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"Once you have decided which method to use, you can call the following:","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"continuation(br::ContResult, ind_HOPF::Int, _contParams::ContinuationPar,\n\tprob::AbstractPeriodicOrbitProblem ;\n\tδp = nothing, ampfactor = 1, kwargs...)","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We refer to continuation for more information about the arguments. Here, we just say a few words about how we can specify prob::AbstractPeriodicOrbitProblem.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"For Periodic orbits based on Trapezoidal rule, you can pass PeriodicOrbitTrapProblem(M = 51) where M is the number of times slices in the periodic orbit.\nFor Periodic orbits based on orthogonal collocation, you can pass PeriodicOrbitOCollProblem(M, m) where M is the number of times slices in the periodic orbit and m is the degree of the collocation polynomials.\nFor Periodic orbits based on the shooting method, you need more parameters. For example, you can pass ShootingProblem(M, odeprob, Euler()) or PoincareShootingProblem(M, odeprob, Euler()) where odeprob::ODEProblem (see DifferentialEquations.jl) is an ODE problem to specify the Cauchy problem amd M is the number of sections.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"See Branch switching (Hopf point) for the precise method definition","category":"page"},{"location":"abs-from-hopf/#Algorithm","page":"From Hopf/PD/Branch to periodic orbits","title":"Algorithm","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"The algorithm proceeds as follows. The normal form of the Hopf bifurcation is first computed. Then a predictor for the bifurcated branch of periodic orbits is generated from the normal form. Finally, this predictor is used as a guess for the computation of periodic orbits.","category":"page"},{"location":"abs-from-hopf/#Example","page":"From Hopf/PD/Branch to periodic orbits","title":"Example","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"The simplest example is from the getting-started section which we repeat partially below. Several examples are provided in example ODE. In the case of PDE, you can have a look at Brusselator or 2d Ginzburg-Landau equation.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We compute a branch with a Hopf bifurcation:","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"using BifurcationKit, Parameters, Plots\n\nfunction Fsl(X, p)\n @unpack r, μ, ν, c3 = p\n u, v = X\n ua = u^2 + v^2\n [\n r * u - ν * v - ua * (c3 * u - μ * v)\n r * v + ν * u - ua * (c3 * v + μ * u)\n ]\nend\n\npar_sl = (r = 0.1, μ = 0., ν = 1.0, c3 = 1.0)\nu0 = zeros(2)\nprob = BifurcationProblem(Fsl, u0, par_sl, (@lens _.r))\nopts = ContinuationPar()\nbr = continuation(prob, PALC(), opts, bothside = true)","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We then compute the branch of periodic solutions using orthogonal collocation (for example):","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"br_po = continuation(br, 2, opts,\n PeriodicOrbitOCollProblem(20, 5)\n )\nplot(br, br_po)","category":"page"},{"location":"abs-from-hopf/#From-Period-doubling-point-to-curve-of-periodic-orbits","page":"From Hopf/PD/Branch to periodic orbits","title":"From Period-doubling point to curve of periodic orbits","text":"","category":"section"},{"location":"abs-from-hopf/#Case-of-Shooting-and-Collocation","page":"From Hopf/PD/Branch to periodic orbits","title":"Case of Shooting and Collocation","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We provide an automatic branching procedure in this case. In essence, all you have to do is to call","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"continuation(br::ContResult, ind_PD::Int, _contParams::ContinuationPar;\n prm = true,\n kwargs...)","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"The option prm=true enforces that the period-doubling normal form is computed using the Poincaré return map ; this is only necessary in case of use of the collocation method. Indeed, in the case of the collocation method, an automatic procedure based on the Iooss normal form has yet to be implemented.","category":"page"},{"location":"abs-from-hopf/#Case-of-Trapezoid-method","page":"From Hopf/PD/Branch to periodic orbits","title":"Case of Trapezoid method","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We do not provide (for now) the automatic branching procedure for these bifurcations of periodic orbits. As a consequence, the user is asked to provide the amplitude of the bifurcated solution.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"The call is as follows. Please note that a deflation is included in this method to simplify branch switching.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"continuation(br::AbstractBranchResult, ind_PD::Int, contParams::ContinuationPar;\n\tδp = 0.1, ampfactor = 1, usedeflation = false, kwargs...)","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"An example of use is provided in Lur'e problem.","category":"page"},{"location":"abs-from-hopf/#Algorithm-2","page":"From Hopf/PD/Branch to periodic orbits","title":"Algorithm","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"The algorithm proceeds as follows. The normal form of the Period-doubling bifurcation is first computed. Then a predictor for the bifurcated branch of periodic orbits is generated from the normal form. Finally, this predictor is used as a guess for the computation of periodic orbits.","category":"page"},{"location":"abs-from-hopf/#From-Branch-point-to-curve-of-periodic-orbits","page":"From Hopf/PD/Branch to periodic orbits","title":"From Branch point to curve of periodic orbits","text":"","category":"section"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We do not provide (for now) the automatic branching procedure for these bifurcations of periodic orbits. As a consequence, the user is asked to provide the amplitude of the bifurcated solution.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"We provide the branching method for the following methods to compute periodic orbits: PeriodicOrbitTrapProblem, PeriodicOrbitOCollProblem, ShootingProblem and PoincareShootingProblem. The call is as follows. Please note that a deflation is included in this method to simplify branch switching.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"An example of use is provided in Lur'e problem.","category":"page"},{"location":"abs-from-hopf/","page":"From Hopf/PD/Branch to periodic orbits","title":"From Hopf/PD/Branch to periodic orbits","text":"continuation(br::AbstractBranchResult, ind_PD::Int, contParams::ContinuationPar;\n\tδp = 0.1, ampfactor = 1, usedeflation = false, kwargs...)","category":"page"},{"location":"tutorials/tutorials/#Tutorials","page":"Tutorials","title":"Tutorials","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"tutorials.md\"]\nDepth = 2","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"The tutorials are rated by the following scale of difficulty","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"🟢 basic knowledge of (numerical) bifurcation theory (following equilibria / periodic orbits)\n🟡 advanced knowledge of (numerical) bifurcation theory (codim 2 bifurcations of equilibria)\n🟠 high level of knowledge of (numerical) bifurcation theory (codim 2 bifurcations of periodic orbits, tweaking the methods)\n🟤 very advanced tutorial, research level","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"There are three levels of automatization of the computation in these tutorials:","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"fully automatic bifurcation diagram (aBD) computation (only for equilibria): one uses bifurcationdiagram and let it compute the diagram fully automatically. Another possibility is to use deflated continuation.\nsemi-automatic bifurcation diagram computation: one uses automatic branch switching (aBS) to compute branches at specified bifurcation points\nmanual bifurcation diagram computation: one does not use automatic branch switching. This has only educational purposes or for complex problems where aBS fails.","category":"page"},{"location":"tutorials/tutorials/#ODE-examples","page":"Tutorials","title":"ODE examples","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"These examples are specific to ODEs. ","category":"page"},{"location":"tutorials/tutorials/#Computation-of-equilibria","page":"Tutorials","title":"Computation of equilibria","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsBasic1.md\", \"ode/tutorials1.md\", \"ode/tutorialPP2.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Codimension-2-bifurcations-of-equilibria","page":"Tutorials","title":"Codimension 2 bifurcations of equilibria","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialCO.md\",\"ode/lorenz84.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Periodic-orbits","page":"Tutorials","title":"Periodic orbits","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"We provide some examples focused on the computation of periodic orbits. Here is one where we present the different ways to compute periodic orbits. ","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsODE.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Here is one for aBS from period-doubling bifurcations of periodic orbits","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsODE-PD.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"In the next tutorial, we show how to refine a periodic orbit guess obtained from numerical simulation. We also show how to perform continuation of PD/NS points using Shooting or Collocation. ","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/tutorialsCodim2PO.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"In the next tutorial, we showcase the detection of Chenciner bifurcations. This is a relatively advanced tutorial, so we don't give much explanations. The reader should get first familiar with the above simpler examples.","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/steinmetz.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"In the next tutorial, we showcase aBS from Bautin/HH to curve of Fold/NS of periodic orbits.","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/lorenz84-PO.md\",]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Homoclinic-orbits","page":"Tutorials","title":"Homoclinic orbits","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Based on the package HclinicBifurcationKit.jl and its docs.","category":"page"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"🟡 Autonomous electronic circuit (aBS from BT)\n🟡 Nonlinear laser model","category":"page"},{"location":"tutorials/tutorials/#DAE-examples","page":"Tutorials","title":"DAE examples","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/Colpitts.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#DDE-examples","page":"Tutorials","title":"DDE examples","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"See the tutorials of DDEBifurcationKit.jl.","category":"page"},{"location":"tutorials/tutorials/#Examples-based-on-ModelingToolkit","page":"Tutorials","title":"Examples based on ModelingToolkit","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"ode/NME-MTK.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs:-bifurcations-of-equilibria","page":"Tutorials","title":"PDEs: bifurcations of equilibria","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"tutorials1.md\", \"tutorials1b.md\", \"tutorials2.md\", \"mittelmann.md\", \"tutorials2b.md\", \"tutorialsSH3d.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs:-automatic-bifurcation-diagram","page":"Tutorials","title":"PDEs: automatic bifurcation diagram","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"Swift-Hohenberg1d.md\", \"tutorialCarrier.md\", \"ks1d.md\", \"mittelmannAuto.md\", \"ks2d.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs:-bifurcations-of-periodic-orbits","page":"Tutorials","title":"PDEs: bifurcations of periodic orbits","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"tutorials3.md\",\"tutorials3b.md\", \"BrusselatorFF.md\", \"tutorialsPD.md\", \"tutorialsCGL.md\", \"tutorialsCGLShoot.md\",\"Langmuir.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#PDEs-based-on-FEM-with-[Gridap.jl](https://github.com/gridap/Gridap.jl)","page":"Tutorials","title":"PDEs based on FEM with Gridap.jl","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"mittelmannGridap.md\"]\nDepth = 1","category":"page"},{"location":"tutorials/tutorials/#Symmetries,-freezing,-waves,-fronts","page":"Tutorials","title":"Symmetries, freezing, waves, fronts","text":"","category":"section"},{"location":"tutorials/tutorials/","page":"Tutorials","title":"Tutorials","text":"Pages = [\"autocatalyticAuto.md\", \"autocatalytic.md\", \"cgl1dwave.md\", \"detonationEngine.md\"]\nDepth = 1","category":"page"},{"location":"PDContinuationPO/#Continuation-of-Period-doubling-(PD)-bifurcations-of-periodic-orbits","page":"Period-Doubling continuation (2 params)","title":"Continuation of Period-doubling (PD) bifurcations of periodic orbits","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"Pages = [\"PDContinuationPO.md\"]\nDepth = 2","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"warning: Work in progress\nContinuation of PD of POs is a recent addition. It has not been thoroughly tested. ","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In this page, we explain how to perform continuation of PD points of periodic orbits and detect the following codim 2 bifurcations.","category":"page"},{"location":"PDContinuationPO/#List-of-detected-codim-2-bifurcation-points","page":"Period-Doubling continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"Bifurcation symbol used\nStrong resonance 1:2 bifurcation R2\nFold / Flip foldFlip\nPeriod-Doubling / Neimark-Sacker pdNS\nGeneralized Period-Doubling gpd","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"PDContinuationPO/#PD-continuation","page":"Period-Doubling continuation (2 params)","title":"PD continuation","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"The continuation of PD bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation), except the Trapezoid one, for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.","category":"page"},{"location":"PDContinuationPO/#Detection-of-codim-2-bifurcation-points","page":"Period-Doubling continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the option detect_codim2_bifurcation in the method continuation ","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"the detection of Generalised Period-Doubling bifurcation is done by computing the PD normal form\nthe detection the above bifurcation points is done by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"PDContinuationPO/#Setting-the-jacobian","page":"Period-Doubling continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In order to apply the newton algorithm to the PD functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the PD functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"For the case jacobian_ma = :minaug, when the shooting method is employed, the adjoint of the flow is required. This can usually be computed with ReverseDiff.jl.","category":"page"},{"location":"PDContinuationPO/#Codim-2-continuation","page":"Period-Doubling continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"To compute the codim 2 curve of PD points of periodic orbits, one can call continuation with the following options","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_pd::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"PDContinuationPO/#Algorithmic-details","page":"Period-Doubling continuation (2 params)","title":"Algorithmic details","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"The continuation of PD points is based on the formulation","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"G(upomega) = (F_po(up) sigma(up))inmathbb R^n+1quadquad (mathcal F_pd)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"where F_po is the functional for locating periodic orbits and the test function sigma is solution of","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"leftbeginarraycc\nN(up) w \nv^top 0\nendarrayrightleftbeginarrayc\nr \nsigma(up)\nendarrayright=leftbeginarrayc\n0_n \n1\nendarrayright","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"In the case of Multiple Standard Shooting, the matrix N is based on the monodromy M(x_iT_i)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"N=left(beginarraycccccc\nM_1 -I 0 cdots 0 \n0 M_2 -I cdots 0 \nvdots cdots ddots ddots vdots \n0 cdots cdots ddots -I \nI cdots cdots 0 M_m \nendarrayright)","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"The jacobian of the PD functional to use for the Newton algorithm","category":"page"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"leftbeginarraycc\npartial_uF_po partial_pF_po \npartial_usigma partial_psigma\nendarrayright","category":"page"},{"location":"PDContinuationPO/#References","page":"Period-Doubling continuation (2 params)","title":"References","text":"","category":"section"},{"location":"PDContinuationPO/","page":"Period-Doubling continuation (2 params)","title":"Period-Doubling continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"tutorials/ks1d/#1d-Kuramoto–Sivashinsky-Equation","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"","category":"section"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"Pages = [\"ks1d.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"warning: Warning\nThis is work in progress... In particular, there is a combinatorial explosion that I need to address.","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"unknown: References\nThe following example is exposed in Evstigneev, Nikolay M., and Oleg I. Ryabkov. Bifurcation Diagram of Stationary Solutions of the 2D Kuramoto-Sivashinsky Equation in Periodic Domains. Journal of Physics: Conference Series 1730, no. 1 2021","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"We study the 1d Kuramoto–Sivashinsky equation with Dirichlet boundary conditions:","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"left(2 u u+ uright)+2lambda u^(4)=0 u(0)=u(pi)=0","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"We discretize the problem by using u(x)=sum_k=1^infty u_k sin (k x) which gives","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"left(2lambda k^4-k^2right) u_k+frack2left(sum_l=1^infty u_k+l u_k-frac12 sum_l+m=k u_l u_mright)=0","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"This is a good example for the use of automatic bifurcation diagram as we shall see. Let us first encode our problem","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"using Revise, LinearAlgebra, Plots\nusing Parameters, Setfield, ForwardDiff\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# we use this library for plotting\nusing ApproxFun\n\nfunction generateLinear(n)\n\tΔ = [-k^2 for k = 1:n]\n\treturn Δ, Δ.^2\nend\n\nfunction Fks1d(a, p)\n\t@unpack Δ, Δ2, λ, N = p\n\tout = (2λ) .* (Δ2 .* a)\n\tout .+= (Δ .* a)\n\tfor l=1:N\n\t\tfor m=1:N\n\t\t\tif 0 < l+m <= N\n\t\t\t\tout[l+m] += l*a[l]*a[m]\n\t\t\tend\n\t\t\tif 0 < m-l <= N\n\t\t\t\tout[m-l] += l*a[l]*a[m]\n\t\t\tend\n\n\t\t\tif 0 < -(m-l) <= N\n\t\t\t\tout[l-m] -= l*a[l]*a[m]\n\t\t\tend\n\t\tend\n\tend\n\n\tout .*= -1\n\treturn out\nend","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"Having defined the model, we chose parameters:","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"N = 50\nΔ, Δ2 = generateLinear(N)\npar_ks = (Δ = Δ, Δ2 = Δ2, λ = 0.75, N = N)\n\n# we define a Bifurcation Problem\nprob = BifurcationProblem(Fks1d, zeros(N), par_ks, (@lens _.λ),\n record_from_solution = (x, p) -> (s = sum(x), u2 = x[3], nrm = norm(x)),\n plot_solution = (x, p; kwargs...) -> plot!(Fun(SinSpace(), x) ; kwargs...),)","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"and continuation options","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"optn = NewtonPar(verbose = false, tol = 1e-9, max_iterations = 15)\n\toptc = ContinuationPar(p_min = 1/150., p_max = 1., max_steps = 700, newton_options = optn,\n\tdsmax = 0.01, dsmin = 1e-4, ds = -0.001, detect_bifurcation = 3, nev = N, n_inversion = 8,\n\tmax_bisection_steps = 30, dsmin_bisection = 1e-10, plot_every_step = 50)\n\nkwargscont = (verbosity = 2, plot = true, normC = norm)","category":"page"},{"location":"tutorials/ks1d/#Computation-of-the-bifurcation-diagram","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"Computation of the bifurcation diagram","text":"","category":"section"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"# function to adapt continuation option to recursion level\nfunction optrec(x, p, l; opt = optc)\n\tlevel = l\n\tif level <= 2\n\t\treturn setproperties(opt; dsmax = 0.005, max_steps = 2000,\n\t\tdetect_bifurcation = 3, detect_loop = true, n_inversion = 6)\n\telse\n\t\treturn setproperties(opt; dsmax = 0.005, max_steps = 2000,\n\t\tdetect_bifurcation = 3, detect_loop = true, n_inversion = 6)\n\tend\nend\n\n# we now compute the bifurcation diagram\n# that is the connected component of (0,0)\ndiagram = @time bifurcationdiagram(prob, PALC(), 4, optrec;\n\t\tkwargscont..., verbosity = 0,\n\t\t)","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"Plotting the result can be done using","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"plot(diagram; code = (), plotfold = false, markersize = 3, putspecialptlegend = false,\n\t plotcirclesbif = true, applytoX = x->2/x, vars = (:param, :nrm),\n\t xlim = (0,150), ylim=(0,8))\ntitle!(\"#branches = $(size(diagram))\")","category":"page"},{"location":"tutorials/ks1d/","page":"🟢 1d Kuramoto–Sivashinsky Equation","title":"🟢 1d Kuramoto–Sivashinsky Equation","text":"(Image: )","category":"page"},{"location":"detectionBifurcation/#Detection-of-bifurcation-points-of-Equilibria","page":"Bifurcation detection (1 param)","title":"Detection of bifurcation points of Equilibria","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcations are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flags:","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"contParams.detect_bifurcation = 2","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The bifurcation points are located by looking at the spectrum e.g. by monitoring the unstable eigenvalues. The eigenvalue λ is declared unstable if real(λ) > contParams.tol_stability. The located bifurcation points are then returned in br.specialpoint. ","category":"page"},{"location":"detectionBifurcation/#Precise-detection-of-bifurcation-points-using-Bisection","page":"Bifurcation detection (1 param)","title":"Precise detection of bifurcation points using Bisection","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Note that the bifurcation points detected when detect_bifurcation = 2 can be rather crude localization of the true bifurcation points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) bifurcation has been detected. Hence, we only have a rough idea of where the bifurcation is located, unless your dsmax is very small... This can be improved as follows.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"If you choose detect_bifurcation = 3, a bisection algorithm is used to locate the bifurcation points more precisely. It means that we recursively track down the change in stability. Some options in ContinuationPar control this behavior:","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"n_inversion: number of sign inversions in the bisection algorithm\nmax_bisection_steps maximum number of bisection steps\ntol_bisection_eigenvalue tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"If this is still not enough, you can use a Newton solver to locate them very precisely. See Fold / Hopf Continuation.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"tip: Bisection mode\nDuring the bisection, the eigensolvers are called like eil(J, nev; bisection = true) in order to be able to adapt the solver precision.","category":"page"},{"location":"detectionBifurcation/#Large-scale-computations","page":"Bifurcation detection (1 param)","title":"Large scale computations","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must specify the number of eigenvalues to be computed (like nev = 10) in the parameters ::ContinuationPar passed to continuation. Note that nev is automatically incremented whenever a bifurcation point is detected [1]. Also, there is an option in ::ContinuationPar to save (or not) the eigenvectors. This can be useful in memory limited environments (like on GPUs).","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"[1]: In this case, the Krylov dimension is not increased because the eigensolver could be a direct solver. You might want to increase this dimension using the callbacks in continuation. ","category":"page"},{"location":"detectionBifurcation/#List-of-detected-bifurcation-points","page":"Bifurcation detection (1 param)","title":"List of detected bifurcation points","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"Bifurcation index used\nFold fold\nHopf hopf\nBifurcation point (single eigenvalue stability change, Fold or branch point) bp\nNot documented nd","category":"page"},{"location":"detectionBifurcation/#Eigensolver","page":"Bifurcation detection (1 param)","title":"Eigensolver","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The user must provide an eigensolver by setting NewtonOptions.eigsolver where newton_options is located in the parameter ::ContinuationPar passed to continuation. See NewtonPar and ContinuationPar for more information on the composite type of the options passed to newton and continuation.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The eigensolver is highly problem dependent and this is why the user should implement / parametrize its own eigensolver through the abstract type AbstractEigenSolver or select one among List of implemented eigen solvers.","category":"page"},{"location":"detectionBifurcation/#Generic-bifurcation","page":"Bifurcation detection (1 param)","title":"Generic bifurcation","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"By this we mean a change in the dimension of the Jacobian kernel. The detection of Branch point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. ","category":"page"},{"location":"detectionBifurcation/#Fold-bifurcation","page":"Bifurcation detection (1 param)","title":"Fold bifurcation","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Fold point is done by monitoring the monotonicity of the parameter.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_fold = true in the parameter ::ContinuationPar passed to continuation. When a Fold is detected on a branch br, a point is added to br.foldpoint allowing for later refinement using the function newton_fold.","category":"page"},{"location":"detectionBifurcation/#Hopf-bifurcation","page":"Bifurcation detection (1 param)","title":"Hopf bifurcation","text":"","category":"section"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection of Hopf point is done by analysis of the spectrum of the Jacobian.","category":"page"},{"location":"detectionBifurcation/","page":"Bifurcation detection (1 param)","title":"Bifurcation detection (1 param)","text":"The detection is triggered by setting detect_bifurcation > 1 in the parameter ::ContinuationPar passed to continuation. When a Hopf point is detected, a point is added to br.specialpoint allowing for later refinement using the function newton_hopf.","category":"page"},{"location":"intro_wave/#Freezing-problems,-symmetries-and-waves","page":"Introduction","title":"Freezing problems, symmetries and waves","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"This section is dedicated to the study of an equation (in x) F(x,p)=0 where one wishes to freeze a continuous symmetry. When the equation F(x p) = 0 has a continuous symmetry described by a Lie group G and action gcdot x for gin G, one can reduce the symmetry of the problem by considering the constrained problem[Beyn]:","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"left\nbeginarrayltagW\nF(x p) - scdot Tcdot x=0 \nlangle Tcdot x_refx-x_refrangle=0\nendarrayright","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"where T is a generator of the Lie algebra associated to G, x_ref is a reference solution and s is the speed. This is known as the freezing method.","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Similarly, one can reduce several symmetries by considering","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"left\nbeginarrayl\nF(x p) - sumlimits_i=1^N_g s_icdot T_icdot x=0 \nlangle T_icdot x_refx-x_refrangle=0quad i=1cdotsN_g\nendarrayright","category":"page"},{"location":"intro_wave/#Wave-stability","page":"Introduction","title":"Wave stability","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"There are several ways to compute the stability of a wave (x^ws^w). From [Sandstede], this requires to compute the spectrum of","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"d_1F(xp)- sumlimits_i=1^N_g s_icdot T_itagEV","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"However, there is (potentially) the zero eigenvalue associated to the eigenvectors T_icdot x^w. In practice, because the symmetry is discrete numerically, we find a small eigenvalue.","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Another way to compute the same spectrum is to proceed as follows. Using (W) as a definition for the functional G((xs)p)inmathbb R^N+1, the eigenproblem for computing the stability of a wave (x^ws^w) is","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"A x = σ BxtagGEV","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"where B = diag(1cdots10) and A=dG. An advantage of (GEV) over (EV) is that the trivial eigenvalues are removed but it comes at an increased cost. We can improved this situation as follows.","category":"page"},{"location":"intro_wave/#Case-N_g1","page":"Introduction","title":"Case N_g=1","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Let us have a look at (GEV) more closely. We need to solve for the eigenvalues sigma and the eigenvectors (x_1c_1) solutions of","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"left\nbeginarrayltagW\nJ x_1+c_1A_12 = sigma x_1 \nlangle A_21x_1rangle + A_22c_1=0\nendarrayright","category":"page"},{"location":"intro_wave/#Case-A_{22}\\neq-0","page":"Introduction","title":"Case A_22neq 0","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"If A_22neq 0, the eigen problem is equivalent to","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Jx_1 - c_1fraclangle A_21x_1rangleA_22 A_12= sigma x_1","category":"page"},{"location":"intro_wave/#Case-A_{22}-0","page":"Introduction","title":"Case A_22 = 0","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"If A_22 = 0, the eigen problem is equivalent to x_1=α A_21 + x_1^bot with langle A_21x_1^botrangle=0. Hence, I find langle A_21Jx_1^botrangle+c_1langle A_21A_12rangle=0","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Jx_1^bot-fraclangle A_21Jx_1^botranglelangle A_21A_12rangleA_21=σ x_1^","category":"page"},{"location":"intro_wave/#Encoding-of-the-functional-for-the-freezed-problem","page":"Introduction","title":"Encoding of the functional for the freezed problem","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"The freezing method is encoded in the composite type TWProblem which we loosely refer to as a Travelling Wave (TW) problem. ","category":"page"},{"location":"intro_wave/#Computation-with-newton","page":"Introduction","title":"Computation with newton","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"We provide a simplified call to newton to locate the freezed solution","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"newton(prob::TWProblem, orbitguess, options::NewtonPar; kwargs...)","category":"page"},{"location":"intro_wave/#Continuation","page":"Introduction","title":"Continuation","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"We also provide a simplified call to continuation to continue the freezed solution as function of a parameter:","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"continuation(prob::TWProblem, orbitguess, lens::Lens, contParams::ContinuationPar; jacobian = :MatrixFree, kwargs...)","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"Note that in this case, the eigen solver passed in contParams is converted into an appropriate generalized eigensolver.","category":"page"},{"location":"intro_wave/#References","page":"Introduction","title":"References","text":"","category":"section"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"intro_wave/","page":"Introduction","title":"Introduction","text":"[Sandstede]: Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.","category":"page"},{"location":"abs-from-codim2-eq/#From-codim-2-to-equilibria","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Pages = [\"abs-from-codim2-eq.md\"]\nDepth = 3","category":"page"},{"location":"abs-from-codim2-eq/#From-Bogdanov-Takens-(BT)-point-to-Fold-/-Hopf-curve","page":"From codim 2 to equilibria","title":"From Bogdanov-Takens (BT) point to Fold / Hopf curve","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"We provide an automatic branch switching method in this case (see for example Extended Lorenz-84 model or 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)). Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"continuation(br::ContResult, ind_BT::Int,\n\toptions_cont::ContinuationPar = br.contparams;\n\tnev = options_cont.nev,\n\tdetect_codim2_bifurcation::Int = 0,\n\tstart_with_eigen = false,\n\tautodiff = false,\n\tTeigvec = getvectortype(br),\n\tscaleζ = norm,\n\tkwargs...)","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"where ind_BT is the index of the BT point in br. Note that the BT has been detected during Fold or Hopf continuation. Calling the above method thus switches from Fold continuation to Hopf continuation (and vice-versa) automatically with the same parameter axis.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.","category":"page"},{"location":"abs-from-codim2-eq/#From-Zero-Hopf-(ZH)-point-to-Fold-/-Hopf-curve","page":"From codim 2 to equilibria","title":"From Zero-Hopf (ZH) point to Fold / Hopf curve","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"We provide an automatic branch switching method in this case (see for example Extended Lorenz-84 model or 2d Ginzburg-Landau). Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"continuation(br::ContResult, ind_ZH::Int,\n\toptions_cont::ContinuationPar = br.contparams;\n\tnev = options_cont.nev,\n\tdetect_codim2_bifurcation::Int = 0,\n\tstart_with_eigen = false,\n\tautodiff = false,\n\tTeigvec = getvectortype(br),\n\tscaleζ = norm,\n\tkwargs...)","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"where ind_ZH is the index of the ZH point in br. Note that the ZH has been detected during Fold or Hopf continuation. Calling the above method thus switches from Fold continuation to Hopf continuation (and vice-versa) automatically with the same parameter axis.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.","category":"page"},{"location":"abs-from-codim2-eq/#From-Hopf-Hopf-(HH)-point-to-Fold-/-Hopf-curve","page":"From codim 2 to equilibria","title":"From Hopf-Hopf (HH) point to Fold / Hopf curve","text":"","category":"section"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"We provide an automatic branch switching method in this case (see for example Extended Lorenz-84 model or 2d Ginzburg-Landau equation). Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"continuation(br::ContResult, ind_HH::Int,\n\toptions_cont::ContinuationPar = br.contparams;\n\tδp = nothing, ampfactor::Real = 1,\n\tnev = options_cont.nev,\n\tdetect_codim2_bifurcation::Int = 0,\n\tstart_with_eigen = false,\n\tautodiff = false,\n\tTeigvec = getvectortype(br),\n\tscaleζ = norm,\n\tkwargs...)","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"where ind_HH is the index of the HH point in br. Note that the HH has been detected during Hopf continuation. Calling the above method thus switches from Hopf continuation to another Hopf branch automatically with the same parameter axis.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"Check the docs of Fold / Hopf Continuation and particularly Setting the jacobian for improving the speed of computation for large scale systems.","category":"page"},{"location":"abs-from-codim2-eq/","page":"From codim 2 to equilibria","title":"From codim 2 to equilibria","text":"","category":"page"},{"location":"simplebp/#Simple-bifurcation-branch-point","page":"Simple branch point","title":"Simple bifurcation branch point","text":"","category":"section"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"unknown: References\nThe general method is exposed in Golubitsky, Martin, David G Schaeffer, and Ian Stewart. Singularities and Groups in Bifurcation Theory. New York: Springer-Verlag, 1985, VI.1.d page 295","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"A simple branch point (x_0p_0) for the problem F(xp)=0 satisfies dim ker dF(x_0p_0) = 1. At such point, we can apply Lyapunov-Schmidt reduction to transform the initial problem in large dimensions to a scalar polynomial (delta p equiv p-p_0): ","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"adelta p + zleft(b_1delta p + fracb_22z + fracb_36z^2right) = 0 tagE","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"whose solutions give access to all solutions in a neighborhood of (xp).","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"More precisely, if ker dF(x_0p_0) = mathbb Rzeta, one can show that x_0+zzeta is close to a solution on a new branch, thus satisfying F(x_0+zzetap_0+delta p)approx 0.","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"In the above scalar equation,","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"if aneq 0, this is a Saddle-Node bifurcation\nif a=0b_2neq 0, the bifurcation point is a Transcritical one where the bifurcated branch exists on each side of p.\nif a=0b_2=0 b_3neq 0, the bifurcation point is a Pitchfork one where the bifurcated branch only exists on one side of p. If it exists at smaller values then p, this is a subcritical Pitchfork bifurcation. In the other case, this is a supercritical Pitchfork bifurcation.","category":"page"},{"location":"simplebp/#Normal-form-computation","page":"Simple branch point","title":"Normal form computation","text":"","category":"section"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"The reduced equation (E) can be automatically computed as follows","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"get_normal_form(br::ContResult, ind_bif::Int ;\n\tverbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"where prob is the bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BranchPoint.","category":"page"},{"location":"simplebp/","page":"Simple branch point","title":"Simple branch point","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"IntroContinuation/#Continuation-methods:-introduction","page":"Introduction","title":"Continuation methods: introduction","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"Pages = [\"IntroContinuation.md\"]\nDepth = 3","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"The goal of these methods[Kuz],[Govaerts],[Rabinowitz],[Mei],[Keller] is to find solutions xinmathbb R^n to nonlinear equations","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"mathbb R^nni F(xp) = 0 quadtagE","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"as function of a real parameter p. Given a known solution (x_0p_0), we can, under reasonable assumptions, continue it by computing a 1d curve of solutions gamma = (x(s)p(s))_sin I passing through (x_0p_0).","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"For the sequel, it is convenient to use the following formalism [Kuz]","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"prediction of the next point\ncorrection\nstep size control.","category":"page"},{"location":"IntroContinuation/#Natural-continuation","page":"Introduction","title":"Natural continuation","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"More information is available at Predictors - Correctors","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"We just use this simple continuation method to give a trivial example of the formalism. Knowing (x_0 p_0), we form the predictor (x_0 p_0+ds) for some ds and use it as a guess for a Newton corrector applied to xto F(x p_0+ds). The corrector is thus the newton algorithm.","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"This continuation method is continuation(prob, Natural(), options).","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"danger: Usage\nYou should almost never use this predictor for computations. It fails at turning points, is not adaptive, ... ","category":"page"},{"location":"IntroContinuation/#Step-size-control","page":"Introduction","title":"Step size control","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"Each time the corrector phase failed, the step size ds is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size can be controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.","category":"page"},{"location":"IntroContinuation/#References","page":"Introduction","title":"References","text":"","category":"section"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Kuz]: Kuznetsov, Elements of Applied Bifurcation Theory.","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Govaerts]: Govaerts, Numerical Methods for Bifurcations of Dynamical Equilibria; Allgower and Georg, Numerical Continuation Methods","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Rabinowitz]: Rabinowitz, Applications of Bifurcation Theory; Dankowicz and Schilder, Recipes for Continuation","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Mei]: Mei, Numerical Bifurcation Analysis for Reaction-Diffusion Equations","category":"page"},{"location":"IntroContinuation/","page":"Introduction","title":"Introduction","text":"[Keller]: Keller, Lectures on Numerical Methods in Bifurcation Problems","category":"page"},{"location":"BifurcationDiagram/#Automatic-Bifurcation-diagram-computation","page":"Bifurcation diagram","title":"Automatic Bifurcation diagram computation","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"Thanks to the functionality presented in this part, we can compute the bifurcation diagram of a system recursively and fully automatically. More precisely, the function bifurcationdiagram allows to:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"compute a branch gamma of equilibria\ndetect all bifurcations on the branch\nrecursively compute the branches emanating from branch points on gamma.","category":"page"},{"location":"BifurcationDiagram/#Pitfalls","page":"Bifurcation diagram","title":"Pitfalls","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"For now, there is no way to decide if two branches gamma_1gamma_2 are the same. As a consequence:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"there is no loop detection. Hence, if the branch gamma has a component akin to a circle, you may experience a large number of branches\nif the bifurcation diagram itself has loops (see example below), you may experience a large number of branches","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"warning: Memory\nThe whole diagram is stored in RAM and you might be careful computing it on GPU. We'll add a file system for this in the future. ","category":"page"},{"location":"BifurcationDiagram/#Basic-example-with-simple-branch-points","page":"Bifurcation diagram","title":"Basic example with simple branch points","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using Revise, Plots\nusing BifurcationKit, Setfield\n\nFbp(u, p) = @. -u * (p + u * (2-5u)) * (p -.15 - u * (2+20u))\n\n# bifurcation problem\nprob = BifurcationProblem(Fbp, [0.0], -0.2, \n\t# specify the continuation parameter\n\t(@lens _);\n\trecord_from_solution = (x, p) -> x[1])\n\n# options for newton\n# we reduce a bit the tolerances to ease automatic branching\nopt_newton = NewtonPar(tol = 1e-9)\n\n# options for continuation\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.005, ds = 0.001,\n\tnewton_options = opt_newton,\n\tnev = 1,\n\t# parameter interval\n\tp_min = -1.0, p_max = .3,\n\t# detect bifurcations with bisection method\n\t# we increase here the precision for the detection of\n\t# bifurcation points\n\tn_inversion = 8)\n\ndiagram = bifurcationdiagram(prob, PALC(),\n\t# very important parameter. This specifies the maximum amount of recursion\n\t# when computing the bifurcation diagram. It means we allow computing branches of branches \n\t# at most in the present case.\n\t2,\n\t(args...) -> opts_br,\n)\n\t\n# You can plot the diagram like \nplot(diagram; putspecialptlegend=false, markersize=2, plotfold=false, title = \"#branches = $(size(diagram))\")","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"This gives","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"diagram","category":"page"},{"location":"BifurcationDiagram/#Example-with-nonsimple-branch-points","page":"Bifurcation diagram","title":"Example with nonsimple branch points","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"To show the ability of the branch switching method to cope with non simple branch points, we look at the normal form of the Pitchfork with D6 symmetry which occurs frequently in problems with hexagonal symmetry. You may want to look at Bratu–Gelfand problem for a non trivial example of use.","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using Revise, Plots\nusing BifurcationKit, Setfield, LinearAlgebra\nconst BK = BifurcationKit\n\nfunction FbpD6(x, p)\n\treturn [ p.μ * x[1] + (p.a * x[2] * x[3] - p.b * x[1]^3 - p.c*(x[2]^2 + x[3]^2) * x[1]),\n\t\tp.μ * x[2] + (p.a * x[1] * x[3] - p.b * x[2]^3 - p.c*(x[3]^2 + x[1]^2) * x[2]),\n\t\tp.μ * x[3] + (p.a * x[1] * x[2] - p.b * x[3]^3 - p.c*(x[2]^2 + x[1]^2) * x[3])]\nend\n\n# model parameters\npard6 = (μ = -0.2, a = 0.3, b = 1.5, c = 2.9)\n\n# problem\nprob = BifurcationProblem(FbpD6, zeros(3), pard6, (@lens _.μ);\n\t\trecord_from_solution = (x, p) -> (n = norminf(x)))\n\n# newton options\nopt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)\n\n# continuation options\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01, \n\t# parameter interval\n\tp_max = 0.4, p_min = -0.5, \n\tnev = 3, \n\tnewton_options = opt_newton, \n\tmax_steps = 1000, \n\tn_inversion = 4)\n\nbdiag = bifurcationdiagram(prob, PALC(), 3,\n\t(args...) -> setproperties(opts_br; p_min = -0.250, p_max = .4, ds = 0.001, dsmax = 0.005, n_inversion = 4, detect_bifurcation = 3, max_bisection_steps=20, newton_options = opt_newton);\n\tnormC = norminf)","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"We can now plot the result:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"plot(bdiag; putspecialptlegend =false, markersize=2, plotfold=false, title=\"#branch = $(size(bdiag))\")","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"(Image: )","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"We can access the different branches with BK.getBranch(bdiag, (1,)). Alternatively, you can plot a specific branch:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"(Image: )","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"Finally, you can resume the computation of the bifurcation diagram if not complete by using the syntax","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":" bifurcationdiagram!(\n\t# this resume the computation of the diagram from the 2nd node\n\t# bdiag is written inplace\n\tget_branch(bdiag, (2,)), (current = 3, maxlevel = 6), \n\t(args...) -> setproperties(opts_br; p_min = -0.250, p_max = .4, ds = 0.001, dsmax = 0.005, n_inversion = 4, detect_bifurcation = 3, dsmin_bisection =1e-18, tol_bisection_eigenvalue=1e-11, max_bisection_steps=20, newton_options = (@set opt_newton.verbose = false)))","category":"page"},{"location":"BifurcationDiagram/#Printing-the-structure-of-the-diagram","page":"Bifurcation diagram","title":"Printing the structure of the diagram","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"It is sometimes useful to have a global representation of the bifurcation diagram. Here, we provide a text representation","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using AbstractTrees\n\nAbstractTrees.children(node::BK.BifDiagNode) = node.child\n\n## Things that make printing prettier\nAbstractTrees.printnode(io::IO, node::BifDiagNode) = print(io, \"$(node.code) [ $(node.level)]\")\n\nprint_tree(bdiag)","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"which should return","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"\njulia> print_tree(bdiag)\n0 [ 1]\n├─ 1 [ 2]\n│ ├─ 2 [ 3]\n│ ├─ 2 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ ├─ 4 [ 3]\n│ └─ 4 [ 3]\n└─ 1 [ 2]\n ├─ 2 [ 3]\n └─ 2 [ 3]","category":"page"},{"location":"BifurcationDiagram/#Plotting-the-structure-of-the-diagram","page":"Bifurcation diagram","title":"Plotting the structure of the diagram","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"We can also use GraphPlot to plot the tree underlying the bifurcation diagram:","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using LightGraphs, MetaGraphs, GraphPlot\n\nfunction graphFromDiagram!(_graph, diagram, indp)\n\t# ind is the index of the parent node\n\t# add vertex and associated information\n\tadd_vertex!(_graph)\n\tset_props!(_graph, nv(_graph), Dict(:code => diagram.code, :level => diagram.level))\n\tif nv(_graph) > 1\n\t\tadd_edge!(_graph, indp, nv(_graph))\n\tend\n\tif length(diagram.child) > 0\n\t\t# we now run through the children\n\t\tnew_indp = nv(_graph)\n\t\tfor diag in diagram.child\n\t\t\tgraphFromDiagram!(_graph, diag, new_indp)\n\t\tend\n\tend\nend\n\nfunction graphFromDiagram(diagram) \n\t_g = MetaGraph()\n\tgraphFromDiagram!(_g, diagram, 1)\n\treturn _g\nend\n\n_g = graphFromDiagram(bdiag)\n\ngplot(_g, nodelabel = [props(_g, ve)[:code] for ve in vertices(_g)])","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"which gives the following picture. The node label represent the index of the bifurcation point from which the branch branches.","category":"page"},{"location":"BifurcationDiagram/#Using-GraphRecipes","page":"Bifurcation diagram","title":"Using GraphRecipes","text":"","category":"section"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"Another solution is to use GraphRecipes and ","category":"page"},{"location":"BifurcationDiagram/","page":"Bifurcation diagram","title":"Bifurcation diagram","text":"using GraphRecipes\n\ngraphplot(_g, \n\tnode_weights = ones(nv(_g)).*10, \n\tnames=[props(_g, ve)[:code] for ve in vertices(_g)], \n\tcurvature_scalar=0.)","category":"page"},{"location":"periodicOrbitTrapeze/#Periodic-orbits-based-on-Trapezoidal-rule","page":"Trapezoid","title":"Periodic orbits based on Trapezoidal rule","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The Trapezoid method allows to compute periodic orbits by discretizing time using Finite Differences based on a trapezoidal rule\t. The method is implemented in the structure PeriodicOrbitTrapProblem. The general method is very well exposed in [Uecker],[Lust] and we adopt the notations of the first reference.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We look for periodic orbits as solutions (x(0)T) of","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"M_adot x = Tcdot F(x) x(0)=x(1)inmathbb R^ntag1","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"where M_a is a mass matrix (default is the identity one).","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"In order to have a unique solution, we need to remove the phase freedom. This is done by imposing a phase condition","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"frac1Tint_0^Tlangle x(s)-x_pi(s) phi(s)rangle dsapprox frac1msumlimits_i=1^mlangle x_i - x_pii phi_irangle = 0","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"for some x_piphi which are chosen (wisely).","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We note m the number of time slices of the periodic orbit. By discretizing the above problem, we obtain","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"beginarrayl\n\t\t0= M_aleft(x_j-x_j-1right)-frach2 left(Fleft(x_jright)+Fleft(x_j-1right)right)equiv G_j(x)quad j=1cdotsm-1 \n0= x_m-x_1 equiv G_m(x) \n0=sumlimits_i=1^mlangle x_i - x_pii phi_irangle=0\nendarray","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"where x_0=x_m and h=Tm. In view of the Newton method, we study the jacobian of the above system. The Jacobian w.r.t. (x_0T) is given by","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"mathcalJ=left(beginarrayccA_1 partial_TG star dendarrayright)tag2","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"where","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A_gamma=left(beginarrayccccccc\nM_1 0 0 0 cdots -H_1 0 \n-H_2 M_2 0 0 cdots 0 0 \n0 -H_3 M_3 0 cdots 0 0 \nvdots cdots ddots ddots ddots vdots vdots \n0 cdots cdots ddots ddots 0 0 \n0 cdots cdots 0 -H_m-1 M_m-1 0 \n-gamma I 0 cdots cdots cdots 0 I\nendarrayright)","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"with M_i = M_a-\tfrac h2dF(x_i) and H_i = M_a+frac h2dF(x_i-1).","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We solve the linear equation mathcal Jcdot sol = rhs with a bordering strategy (i.e. the linear solver is a subtype of <: AbstractBorderedLinearSolver) which in turn requires to solve A_gamma z=b where z=(xx_m). We also solve this equation with a bordering strategy but this time, it can be simplified as follows. If we write b=(fg), one gets J_c x=f and x_m=g+gamma x_1 where x_1 is the first time slice of x and J_c is the following cyclic matrix:","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"J_c=left(beginarrayccccccc\nM_1 0 0 0 cdots -H_1 \n-H_2 M_2 0 0 cdots 0 \n0 -H_3 M_3 0 cdots 0 \nvdots cdots ddots ddots ddots vdots \n0 cdots cdots ddots ddots 0 \n0 cdots cdots 0 -H_m-1 M_m-1 \nendarrayright)","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Our code thus provides methods to invert J_c and A_gamma using a sparse solver or a Matrix-Free one. A preconditioner can be used.","category":"page"},{"location":"periodicOrbitTrapeze/#Encoding-of-the-functional","page":"Trapezoid","title":"Encoding of the functional","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The functional is encoded in the composite type PeriodicOrbitTrapProblem. See the link for more information, in particular on how to access the underlying functional, its jacobian and other matrices related to it like A_gamma J_c...","category":"page"},{"location":"periodicOrbitTrapeze/#Preconditioning","page":"Trapezoid","title":"Preconditioning","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We strongly advise you to use a preconditioner to deal with the above linear problem. See 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS) for an example.","category":"page"},{"location":"periodicOrbitTrapeze/#Linear-solvers","page":"Trapezoid","title":"Linear solvers","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We provide many different linear solvers to take advantage of the formulations. These solvers are available through the argument jacobian in the constructor of PeriodicOrbitTrapProblem. For example, you can pass jacobian = :FullLU. Note that all the internal solvers and jacobian are set up automatically, you don't need to do anything. However, for the sake of explanation, we detail how this works.\t","category":"page"},{"location":"periodicOrbitTrapeze/#.-FullLU","page":"Trapezoid","title":"1. FullLU","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"When using jacobianPO = :FullLU, this triggers the computation of mathcal J as in (2) at each step of newton/continuation. The jacobian matrix mathcal J is stored a SparseArray. This can be quite costly flow large n (see (1)). This jacobian is often used with the the linear solver DefaultLS().","category":"page"},{"location":"periodicOrbitTrapeze/#.-FullSparseInplace","page":"Trapezoid","title":"2. FullSparseInplace","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Same as :FullLU but the jacobian is allocated only once and updated inplace. This is much faster than :FullLU but the sparsity pattern of dF must be constant.","category":"page"},{"location":"periodicOrbitTrapeze/#.-Dense","page":"Trapezoid","title":"3. Dense","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Same as : FullSparseInplace above but the matrix dG is dense. It is also updated inplace. This is useful to study ODE of small dimension.","category":"page"},{"location":"periodicOrbitTrapeze/#.-FullMatrixFree","page":"Trapezoid","title":"4. FullMatrixFree","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A matrix free linear solver is used for mathcal J: note that a preconditioner is very likely required here because of the cyclic shape of mathcal J which affects negatively the convergence properties of iterative solvers. Note that mathcal J is never formed in this case.","category":"page"},{"location":"periodicOrbitTrapeze/#.-BorderedLU","page":"Trapezoid","title":"5. BorderedLU","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"For :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver. More precisely, the bordered structure of mathcal J is stored using the internal structure POTrapJacobianBordered. Then, mathcal J is inverted using the custom bordered linear solver PeriodicOrbitTrapBLS which is based on the bordering strategy (see Bordered linear solvers (BLS)). This particular solver is based on an explicit formula which only requires to invert A_gamma: this is done by the linear solver AγLinearSolver. In a nutshell, we have:","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"PeriodicOrbitTrapBLS = BorderingBLS(solver = AγLinearSolver(), check_precision = false)","category":"page"},{"location":"periodicOrbitTrapeze/#.-BorderedSparseInplace","page":"Trapezoid","title":"6. BorderedSparseInplace","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Same as :BorderedLU but the jacobian is allocated only once and updated inplace. This is much faster than :BorderedLU but the sparsity pattern of dF must be constant.","category":"page"},{"location":"periodicOrbitTrapeze/#.-BorderedMatrixFree","page":"Trapezoid","title":"7. BorderedMatrixFree","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A matrix free linear solver is used but for mathcal J_c only: it means that options.linsolver is used to invert mathcal J_c. ","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"info: Matrix-Free\nThese two Matrix-Free options, :FullMatrixFree and :BorderedMatrixFree, thus expose different part of the jacobian mathcal J in order to use specific preconditioners. For example, an ILU preconditioner on mathcal J_c could remove the constraints in mathcal J and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely be required.","category":"page"},{"location":"periodicOrbitTrapeze/#Floquet-multipliers-computation","page":"Trapezoid","title":"Floquet multipliers computation","text":"","category":"section"},{"location":"periodicOrbitTrapeze/#Default-method","page":"Trapezoid","title":"Default method","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"A not very precise algorithm for computing the Floquet multipliers is provided in the package. The method, dubbed Quick and Dirty (QaD), is not numerically very precise for large / small Floquet exponents because it relies on constructing the monodromy matrix. ","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Note that the computation of the eigenvalues can be iterative or direct based on the eigensolver passed in arguments.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"It amounts to computing the eigenvalues of the monodromy matrix","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"mathcalM=M_1^-1 H_1 M_m-1^-1 H_m-1 cdots M_2^-1 H_2","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The method allows, nevertheless, to detect bifurcations of periodic orbits. It seems to work reasonably well for the tutorials considered here. For more information, have a look at FloquetQaD.","category":"page"},{"location":"periodicOrbitTrapeze/#Most-precise-method","page":"Trapezoid","title":"Most precise method","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The state of the art method is based on a Periodic Schur decomposition. It is available through the package PeriodicSchurBifurcationKit.jl. For more information, have a look at FloquetPQZ.","category":"page"},{"location":"periodicOrbitTrapeze/#Computation-with-newton","page":"Trapezoid","title":"Computation with newton","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We provide a simplified call to newton to locate the periodic orbits. Compared to the regular newton function, there is an additional option linearalgo to select one of the many ways to deal with the above linear problem. The default solver linearalgo is :BorderedLU.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Have a look at the Periodic orbits based on Trapezoidal rule example for the Brusselator for a basic example and at 2d Ginzburg-Landau equation for a more advanced one.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"The docs for this specific newton are located at newton.","category":"page"},{"location":"periodicOrbitTrapeze/#Computation-with-newton-and-deflation","page":"Trapezoid","title":"Computation with newton and deflation","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"We also provide a simplified call to newton to locate the periodic orbit with a deflation operator.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"newton(probPO::PeriodicOrbitTrapProblem,\n\t\torbitguess::vectype,\n\t\tdefOp::DeflationOperator{Tp, Tdot, T, vectype},\n\t\toptions::NewtonPar;\n\t\tkwargs...) where {Tp, Tdot, T, vectype}","category":"page"},{"location":"periodicOrbitTrapeze/#BifurcationKit.newton-Union{Tuple{vectype}, Tuple{T}, Tuple{Tdot}, Tuple{Tp}, Tuple{PeriodicOrbitTrapProblem, vectype, DeflationOperator{Tp, Tdot, T, vectype}, NewtonPar}} where {Tp, Tdot, T, vectype}","page":"Trapezoid","title":"BifurcationKit.newton","text":"newton(probPO, orbitguess, defOp, options; kwargs...)\n\n\nThis function is similar to newton(probPO, orbitguess, options, jacobianPO; kwargs...) except that it uses deflation in order to find periodic orbits different from the ones stored in defOp. We refer to the mentioned method for a full description of the arguments. The current method can be used in the vicinity of a Hopf bifurcation to prevent the Newton-Krylov algorithm from converging to the equilibrium point.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitTrapeze/#Continuation","page":"Trapezoid","title":"Continuation","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"Have a look at the Periodic orbits based on Trapezoidal rule example for the Brusselator. We refer to continuation for more information regarding the arguments.","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"continuation(prob::PeriodicOrbitTrapProblem,\n\t\t\t\torbitguess,\n\t\t\t\talg::BifurcationKit.AbstractContinuationAlgorithm,\n\t\t\t\t_contParams::ContinuationPar;\n\t\t\t\tkwargs...)","category":"page"},{"location":"periodicOrbitTrapeze/#BifurcationKit.continuation-Tuple{PeriodicOrbitTrapProblem, Any, BifurcationKit.AbstractContinuationAlgorithm, ContinuationPar}","page":"Trapezoid","title":"BifurcationKit.continuation","text":"continuation(\n prob,\n orbitguess,\n alg,\n _contParams;\n record_from_solution,\n linear_algo,\n kwargs...\n)\n\n\nThis is the continuation routine for computing a periodic orbit using a functional G based on Finite Differences and a Trapezoidal rule.\n\nArguments\n\nprob::PeriodicOrbitTrapProblem encodes the functional G\norbitguess a guess for the periodic orbit where orbitguess[end] is an estimate of the period of the orbit. It could be a vector of size N * M + 1 where M is the number of time slices, N is the dimension of the phase space. This must be compatible with the numbers N, M in prob.\nalg continuation algorithm\ncontParams same as for the regular continuation method\n\nKeyword arguments\n\nlinear_algo same as in continuation\n\nSpecify the choice of the jacobian (and linear algorithm), jacobian must belong to [:FullLU, :FullSparseInplace, :Dense, :DenseAD, :BorderedLU, :BorderedSparseInplace, :FullMatrixFree, :BorderedMatrixFree, :FullMatrixFreeAD]. This is used to select a way of inverting the jacobian dG of the functional G.\n\nFor jacobian = :FullLU, we use the default linear solver based on a sparse matrix representation of dG. This matrix is assembled at each newton iteration. This is the default algorithm.\nFor jacobian = :FullSparseInplace, this is the same as for :FullLU but the sparse matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :FullLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :Dense, same as above but the matrix dG is dense. It is also updated inplace. This option is useful to study ODE of small dimension.\nFor jacobian = :DenseAD, evaluate the jacobian using ForwardDiff\nFor jacobian = :BorderedLU, we take advantage of the bordered shape of the linear solver and use a LU decomposition to invert dG using a bordered linear solver.\nFor jacobian = :BorderedSparseInplace, this is the same as for :BorderedLU but the cyclic matrix dG is updated inplace. This method allocates much less. In some cases, this is significantly faster than using :BorderedLU. Note that this method can only be used if the sparsity pattern of the jacobian is always the same.\nFor jacobian = :FullMatrixFree, a matrix free linear solver is used for dG: note that a preconditioner is very likely required here because of the cyclic shape of dG which affects negatively the convergence properties of GMRES.\nFor jacobian = :BorderedMatrixFree, a matrix free linear solver is used but for Jc only (see docs): it means that options.linsolver is used to invert Jc. These two Matrix-Free options thus expose different part of the jacobian dG in order to use specific preconditioners. For example, an ILU preconditioner on Jc could remove the constraints in dG and lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required.\nFor jacobian = :FullMatrixFreeAD, the evaluation map of the differential is derived using automatic differentiation. Thus, unlike the previous two cases, the user does not need to pass a Matrix-Free differential.\n\nNote that by default, the method prints the period of the periodic orbit as function of the parameter. This can be changed by providing your record_from_solution argument.\n\n\n\n\n\n","category":"method"},{"location":"periodicOrbitTrapeze/#References","page":"Trapezoid","title":"References","text":"","category":"section"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"[Uecker]: Uecker, Hannes. Hopf Bifurcation and Time Periodic Orbits with Pde2path – Algorithms and Applications. Communications in Computational Physics 25, no. 3 (2019)","category":"page"},{"location":"periodicOrbitTrapeze/","page":"Trapezoid","title":"Trapezoid","text":"[Lust]: Lust, Kurt, Numerical Bifurcation Analysis of Periodic Solutions of Partial Differential Equations, PhD thesis, 1997.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#pdlure","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"Pages = [\"tutorialsODE-PD.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"The following model is an adaptive control system of Lur’e type. It is an example from the MatCont library.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"leftbeginarrayl\ndotx=y \ndoty=z \ndotz=-alpha z-beta y-x+x^2\nendarrayright","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"The model is interesting because there is a period doubling bifurcation and we want to show the branch switching capabilities of BifurcationKit.jl in this case. We provide 3 different ways to compute this periodic orbits and highlight their pro / cons.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"It is easy to encode the ODE as follows","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"using Revise, Parameters, Plots\nusing BifurcationKit\nconst BK = BifurcationKit\n\nrecordFromSolution(x, p) = (u1 = x[1], u2 = x[2])\n\nfunction lur!(dz, u, p, t = 0)\n\t@unpack α, β = p\n\tx, y, z = u\n\tdz[1] = y\n\tdz[2] =\tz\n\tdz[3] = -α * z - β * y - x + x^2\n\tdz\nend\n\n# parameters\npar_lur = (α = -1.0, β = 1.)\n\n# initial guess\nz0 = zeros(3)\n\n# bifurcation problem\nprob = BifurcationProblem(lur!, z0, par_lur, (@lens _.α);\n record_from_solution = recordFromSolution)\nnothing #hide","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We first compute the branch of equilibria","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# continuation options\nopts_br = ContinuationPar(p_min = -1.4, p_max = 1.8, dsmax = 0.01, max_steps = 1000)\n\n# computation of the branch\nbr = continuation(prob, PALC(), opts_br)\n\nscene = plot(br)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"With detailed information:","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"br","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We note the Hopf bifurcation point which we shall investigate now.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#Branch-of-periodic-orbits-with-finite-differences","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"Branch of periodic orbits with finite differences","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We compute the branch of periodic orbits from the Hopf bifurcation point. We first define a plotting function and a record function which are used for all cases below:","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# plotting function\nfunction plotPO(x, p; k...)\n\txtt = get_periodic_orbit(p.prob, x, p.p)\n\tplot!(xtt.t, xtt[1,:]; markersize = 2, k...)\n\tplot!(xtt.t, xtt[2,:]; k...)\n\tplot!(xtt.t, xtt[3,:]; legend = false, k...)\nend\n\n# record function\nfunction recordPO(x, p)\n\txtt = get_periodic_orbit(p.prob, x, p.p)\n\tperiod = getperiod(p.prob, x, p.p)\n\treturn (max = maximum(xtt[1,:]), min = minimum(xtt[1,:]), period = period)\nend","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We use finite differences to discretize the problem for finding periodic orbits. We appeal to automatic branch switching as follows","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.02, ds= 0.01, dsmin = 1e-4, p_max = 1.1, max_steps = 80, tol_stability = 1e-4)\n\nMt = 120 # number of time sections\nbr_po = continuation(\n\tbr, 1, opts_po_cont,\n\tPeriodicOrbitTrapProblem(M = Mt);\n\trecord_from_solution = recordPO,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## plot previous branch\n\t\tplot!(br, subplot=1, putbifptlegend = false)\n\t\tend,\n\tnormC = norminf)\n\nscene = plot(br, br_po)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"Two period doubling bifurcations were detected. We shall now compute the branch of periodic orbits from these PD points. We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# aBS from PD\nbr_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40);\n\tplot = true,\n\tampfactor = .2, δp = -0.005,\n\tusedeflation = true,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## add previous branch\n\t\tplot!(br_po; legend=false, subplot=1)\n\tend,\n\trecord_from_solution = recordPO,\n\tnormC = norminf\n\t)\nScene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"plot(br, br_po, br_po_pd)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#Periodic-orbits-with-Parallel-Standard-Shooting","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"Periodic orbits with Parallel Standard Shooting","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We use a different method to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl. This way of computing periodic orbits should be more precise than the previous one. We use a particular instance called multiple shooting which is computed in parallel. This is an additional advantage compared to the previous method. Finally, please note the close similarity to the code of the previous part. As before, we first rely on Hopf aBS.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"using DifferentialEquations\n\n# ODE problem for using DifferentialEquations\nprobsh = ODEProblem(lur!, copy(z0), (0., 1000.), par_lur; abstol = 1e-11, reltol = 1e-9)\n\n# continuation parameters\nopts_po_cont = ContinuationPar(dsmax = 0.02, ds= -0.001, dsmin = 1e-4, max_steps = 130, tol_stability = 1e-5,plot_every_step = 10)\n\nbr_po = continuation(\n\tbr, 1, opts_po_cont,\n\t# parallel shooting functional with 15 sections\n\tShootingProblem(15, probsh, Rodas5(); parallel = true);\n\tplot = true,\n\trecord_from_solution = recordPO,\n\tplot_solution = plotPO,\n\t# limit the residual, useful to help DifferentialEquations\n\tcallback_newton = BK.cbMaxNorm(10),\n\tnormC = norminf)\n\nscene = title!(\"\")","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# aBS from PD\nbr_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40, dsmax = 0.01, plot_every_step = 10, ds = 0.01);\n\tplot = true,\n\tampfactor = .1, δp = -0.005,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## add previous branch\n\t\tplot!(br_po; subplot = 1)\n\tend,\n\trecord_from_solution = recordPO,\n\tnormC = norminf,\n\tcallback_newton = BK.cbMaxNorm(10),\n\t)\n\nscene = plot(br, br_po, br_po_pd)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/#Periodic-orbits-with-orthogonal-collocation","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"Periodic orbits with orthogonal collocation","text":"","category":"section"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We now rely on a the state of the art method for computing periodic orbits of ODE: orthogonal collocation.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# continuation parameters\nopts_po_cont = ContinuationPar(opts_br, dsmax = 0.03, ds = 0.01, dsmin = 1e-4, max_steps = 70, tol_stability = 1e-4, plot_every_step = 20)\n\nbr_po = continuation(\n\tbr, 1, opts_po_cont,\n\tPeriodicOrbitOCollProblem(40, 4);\n\tplot = true,\n\trecord_from_solution = recordPO,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## plot previous branch\n\t\tplot!(br, subplot=1, putbifptlegend = false)\n\t\tend,\n\tnormC = norminf)\n\nscene = plot(br, br_po)","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.","category":"page"},{"location":"tutorials/ode/tutorialsODE-PD/","page":"🟡 Period doubling in Lur'e problem (PD aBS)","title":"🟡 Period doubling in Lur'e problem (PD aBS)","text":"# aBS from PD\nbr_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 80, dsmax = 0.02, plot_every_step = 10);\n\tplot = true,\n\tampfactor = .3, δp = -0.005,\n\tplot_solution = (x, p; k...) -> begin\n\t\tplotPO(x, p; k...)\n\t\t## add previous branch\n\t\tplot!(br_po; subplot = 1)\n\tend,\n\trecord_from_solution = recordPO,\n\tnormC = norminf,\n\tcallback_newton = BK.cbMaxNorm(10),\n\t)\n\nscene = plot(br_po, br_po_pd)","category":"page"},{"location":"tutorials/tutorialCarrier/#carrier","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"","category":"section"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"unknown: References\nChapman, S. J., and P. E. Farrell. Analysis of Carrier’s Problem. ArXiv:1609.08842 [Math], September 28, 2016. http://arxiv.org/abs/1609.08842.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"In this example, we study the following singular perturbation problem:","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"epsilon^2 y^prime prime+2left(1-x^2right) y+y^2=1 quad y(-1)=y(1)=0tagE","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"It is a remarkably difficult problem which presents many disconnected branches which are not amenable to the classical continuation methods. We thus use the recently developed deflated continuation method which builds upon the Deflated Newton (see Deflated problems) techniques to find solutions which are different from a set of already known solutions.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We start with some import","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"using Revise\nusing LinearAlgebra, Parameters, Setfield, SparseArrays, BandedMatrices\n\nusing BifurcationKit, Plots\nconst BK = BifurcationKit","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"and a discretization of the problem","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"function F_carr(x, p)\n\t@unpack ϵ, X, dx = p\n\tf = similar(x)\n\tn = length(x)\n\tf[1] = x[1]\n\tf[n] = x[n]\n\tfor i=2:n-1\n\t\tf[i] = ϵ^2 * (x[i-1] - 2 * x[i] + x[i+1]) / dx^2 +\n\t\t\t2 * (1 - X[i]^2) * x[i] + x[i]^2-1\n\tend\n\treturn f\nend\n\nfunction Jac_carr(x, p)\n\t@unpack ϵ, X, dx = p\n\tn = length(x)\n\tJ = BandedMatrix{Float64}(undef, (n,n), (1,1))\n\tJ[band(-1)] .= ϵ^2/dx^2 \t\t\t\t\t\t\t\t\t# set the diagonal band\n\tJ[band(1)] .= ϵ^2/dx^2\t\t\t\t\t\t\t\t\t\t# set the super-diagonal band\n\tJ[band(0)] .= (-2ϵ^2 /dx^2) .+ 2 * (1 .- X.^2) .+ 2 .* x # set the second super-diagonal band\n\tJ[1, 1] = 1.0\n\tJ[n, n] = 1.0\n\tJ[1, 2] = 0.0\n\tJ[n, n-1] = 0.0\n\tJ\nend","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We can now use Newton to find solutions:","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"N = 200\nX = LinRange(-1,1,N)\ndx = X[2] - X[1]\npar_car = (ϵ = 0.7, X = X, dx = dx)\nsol0 = -(1 .- par_car.X.^2)\n\nrecordFromSolution(x, p) = (x[2]-x[1]) * sum(x->x^2, x)\n\nprob = BifurcationProblem(F_carr, zeros(N), par_car, (@lens _.ϵ); J = Jac_carr, record_from_solution = recordFromSolution)\n\noptnew = NewtonPar(tol = 1e-8, verbose = true)\n\tsol = @time newton(prob, optnew, normN = norminf)\nnothing #hide","category":"page"},{"location":"tutorials/tutorialCarrier/#First-try-with-automatic-bifurcation-diagram","page":"🟡 Deflated Continuation in the Carrier Problem","title":"First try with automatic bifurcation diagram","text":"","category":"section"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We can start by using our Automatic bifurcation method.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"\noptcont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= -0.01, p_min = 0.05, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, max_iterations = 20, verbose = true), max_steps = 300, detect_bifurcation = 3, nev = 40)\n\ndiagram = bifurcationdiagram(prob,\n # particular bordered linear solver to use\n\t# BandedMatrices.\n PALC(bls = BorderingBLS(solver = DefaultLS(), check_precision = false)),\n 2,\n\t(arg...) -> @set optcont.newton_options.verbose = false;\n\tplot = false)\n\nscene = plot(diagram)","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"However, this is a bit disappointing as we only find two branches.","category":"page"},{"location":"tutorials/tutorialCarrier/#Second-try-with-deflated-continuation","page":"🟡 Deflated Continuation in the Carrier Problem","title":"Second try with deflated continuation","text":"","category":"section"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"# deflation operator to hold solutions\ndeflationOp = DeflationOperator(2, dot, 1.0, [sol.u])\n\n# parameter values for the problem\npar_def = @set par_car.ϵ = 0.6\n\n# newton options\noptdef = setproperties(optnew; tol = 1e-7, max_iterations = 200)\n\n# function to encode a perturbation of the old solutions\nfunction perturbsol(sol, p, id)\n\t# we use this sol0 for the boundary conditions\n\tsol0 = @. exp(-.01/(1-par_car.X^2)^2)\n\tsolp = 0.02*rand(length(sol))\n\treturn sol .+ solp .* sol0\nend\n\n# encode the deflated continuation algo\nalg = DefCont(deflation_operator = deflationOp, perturb_solution = perturbsol, max_branches = 40)\n\n# call the deflated continuation method\nbr = @time continuation(\n\tre_make(prob; params = par_def), alg,\n\tsetproperties(optcont; ds = -0.00021, dsmin=1e-5, max_steps = 20000,\n\t\tp_max = 0.7, p_min = 0.05, detect_bifurcation = 0, plot_every_step = 40,\n\t\tnewton_options = setproperties(optnew; tol = 1e-9, max_iterations = 100, verbose = false));\n\tnormN = x -> norm(x, Inf),\n verbosity = 0,\n\t)\n\nplot(br...)","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"We obtain the following result which is remarkable because it contains many more disconnected branches which we did not find in the first try.","category":"page"},{"location":"tutorials/tutorialCarrier/","page":"🟡 Deflated Continuation in the Carrier Problem","title":"🟡 Deflated Continuation in the Carrier Problem","text":"(Image: )","category":"page"},{"location":"hh/#Normal-form-of-the-Hopf-Hopf-bifurcation","page":"Hopf-Hopf","title":"Normal form of the Hopf-Hopf bifurcation","text":"","category":"section"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"We follow the paper[Kuznetsov],[Kuznetsov2] and consider a Cauchy problem","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"dot x=mathbf F(xp)","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"We denote by mathbf L the jacobian of mathbf F at the bifurcation point (x_0p_0). We choose a basis such that:","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"mathbf L q_1=i omega_1 q_1 quad mathbf L q_2=i omega_2 q_2","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"Under some conditions, x(t)approx x_0+2Re w_1(t)q_1+2Re w_2(t)q_2 where w_i satisfy the normal form:","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"leftbeginaligned\ndotw_1= i omega_1 w_1+frac12 G_2100 w_1leftw_1right^2+G_1011 w_1leftw_2right^2 \n +frac112 G_3200 w_1leftw_1right^4+frac12 G_2111 w_1leftw_1right^2leftw_2right^2+frac14 G_1022 w_1leftw_2right^4 \n +Oleft(leftleft(w_1 barw_1 w_2 barw_2right)right^6right) \ndotw_2= i omega_2 w_2+G_1110 w_2leftw_1right^2+frac12 G_0021 w_2leftw_2right^2 +frac14 G_2210 w_2leftw_1right^4+frac12 G_1121 w_2leftw_1right^2leftw_2right^2+frac112 G_0032 w_2leftw_2right^4 \n +Oleft(leftleft(w_1 barw_1 w_2 barw_2right)right^6right)\nendalignedrighttagE","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"This normal form is usually computed in order to branch from a Hopf-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the G_ijkl is returned.","category":"page"},{"location":"hh/#Normal-form-computation","page":"Hopf-Hopf","title":"Normal form computation","text":"","category":"section"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"The normal form (E) can be automatically computed as follows","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type HopfHopf.","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"info: Note\nYou should not need to call get_normal_form except if you need the full information about the branch point.","category":"page"},{"location":"hh/#References","page":"Hopf-Hopf","title":"References","text":"","category":"section"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"[Kuznetsov]: Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.","category":"page"},{"location":"hh/","page":"Hopf-Hopf","title":"Hopf-Hopf","text":"[Kuznetsov2]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.","category":"page"},{"location":"interfacePred/#Interface-for-Predictor-/-Corrector","page":"Predictor / corrector","title":"Interface for Predictor / Corrector","text":"","category":"section"},{"location":"interfacePred/","page":"Predictor / corrector","title":"Predictor / corrector","text":"Here is a description of the interface that is used to specify predictor / corrector for continuation methods. The type must be a subtype of the abstract type AbstractTangentPredictor.","category":"page"},{"location":"interfacePred/","page":"Predictor / corrector","title":"Predictor / corrector","text":"In the table below, we assume it::AbstractContinuationIterable and M = BorderedArray","category":"page"},{"location":"interfacePred/","page":"Predictor / corrector","title":"Predictor / corrector","text":"Required methods Brief description\ngetPredictor!(z_pred::M, z_old::M, τ::M, ds, pred::AbstractTangentPredictor, nrm = false) Write in z_pred a prediction for the new Newton guess given the current solution z_old, tangent τ and arc length ds.\ngetTangent!(τ::M, z_new::M, z_old::M, it, ds, θ, pred:: AbstractTangentPredictor, verbosity) Generate an estimate of the tangent to the branch of solutions at positions z_new, z_old\ncorrector(it, z_old::M, τ::M, z_pred::M, ds, θ, pred::AbstractTangentPredictor, linearalgo; normC = norm, callback = cbDefault, kwargs...) Correct the guess z_pred. Must return a tuple (sol, residuals, isconverged, it numbers, itlinear)\nOptional methods Brief description\nBase.empty!(pred::AbstractTangentPredictor) Reset the predictor","category":"page"},{"location":"modulated_wave_fd/#Modulated-waves-with-Trapezoid-method","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"","category":"section"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"This section is dedicated to the computation of modulated waves based on the Trapezoid method. Given a Cauchy problem fracdxdt = F(x)tagE we have reduced the symmetries by considering","category":"page"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"left\nbeginarrayl\nF(x p) - scdot Tcdot x=0 \nlangle Tcdot x_refx-x_refrangle=0\nendarrayrighttagFE","category":"page"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"This provides a travelling wave solution $","category":"page"},{"location":"modulated_wave_fd/#References","page":"Modulated waves with Trapezoid method","title":"References","text":"","category":"section"},{"location":"modulated_wave_fd/","page":"Modulated waves with Trapezoid method","title":"Modulated waves with Trapezoid method","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"tutorials/tutorialsCGL/#cgl","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Pages = [\"tutorialsCGL.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"This example is also treated in the MATLAB library pde2path.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We look at the Ginzburg-Landau equations in 2d. The code is very similar to the Brusselator example except that some special care has to be taken in order to cope with the \"high\" dimensionality of the problem.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Note that we try to be pedagogical here. Hence, we may write \"bad\" code that we improve later. Finally, we could use all sort of tricks to take advantage of the specificity of the problem. Rather, we stay quite close to the example in the MATLAB library pde2path (and discussed in Hopf Bifurcation and Time Periodic Orbits with Pde2path – Algorithms and Applications., Uecker, Hannes, Communications in Computational Physics 25, no. 3 (2019)) for fair comparison.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"info: Goal\nWe do not use automatic branch switching here. The goal is to show our to use the internals of the package to squeeze most of the performances, use tailored options...","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The equations are as follows","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"partial_t u=Delta u+(r+mathrmi v) u-left(c_3+mathrmi muright)u^2 u-c_5u^4 u+gamma quad u=u(t x) in mathbbCquad gammainmathbb R","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"with Dirichlet boundary conditions. We discretize the square Omega = (0L_x)times(0L_y) with 2N_xN_y points. We start by writing the Laplacian:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\n\nnorminf(x) = norm(x, Inf)\n\nfunction Laplacian2D(Nx, Ny, lx, ly)\n\thx = 2lx/Nx; hy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Dirichlet0BC(typeof(hx))\n\tQy = Dirichlet0BC(typeof(hy))\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"It is then straightforward to write the vector field","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# this encodes the nonlinearity\nfunction NL(u, p)\n\t@unpack r, μ, ν, c3, c5, γ = p\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf = similar(u)\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@. f1 .= r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1 + γ\n\t@. f2 .= r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\n\treturn f\nend\n\nfunction Fcgl(u, p)\n\tf = similar(u)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and its jacobian:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"function Jcgl(u, p)\n\t@unpack r, μ, ν, c3, c5, Δ = p\n\n\tn = div(length(u), 2)\n\tu1 = @view u[1:n]\n\tu2 = @view u[n+1:2n]\n\n\tua = u1.^2 .+ u2.^2\n\n\tf1u = zero(u1)\n\tf2u = zero(u1)\n\tf1v = zero(u1)\n\tf2v = zero(u1)\n\n\t@. f1u = r - 2 * u1 * (c3 * u1 - μ * u2) - c3 * ua - 4 * c5 * ua * u1^2 - c5 * ua^2\n\t@. f1v = -ν - 2 * u2 * (c3 * u1 - μ * u2) + μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2u = ν - 2 * u1 * (c3 * u2 + μ * u1) - μ * ua - 4 * c5 * ua * u1 * u2\n\t@. f2v = r - 2 * u2 * (c3 * u2 + μ * u1) - c3 * ua - 4 * c5 * ua * u2 ^2 - c5 * ua^2\n\n\tjacdiag = vcat(f1u, f2v)\n\n\tΔ + spdiagm(0 => jacdiag, n => f1v, -n => f2u)\nend\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We now define the parameters and the stationary solution:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Nx = 41\nNy = 21\nn = Nx * Ny\nlx = pi\nly = pi/2\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)\npar_cgl = (r = 0.5, μ = 0.1, ν = 1.0, c3 = -1.0, c5 = 1.0, Δ = blockdiag(Δ, Δ), γ = 0.)\nsol0 = zeros(2Nx, Ny)\n\n# we make a problem\nprob = BK.BifurcationProblem(Fcgl, vec(sol0), par_cgl, (@lens _.r); J = Jcgl)\nnothing #hide","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and we continue it to find the Hopf bifurcation points. We use a Shift-Invert eigensolver.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# Shift-Invert eigensolver\neigls = EigArpack(1.0, :LM) # shift = 1.0\nopt_newton = NewtonPar(tol = 1e-10, verbose = true, eigsolver = eigls)\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.005, ds = 0.001, p_max = 2., detect_bifurcation = 3, nev = 5, plot_every_step = 50, newton_options = opt_newton, max_steps = 1060)\n\nbr = continuation(prob, PALC(), opts_br)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"scene = plot(br, ylims=(-0.1,0.1))","category":"page"},{"location":"tutorials/tutorialsCGL/#Normal-form-computation","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Normal form computation","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We compute the Hopf normal form of the first bifurcation point.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"hopfpt = get_normal_form(br, 1)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"So the Hopf branch is subcritical.","category":"page"},{"location":"tutorials/tutorialsCGL/#Codim-2-Hopf-continuation","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Codim 2 Hopf continuation","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Having detected 2 hopf bifurcation points, we now continue them in the plane (gamma r).","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Before we start the codim 2 continuation, we tell BifurcationKit.jl to use the spectral information start_with_eigen = true because the left eigenvector of the Jacobian is simply not the conjugate of the right one.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# we perform Hopf continuation of the first Hopf point in br\nind_hopf = 1\nbr_hopf = @time continuation(\n\tbr, ind_hopf, (@lens _.γ),\n\tContinuationPar(dsmin = 0.001, dsmax = 0.02, ds= 0.01, p_max = 6.5, p_min = -10., newton_options = opts_br.newton_options, detect_bifurcation = 1); plot = true,\n\tupdate_minaug_every_step = 1,\n\tnormC = norminf,\n\tdetect_codim2_bifurcation = 2,\n\tstart_with_eigen = true,\n\tjacobian_ma = :minaug, # specific to high dimensions\n\tbdlinsolver = BorderingBLS(solver = DefaultLS(), check_precision = false))\n\nplot(br_hopf, branchlabel = \"Hopf curve\", legend = :topleft)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"with detailed information","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"br_hopf","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now construct the curve of Fold points branching off the Bogdanov-Takens bifurcation we just detected.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# find the index of the BT point\nindbt = findfirst(x -> x.type == :bt, br_hopf.specialpoint)\n# branch from the BT point\nbrfold = continuation(br_hopf, indbt, setproperties(br_hopf.contparams; detect_bifurcation = 1, max_steps = 20);\n\tupdate_minaug_every_step = 1,\n\tdetect_codim2_bifurcation = 2,\n\tcallback_newton = BK.cbMaxNorm(1e5),\n\tbdlinsolver = BorderingBLS(solver = DefaultLS(), check_precision = false),\n\tjacobian_ma = :minaug, # specific to high dimensions\n\tbothside = true, normC = norminf)\n\nplot(br_hopf, branchlabel = \"Hopf\"); plot!(brfold, legend = :topleft, branchlabel = \"Fold\")","category":"page"},{"location":"tutorials/tutorialsCGL/#Periodic-orbits-continuation-with-stability","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Periodic orbits continuation with stability","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Having found two Hopf bifurcation points, we aim at computing the periodic orbits branching from them. Like for the Brusselator example, we need to find some educated guess for the periodic orbits in order to have a successful Newton call.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The following code is very close to the one explained in the tutorial 1d Brusselator (advanced user) so we won't give too much details here.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We focus on the first Hopf bifurcation point. Note that, we do not improve the guess for the Hopf bifurcation point, e.g. by calling newtonHopf, as this is not really needed.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# index of the Hopf point we want to branch from\nind_hopf = 1\n\n# number of time slices in the periodic orbit\nM = 30\n\n# periodic orbit initial guess from Hopf point\nr_hopf, Th, orbitguess2, hopfpt, eigvec = guess_from_hopf(br, ind_hopf, opt_newton.eigsolver,\n\t# we pass the number of time slices M, the amplitude 22*sqrt(0.1) and phase\n\tM, 22*sqrt(0.1); phase = 0.25)\n\n# flatten the initial guess\norbitguess_f2 = reduce(hcat, orbitguess2)\norbitguess_f = vcat(vec(orbitguess_f2), Th) |> vec","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We create a problem to hold the functional and compute Periodic orbits based on Trapezoidal rule","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"poTrap = PeriodicOrbitTrapProblem(\n# vector field and sparse Jacobian\n\tre_make(prob, params = (@set par_cgl.r = r_hopf - 0.01)),\n# parameters for the phase condition\n\treal.(eigvec),\n\thopfpt.u,\n# number of time slices\n\tM,\n# space dimension\n\t2n,\n# jacobian of the periodic orbit functional\n jacobian = :FullMatrixFree)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can use this (family) problem poTrap with newton on our periodic orbit guess to find a periodic orbit. Hence, one can be tempted to use","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"danger: Don't run this!!\nIt uses too much memoryopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.03, ds= 0.001, p_max = 2.5, max_steps = 250, plot_every_step = 3, newton_options = (@set opt_po.linsolver = DefaultLS()))\nbr_po = @time continuation(poTrap, vec(sol0), PALC(), opts_po_cont)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"However, the linear system associated to the newton iterations will be solved by forming the sparse jacobian of size (2N_xN_yM+1)^2 and the use of \\ (based on LU decomposition). It takes way too much time and memory.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Instead, we use a preconditioner. We build the jacobian once, compute its incomplete LU decomposition (ILU) and use it as a preconditioner.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using IncompleteLU\n\n# Sparse matrix representation of the jacobian of the periodic orbit functional\nJpo = poTrap(Val(:JacFullSparse), orbitguess_f, @set par_cgl.r = r_hopf - 0.01)\n\n# incomplete LU factorization with threshold\nPrecilu = @time ilu(Jpo, τ = 0.005);\n\n# we define the linear solver with left preconditioner Precilu\nls = GMRESIterativeSolvers(verbose = false, reltol = 1e-3, N = size(Jpo,1), restart = 40, maxiter = 50, Pl = Precilu, log=true)\n\n# we try the linear solver\nls(Jpo, rand(ls.N))","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"This converges in 7 iterations whereas, without the preconditioner, it does not converge after 100 iterations.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We set the parameters for the newton solve.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"opt_po = @set opt_newton.verbose = true\noutpo_f = @time newton(poTrap, orbitguess_f, (@set opt_po.linsolver = ls); normN = norminf)\nBK.converged(outpo_f) && printstyled(color=:red, \"--> T = \", outpo_f.u[end], \", amplitude = \", BK.amplitude(outpo_f.u, Nx*Ny, M; ratio = 2),\"\\n\")\nBK.plotPeriodicPOTrap(outpo_f.u, M, Nx, Ny; ratio = 2);","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.5432e-03 │ 0 │\n│ 1 │ 1.4372e-03 │ 8 │\n│ 2 │ 3.6731e-04 │ 8 │\n│ 3 │ 6.5658e-05 │ 9 │\n│ 4 │ 4.3028e-06 │ 10 │\n│ 5 │ 6.4509e-08 │ 11 │\n│ 6 │ 2.9713e-10 │ 12 │\n│ 7 │ 2.2181e-13 │ 14 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.780986 seconds (132.31 k allocations: 1.237 GiB, 12.13% gc time)\n--> T = 6.532023020978835, amplitude = 0.2684635643839235","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"At this point, we are still wasting a lot of resources, because the matrix-free version of the jacobian of the functional uses the jacobian of the vector field x -> Jcgl(x, p). Hence, it builds M sparse matrices for each evaluation!! Let us create a problem which is fully Matrix Free:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# computation of the first derivative using automatic differentiation\nd1Fcgl(x, p, dx) = ForwardDiff.derivative(t -> Fcgl(x .+ t .* dx, p), 0.)\n\n# linear solver for solving Jcgl*x = rhs. Needed for Floquet multipliers computation\nls0 = GMRESIterativeSolvers(N = 2Nx*Ny, reltol = 1e-9, Pl = lu(I + par_cgl.Δ))\n\npoTrapMF = PeriodicOrbitTrapProblem(\n# vector field and sparse Jacobian\n\tre_make(prob, params = (@set par_cgl.r = r_hopf - 0.01), J = (x, p) -> (dx -> d1Fcgl(x, p, dx))),\n# parameters for the phase condition\n\treal.(eigvec),\n\thopfpt.u,\n# number of time slices\n\tM,\n# space dimension\n\t2n,\n ls0,\n# jacobian of the periodic orbit functional\n jacobian = :FullMatrixFree)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now use newton","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"outpo_f = @time newton(poTrapMF, orbitguess_f, (@set opt_po.linsolver = ls); normN = norminf)\nBK.converged(outpo_f) && printstyled(color=:red, \"--> T = \", outpo_f.u[end], \", amplitude = \", BK.amplitude(outpo_f.u, Nx*Ny, M; ratio = 2),\"\\n\")","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.5432e-03 │ 0 │\n│ 1 │ 1.4372e-03 │ 8 │\n│ 2 │ 3.6731e-04 │ 8 │\n│ 3 │ 6.5658e-05 │ 9 │\n│ 4 │ 4.3028e-06 │ 10 │\n│ 5 │ 6.4509e-08 │ 11 │\n│ 6 │ 2.9713e-10 │ 12 │\n│ 7 │ 2.2188e-13 │ 14 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.322440 seconds (35.03 k allocations: 459.996 MiB, 7.63% gc time)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The speedup will increase a lot for larger N_x N_y. Also, for Floquet multipliers computation, the speedup will be substantial.","category":"page"},{"location":"tutorials/tutorialsCGL/#Removing-most-allocations-(Advanced-and-Experimental)","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Removing most allocations (Advanced and Experimental)","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We show here how to remove most allocations and speed up the computations. This is an experimental feature as the Floquet multipliers computation is not yet readily available in this case. To this end, we rewrite the functional using inplace formulation and trying to avoid allocations. This can be done as follows:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# compute just the nonlinearity\nfunction NL!(f, u, p, t = 0.)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1v = @view u[1:n]\n\tu2v = @view u[n+1:2n]\n\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@inbounds for ii = 1:n\n\t\tu1 = u1v[ii]\n\t\tu2 = u2v[ii]\n\t\tua = u1^2+u2^2\n\t\tf1[ii] = r * u1 - ν * u2 - ua * (c3 * u1 - μ * u2) - c5 * ua^2 * u1\n\t\tf2[ii] = r * u2 + ν * u1 - ua * (c3 * u2 + μ * u1) - c5 * ua^2 * u2\n\tend\n\treturn f\nend\n\n# derivative of the nonlinearity\nfunction dNL!(f, u, p, du)\n\t@unpack r, μ, ν, c3, c5 = p\n\tn = div(length(u), 2)\n\tu1v = @view u[1:n]\n\tu2v = @view u[n+1:2n]\n\n\tdu1v = @view du[1:n]\n\tdu2v = @view du[n+1:2n]\n\n\tf1 = @view f[1:n]\n\tf2 = @view f[n+1:2n]\n\n\t@inbounds for ii = 1:n\n\t\tu1 = u1v[ii]\n\t\tu2 = u2v[ii]\n\t\tdu1 = du1v[ii]\n\t\tdu2 = du2v[ii]\n\t\tua = u1^2+u2^2\n\t\tf1[ii] = (-5*c5*u1^4 + (-6*c5*u2^2 - 3*c3)*u1^2 + 2*μ*u1*u2 - c5*u2^4 - c3*u2^2 + r) * du1 +\n\t\t(-4*c5*u2*u1^3 + μ*u1^2 + (-4*c5*u2^3 - 2*c3*u2)*u1 + 3*u2^2*μ - ν) * du2\n\n\t\tf2[ii] = (-4*c5*u2*u1^3 - 3*μ*u1^2 + (-4*c5*u2^3 - 2*c3*u2)*u1 - u2^2*μ + ν) * du1 + (-c5*u1^4 + (-6*c5*u2^2 - c3)*u1^2 - 2*μ*u1*u2 - 5*c5*u2^4 - 3*c3*u2^2 + r) * du2\n\tend\n\n\treturn f\nend\n\n# inplace vector field\nfunction Fcgl!(f, u, p, t = 0.)\n\tNL!(f, u, p)\n\tmul!(f, p.Δ, u, 1., 1.)\nend\n\n# inplace derivative of the vector field\nfunction dFcgl!(f, x, p, dx)\n\tdNL!(f, x, p, dx)\n\tmul!(f, p.Δ, dx, 1., 1.)\nend\n\n# we create a problem inplace\nprobInp = BifurcationProblem(Fcgl!, vec(sol0), (@set par_cgl.r = r_hopf - 0.01), (@lens _.r); J = dFcgl!, inplace = true)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now define an inplace functional","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"ls0 = GMRESIterativeSolvers(N = 2Nx*Ny, reltol = 1e-9)#, Pl = lu(I + par_cgl.Δ))\n\npoTrapMFi = PeriodicOrbitTrapProblem(\n# vector field and sparse Jacobian\n\tprobInp,\n# parameters for the phase condition\n\treal.(eigvec),\n\thopfpt.u,\n# number of time slices\n\tM,\n# space dimension\n\t2n,\n ls0,\n# jacobian of the periodic orbit functional\n jacobian = :FullMatrixFree)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and run the newton method:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"outpo_f = @time newton(poTrapMFi, orbitguess_f, (@set opt_po.linsolver = ls); normN = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"It gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 6.5432e-03 │ 0 │\n│ 1 │ 1.4372e-03 │ 8 │\n│ 2 │ 3.6731e-04 │ 8 │\n│ 3 │ 6.5658e-05 │ 9 │\n│ 4 │ 4.3028e-06 │ 10 │\n│ 5 │ 6.4509e-08 │ 11 │\n│ 6 │ 2.9713e-10 │ 12 │\n│ 7 │ 2.2143e-13 │ 14 │\n└─────────────┴──────────────────────┴────────────────┘\n 1.179854 seconds (902 allocations: 151.500 MiB)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Notice the small speed boost but the reduced allocations. At this stage, further improvements could target the use of BlockBandedMatrices.jl for the Laplacian operator, etc.","category":"page"},{"location":"tutorials/tutorialsCGL/#Other-linear-formulation","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Other linear formulation","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We could use another way to \"invert\" jacobian of the functional based on bordered techniques. We try to use an ILU preconditioner on the cyclic matrix J_c (see Periodic orbits based on Trapezoidal rule) which has a smaller memory footprint:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Jpo2 = poTrap(Val(:JacCyclicSparse), orbitguess_f, @set par_cgl.r = r_hopf - 0.1)\nPrecilu = @time ilu(Jpo2, τ = 0.005)\nls2 = GMRESIterativeSolvers(verbose = false, reltol = 1e-3, N = size(Jpo2, 1), restart = 30, maxiter = 50, Pl = Precilu, log=true)\n\nopt_po = @set opt_newton.verbose = true\noutpo_f = @time newton((@set poTrapMF.jacobian = :BorderedMatrixFree),\torbitguess_f,\n\t(@set opt_po.linsolver = ls2), normN = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"but it gives:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 3.3298e-03 │ 0 │\n│ 1 │ 9.5088e-03 │ 34 │\n│ 2 │ 1.2807e-03 │ 26 │\n│ 3 │ 7.1393e-05 │ 29 │\n│ 4 │ 4.1625e-07 │ 36 │\n│ 5 │ 1.7924e-09 │ 44 │\n│ 6 │ 6.2725e-13 │ 60 │\n└─────────────┴──────────────────────┴────────────────┘\n 3.479920 seconds (62.64 k allocations: 1009.778 MiB, 5.19% gc time)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Hence, it seems better to use the previous preconditioner.","category":"page"},{"location":"tutorials/tutorialsCGL/#Continuation-of-periodic-solutions","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Continuation of periodic solutions","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now perform continuation of the newly found periodic orbit and compute the Floquet multipliers using Matrix-Free methods.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# set the eigensolver for the computation of the Floquet multipliers\nopt_po = @set opt_po.eigsolver = EigKrylovKit(tol = 1e-3, x₀ = rand(2n), verbose = 2, dim = 25)\n\n# parameters for the continuation\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.02, ds = 0.001, p_max = 2.2, max_steps = 250, plot_every_step = 3, newton_options = (@set opt_po.linsolver = ls),\n\tnev = 5, tol_stability = 1e-7, detect_bifurcation = 0)\n\nbr_po = @time continuation(poTrapMF, outpo_f.u, PALC(),\topts_po_cont;\n\tverbosity = 2,\tplot = true,\n\tlinear_algo = BorderingBLS(solver = ls, check_precision = false),\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_potrap(x, M, Nx, Ny; ratio = 2, kwargs...),\n\trecord_from_solution = (u, p) -> BK.getamplitude(poTrapMF, u, par_cgl; ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"This gives the following bifurcation diagram:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"tip: Improved performances\nAlthough it would be \"cheating\" for fair comparisons with existing packages, there is a trick to compute the bifurcation diagram without using preconditionners. We will not detail it here but it allows to handle the case Nx = 200; Ny = 110; M = 30 and above.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We did not change the preconditioner in the previous example as it does not seem needed. Let us show how to do this nevertheless:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# callback which will be sent to newton.\n# `iteration` in the arguments refers to newton iterations\nfunction callbackPO(state; linsolver = ls, prob = poTrap, p = par_cgl, kwargs...)\n\t@show ls.N keys(kwargs)\n\t# we update the preconditioner every 10 continuation steps\n\tif mod(kwargs[:iterationC], 10) == 9 && state.it == 1\n\t\t@info \"update Preconditioner\"\n\t\tJpo = poTrap(Val(:JacCyclicSparse), state.x, (@set p.r = state.p))\n\t\tPrecilu = @time ilu(Jpo, τ = 0.003)\n\t\tls.Pl = Precilu\n\tend\n\ttrue\nend\n\nbr_po = @time continuation(poTrapMF, outpo_f.u, PALC(),\topts_po_cont;\n\tverbosity = 2,\tplot = true,\n\tcallback_newton = callbackPO,\n\tlinear_algo = BorderingBLS(solver = ls, check_precision = false),\n\tplot_solution = (x, p; kwargs...) -> BK.plot_periodic_potrap(x, M, Nx, Ny; ratio = 2, kwargs...),\n\trecord_from_solution = (u, p) -> BK.getamplitude(poTrapMF, u, par_cgl; ratio = 2), normC = norminf)","category":"page"},{"location":"tutorials/tutorialsCGL/#Continuation-of-Fold-of-periodic-orbits","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Continuation of Fold of periodic orbits","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We continue the Fold point of the first branch of the previous bifurcation diagram in the parameter plane (r c_5). To this end, we need to be able to compute the Hessian of the periodic orbit functional. This is not yet readily available so we turn to automatic differentiation.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using ForwardDiff\n\n# computation of the second derivative of a function f\nfunction d2Fcglpb(f, x, dx1, dx2)\n return ForwardDiff.derivative(t2 -> ForwardDiff.derivative( t1-> f(x .+ t1 .* dx1 .+ t2 .* dx2,), 0.), 0.)\nend","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We select the Fold point from the branch br_po and redefine our linear solver to get the ILU preconditioner tuned close to the Fold point.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"indfold = 2\nfoldpt = foldpoint(br_po, indfold)\n\nJpo = poTrap(Val(:JacFullSparse), orbitguess_f, (@set par_cgl.r = r_hopf - 0.1))\nPrecilu = @time ilu(Jpo, τ = 0.005);\nls = GMRESIterativeSolvers(verbose = false, reltol = 1e-4, N = size(Jpo, 1), restart = 40, maxiter = 60, Pl = Precilu);","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can then use our functional to call newtonFold unlike for a regular function (see Tutorial 1). Indeed, we specify the change the parameters too much to rely on a generic algorithm.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# define a bifurcation problem for the fold\n# this will be made automatic in the future\nprobFold = BifurcationProblem((x, p) -> poTrap(x, p), foldpt, getparams(br), getlens(br);\n\t\t\tJ = (x, p) -> poTrap(Val(:JacFullSparse), x, p),\n\t\t\td2F = (x, p, dx1, dx2) -> d2Fcglpb(z -> poTrap(z, p), x, dx1, dx2))\n\noutfold = @time BK.newton_fold(\n br_po, indfold; #index of the fold point\n prob = probFold,\n\t# we change the linear solver for the one we\n\t# defined above\n\toptions = (@set opt_po.linsolver = ls),\n\tbdlinsolver = BorderingBLS(solver = ls, check_precision = false))\nBK.converged(outfold) && printstyled(color=:red, \"--> We found a Fold Point at α = \", outfold.u.p,\" from \", br_po.specialpoint[indfold].param,\"\\n\")","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and this gives","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 4.5937e-01 │ 0 │\n│ 1 │ 5.6013e-01 │ 20 │\n│ 2 │ 3.1385e-02 │ 23 │\n│ 3 │ 6.0620e-05 │ 29 │\n│ 4 │ 2.7839e-08 │ 39 │\n│ 5 │ 8.1593e-12 │ 45 │\n└─────────────┴──────-───────────────┴────────────────┘\n 27.289005 seconds (1.07 M allocations: 24.444 GiB, 10.12% gc time)\n--> We found a Fold Point at α = 0.9470569704262517 from 0.9481896723164748","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Finally, one can perform continuation of the Fold bifurcation point as follows CA NE MARCHE PAS","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"optcontfold = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 40.1, p_min = -10., newton_options = (@set opt_po.linsolver = ls), max_steps = 20, detect_bifurcation = 0)\n\noutfoldco = BK.continuation_fold(probFold,\n\tbr_po, indfold, (@lens _.c5),\n\toptcontfold;\n\tjacobian_ma = :minaug,\n\tbdlinsolver = BorderingBLS(solver = ls, check_precision = false),\n\tplot = true, verbosity = 2)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"which yields:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"(Image: )","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"There is still room for a lot of improvements here. Basically, the idea would be to use full Matrix-Free the jacobian functional and its transpose.","category":"page"},{"location":"tutorials/tutorialsCGL/#Continuation-of-periodic-orbits-on-the-GPU-(Advanced)","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"Continuation of periodic orbits on the GPU (Advanced)","text":"","category":"section"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"tip: \nThis is a very neat example all done on the GPU using the following ingredients: Matrix-Free computation of periodic orbits using preconditioners.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We now take advantage of the computing power of GPUs. The section is run on an NVIDIA Tesla V100. Given the small number of unknowns, we can (only) expect significant speedup in the application of the big preconditioner.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Note that we use the parameters Nx = 82; Ny = 42; M=30.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# computation of the first derivative\nd1Fcgl(x, p, dx) = ForwardDiff.derivative(t -> Fcgl(x .+ t .* dx, p), 0.)\n\nd1NL(x, p, dx) = ForwardDiff.derivative(t -> NL(x .+ t .* dx, p), 0.)\n\nfunction dFcgl(x, p, dx)\n\tf = similar(dx)\n\tmul!(f, p.Δ, dx)\n\tnl = d1NL(x, p, dx)\n\tf .= f .+ nl\nend","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We first load CuArrays","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"using CUDA\nCUDA.allowscalar(false)\nimport LinearAlgebra: mul!, axpby!\nmul!(x::CuArray, y::CuArray, α::T) where {T <: Number} = (x .= α .* y)\nmul!(x::CuArray, α::T, y::CuArray) where {T <: Number} = (x .= α .* y)\naxpby!(a::T, X::CuArray, b::T, Y::CuArray) where {T <: Number} = (Y .= a .* X .+ b .* Y)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"and update the parameters","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"par_cgl_gpu = @set par_cgl.Δ = CUDA.CUSPARSE.CuSparseMatrixCSC(par_cgl.Δ);","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Then, we precompute the preconditioner on the CPU:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Jpo = poTrap(Val(:JacFullSparse), orbitguess_f, @set par_cgl.r = r_hopf - 0.01)\nPrecilu = @time ilu(Jpo, τ = 0.003)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"To invert Precilu on the GPU, we need to define a few functions which are not in CuArrays and which are related to LU decomposition:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"struct LUperso\n\tL\n\tUt\t# transpose of U in LU decomposition\nend\n\nimport Base: ldiv!\nfunction LinearAlgebra.ldiv!(_lu::LUperso, rhs::CUDA.CuArray)\n\t_x = UpperTriangular(_lu.Ut) \\ (LowerTriangular(_lu.L) \\ rhs)\n\trhs .= vec(_x)\n\tCUDA.unsafe_free!(_x)\n\trhs\nend","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Finally, for the methods in PeriodicOrbitTrapProblem to work, we need to redefine the following method. Indeed, we disable the use of scalar on the GPU to increase the speed.","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"import BifurcationKit: extractPeriodFDTrap\nextractPeriodFDTrap(x::CuArray) = x[end:end]","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"We can now define our functional:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"# we create a problem for the vector field on the GUP\nprobGPU = BifurcationProblem(Fcgl,\n vec(CuArrays(zeros((x, p) -> (dx -> dFcgl(x, p, dx))))),\n (@set par_cgl_gpu.r = r_hopf - 0.01),\n (@lens _.r);\n J = (x, p) -> (dx -> dFcgl(x, p, dx)))\n\n# matrix-free problem on the gpu\nls0gpu = GMRESKrylovKit(rtol = 1e-9)\npoTrapMFGPU = PeriodicOrbitTrapProblem(\n\tprobGPU,\n\tCuArray(real.(eigvec)),\n\tCuArray(hopfpt.u),\n\tM, 2n, ls0gpu;\n jacobian = :FullMatrixFree,\n\tongpu = true) # this is required to alter the way the constraint is handled","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"Let us have a look at the linear solvers and compare the speed on CPU and GPU:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"ls = GMRESKrylovKit(verbose = 2, Pl = Precilu, rtol = 1e-3, dim = 20)\n # runs in \t2.990495 seconds (785 allocations: 31.564 MiB, 0.98% gc time)\n\touth, = @time ls((Jpo), orbitguess_f)\n\nPrecilu_gpu = LUperso(LowerTriangular(CUDA.CUSPARSE.CuSparseMatrixCSR(I+Precilu.L)), UpperTriangular(CUDA.CUSPARSE.CuSparseMatrixCSR(sparse(Precilu.U'))));\nlsgpu = GMRESKrylovKit(verbose = 2, Pl = Precilu_gpu, rtol = 1e-3, dim = 20)\n\tJpo_gpu = CUDA.CUSPARSE.CuSparseMatrixCSR(Jpo);\n\torbitguess_cu = CuArray(orbitguess_f)\n\t# runs in 1.751230 seconds (6.54 k allocations: 188.500 KiB, 0.43% gc time)\n\toutd, = @time lsgpu(Jpo_gpu, orbitguess_cu)","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"So we can expect a pretty descent x2 speed up in computing the periodic orbits. We can thus call newton:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"opt_po = @set opt_newton.verbose = true\noutpo_f = @time newton(poTrapMFGPU, orbitguess_cu,\n\t\t(@set opt_po.linsolver = lsgpu);\n\t\tnormN = x->maximum(abs.(x)))","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"The computing time is 6.914367 seconds (2.94 M allocations: 130.348 MiB, 1.10% gc time). The same computation on the CPU, runs in 13.972836 seconds (551.41 k allocations: 1.300 GiB, 1.05% gc time).","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"You can also perform continuation, here is a simple example:","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"opts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.02, ds= 0.001, p_max = 2.2, max_steps = 250, plot_every_step = 3, newton_options = (@set opt_po.linsolver = lsgpu), detect_bifurcation = 0)\nbr_po = @time continuation(poTrapMFGPU, orbitguess_cu, PALC(),\n opts_po_cont;\n verbosity = 2,\n record_from_solution = (u, p) -> getAmplitude(poTrapMFGPU, u, par_cgl_gpu), normC = x->maximum(abs.(x)))","category":"page"},{"location":"tutorials/tutorialsCGL/","page":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","title":"🟠 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS)","text":"info: Preconditioner update\nFor now, the preconditioner has been precomputed on the CPU which forbids its (efficient) update during continuation of a branch of periodic orbits. This could be improved using ilu0! and friends in CuArrays.","category":"page"},{"location":"tutorials/mittelmannAuto/#gelfandauto","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Pages = [\"mittelmannAuto.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"unknown: References\nThe following example is exposed in Farrell, Patrick E., Casper H. L. Beentjes, and Ásgeir Birkisson. The Computation of Disconnected Bifurcation Diagrams. ArXiv:1603.00809 [Math], March 2, 2016. . It is also treated in Michiel Wouters. Automatic Exploration Techniques for the Numerical Continuation of Large–Scale Nonlinear Systems, 2019.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We consider the problem of Mittelmann:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Delta u +NL(lambdau) = 0","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"with Neumann boundary condition on Omega = (01)^2 and where NL(lambdau)equiv-10(u-lambda e^u). This is a good example to show how automatic bifurcation diagram computation works.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We start with some imports:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"using Revise\nusing DiffEqOperators, ForwardDiff\nusing BifurcationKit, LinearAlgebra, Plots, SparseArrays, Parameters, Setfield\nconst BK = BifurcationKit\n\n# define the sup norm\nnorm2(x) = norm(x) / sqrt(length(x))\nnormbratu(x) = norm(x .* w) / sqrt(length(x)) # the weight w is defined below\n\n# some plotting functions to simplify our life\nplotsol!(x, nx = Nx, ny = Ny; kwargs...) = heatmap!(reshape(x, nx, ny); color = :viridis, kwargs...)\nplotsol(x, nx = Nx, ny = Ny; kwargs...) = (plot();plotsol!(x, nx, ny; kwargs...))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"and with the discretization of the problem","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function Laplacian2D(Nx, Ny, lx, ly, bc = :Neumann)\n\thx = 2lx/Nx\n\thy = 2ly/Ny\n\tD2x = CenteredDifference(2, 2, hx, Nx)\n\tD2y = CenteredDifference(2, 2, hy, Ny)\n\n\tQx = Neumann0BC(hx)\n\tQy = Neumann0BC(hy)\n\n\tD2xsp = sparse(D2x * Qx)[1]\n\tD2ysp = sparse(D2y * Qy)[1]\n\tA = kron(sparse(I, Ny, Ny), D2xsp) + kron(D2ysp, sparse(I, Nx, Nx))\n\treturn A\nend\n\nϕ(u, λ) = -10(u-λ*exp(u))\ndϕ(u, λ) = -10(1-λ*exp(u))\n\nfunction NL!(dest, u, p)\n\t@unpack λ = p\n\tdest .= ϕ.(u, λ)\n\treturn dest\nend\n\nNL(u, p) = NL!(similar(u), u, p)\n\nfunction Fmit!(f, u, p)\n\tmul!(f, p.Δ, u)\n\tf .= f .+ NL(u, p)\n\treturn f\nend\n\nFmit(u, p) = Fmit!(similar(u), u, p)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"It will also prove useful to have the jacobian of our functional and the other derivatives:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function JFmit(x,p)\n\tJ = p.Δ\n\tdg = dϕ.(x, p.λ)\n\treturn J + spdiagm(0 => dg)\nend","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We need to pass the parameters associated to this problem:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Nx = 30\nNy = 30\nlx = 0.5\nly = 0.5\n\n# weight for normbratu\nconst w = (lx .+ LinRange(-lx,lx,Nx)) * (LinRange(-ly,ly,Ny))' |> vec\nw .-= minimum(w)\n\nΔ = Laplacian2D(Nx, Ny, lx, ly)\n\n# parameters associated with the PDE\npar_mit = (λ = .01, Δ = Δ)\n\n# initial condition\nsol0 = 0*ones(Nx, Ny) |> vec\n\n# Bifurcation Problem\nprob = BifurcationProblem(Fmit, sol0, par_mit, (@lens _.λ),; J = JFmit,\n record_from_solution = (x, p) -> (x = normbratu(x), n2 = norm(x), n∞ = norminf(x)),\n plot_solution = (x, p; k...) -> plotsol!(x ; k...))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"To compute the eigenvalues, we opt for the solver in KrylovKit.jl","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"# eigensolver\neigls = EigKrylovKit(dim = 70)\n\n# options for Newton solver\nopt_newton = NewtonPar(tol = 1e-8, verbose = true, eigsolver = eigls, max_iterations = 20)\n\n# options for continuation, we want to locate very precisely the\n# bifurcation points, so we tune the bisection accordingly\nopts_br = ContinuationPar(dsmin = 0.0001, dsmax = 0.04, ds = 0.005, p_max = 3.5, p_min = 0.01, detect_bifurcation = 3, nev = 50, plot_every_step = 10, newton_options = (@set opt_newton.verbose = false), max_steps = 251, tol_stability = 1e-6, n_inversion = 6, dsmin_bisection = 1e-7, max_bisection_steps = 25, tol_bisection_eigenvalue = 1e-19)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Note that we put the option detect_bifurcation = 3 to detect bifurcations precisely with a bisection method. Indeed, we need to locate these branch points precisely to be able to call automatic branch switching.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"In order to have an output like Auto07p, we provide the finaliser (see arguments of continuation)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function finSol(z, tau, step, br; k...)\n\tif length(br.specialpoint)>0\n\t\tif br.specialpoint[end].step == step\n\t\t\tBK._show(stdout, br.specialpoint[end], step)\n\t\tend\n\tend\n\treturn true\nend","category":"page"},{"location":"tutorials/mittelmannAuto/#Automatic-bifurcation-diagram","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"Automatic bifurcation diagram","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"In order to avoid spurious branch switching, we use a callback (see continuation) to reject specific continuation steps where the jump in parameters is too large or when the residual is too large:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function cb(state; kwargs...)\n\t_x = get(kwargs, :z0, nothing)\n\tfromNewton = get(kwargs, :fromNewton, false)\n\tif ~fromNewton\n\t\treturn (norm(_x.u - state.x) < 20.5 && abs(_x.p - state.p) < 0.05)\n\tend\n\ttrue\nend","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Finally, before calling the automatic bifurcationdiagram, we need to provide a function to adjust the continuation parameters as function of the branching level (Note that this function can be constant).","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"function optionsCont(x,p,l; opt0 = opts_br)\n\tif l == 1\n\t\treturn opt0\n\telseif l==2\n\t\treturn setproperties(opt0 ;detect_bifurcation = 3,ds = 0.001, a = 0.75)\n\telse\n\t\treturn setproperties(opt0 ;detect_bifurcation = 3,ds = 0.00051, dsmax = 0.01)\n\tend\nend","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We are then ready to compute the bifurcation diagram. If we choose a level 5 of recursion like","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"diagram = @time bifurcationdiagram(prob, PALC(),\n\t# important argument: this is the maximal\n\t# recursion level\n\t5,\n\toptionsCont;\n\tverbosity = 0, plot = true,\n\tcallback_newton = cb,\n\tusedeflation = true,\n\tfinalise_solution = finSol,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"this gives using plot(diagram; plotfold = false, putspecialptlegend=false, markersize=2, title = \"#branches = $(size(diagram))\"):","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We can zoom in on the left part to get","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Actually, this plot is misleading because of the symmetries. If we chose a weighted norm which breaks those symmetries and use it to print the solution, we get","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"plot(diagram; plotfold = false, putspecialptlegend=false, markersize=2,\n\ttitle = \"#branches = $(size(diagram))\", vars = (:param, :nw))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We can make more sense of these spaghetti by only plotting the first two levels of recursion","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"plot(diagram; level = (1, 2), plotfold = false, putspecialptlegend=false, markersize=2, vars = (:param, :nw))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/#Interactive-exploration","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"Interactive exploration","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"We can see that the non-simple 2d branch points (magenta points) have produced non trivial branches. For example, we can look at the second bifurcation point (the first is the fold) which is composed of 8 branches","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"plot(getBranchesFromBP(diagram, 2); plotfold = false, legend = false, vars = (:param, :nw))","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/#Interactive-computation","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"Interactive computation","text":"","category":"section"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"Let's say you have been cautious and did not launch a deep bifurcation diagram computation by using a small recursion level 2:","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"diagram = bifurcationdiagram(prob, PALC(),\n\t# here the recursion level is\n\t2,\n\toptionsCont;\n\tverbosity = 0, plot = true,\n\tcallback_newton = cb,\n\tusedeflation = true,\n\tfinalise_solution = finSol,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"You would end up with this diagram","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"How can we complete this diagram without recomputing it from scratch? It is easy! For example, let us complete the magenta branches as follow","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"bifurcationdiagram!(prob,\n\t# this improves the first branch on the violet curve. Note that\n\t# for symmetry reasons, the first bifurcation point\n\t# has 8 branches\n\tget_branch(diagram, (1,)), 6, optionsCont;\n\tverbosity = 0, plot = true,\n\tcallback_newton = cb,\n\tfinalise_solution = finSol,\n\tusedeflation = true,\n\tnormC = norminf)","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"This gives the following diagram. Using this call, you can pinpoint the particular location where to refine the diagram.","category":"page"},{"location":"tutorials/mittelmannAuto/","page":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","title":"🟡 Automatic diagram of 2d Bratu–Gelfand problem","text":"(Image: )","category":"page"},{"location":"EventCallback/#Event-Handling","page":"Event handling and Callback","title":"Event Handling","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.jl allows the detection of events along the branch of solutions. Its main use consists in detecting bifurcation points but they can be used and combined together by the user too.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"The events are detected during a call to br = continuation(prob, alg, contParams::ContinuationPar;kwargs...) by turning on the following flag(s):","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"contParams.detect_event = 1","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"The event points are located by looking at the function defining the event (see below). The located event points are then returned in br.specialpoint.","category":"page"},{"location":"EventCallback/#Precise-detection-of-event-points-using-Bisection","page":"Event handling and Callback","title":"Precise detection of event points using Bisection","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Note that the event points detected when detect_event = 1 are only approximate event points. Indeed, we only signal that, in between two continuation steps which can be large, a (several) event point has been detected. Hence, we only have a rough idea of where the event is located, unless your ContinuationPar().dsmax is very small... This can be improved as follows.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"If you choose detect_event = 2, a bisection algorithm is used to locate the event points more precisely. It means that we recursively track down the event. Some options in ContinuationPar control this behavior:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"n_inversion: number of sign inversions in the bisection algorithm\nmax_bisection_steps maximum number of bisection steps\ntol_param_bisection_event tolerance on parameter to locate event","category":"page"},{"location":"EventCallback/#Different-event-types","page":"Event handling and Callback","title":"Different event types","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"The set of possible events DiscreteEvent, ContinuousEvent, SetOfEvents, PairOfEvents is detailed in the Library.","category":"page"},{"location":"EventCallback/#Built-in-events","page":"Event handling and Callback","title":"Built-in events","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.SaveAtEvent","category":"page"},{"location":"EventCallback/#BifurcationKit.SaveAtEvent","page":"Event handling and Callback","title":"BifurcationKit.SaveAtEvent","text":"`SaveAtEvent(positions::Tuple)`\n\nThis event implements the detection of when the parameter values, used during continuation, equals one of the values in positions. This state is then saved in the branch.\n\nFor example, you can use it like continuation(args...; event = SaveAtEvent((1., 2., -3.)))\n\n\n\n\n\n","category":"function"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.FoldDetectEvent","category":"page"},{"location":"EventCallback/#BifurcationKit.FoldDetectEvent","page":"Event handling and Callback","title":"BifurcationKit.FoldDetectEvent","text":"`FoldDetectEvent`\n\nThis event implements the detection of Fold points based on the p-component of the tangent vector to the continuation curve. It is designed to work with PALC(tangent=Bordered()) as continuation algorithm. To use it, pass event = FoldDetectEvent to continuation.\n\n\n\n\n\n","category":"constant"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"BifurcationKit.BifDetectEvent","category":"page"},{"location":"EventCallback/#BifurcationKit.BifDetectEvent","page":"Event handling and Callback","title":"BifurcationKit.BifDetectEvent","text":"`BifDetectEvent`\n\nThis event implements the detection of bifurcations points along a continuation curve. The detection is based on monitoring the number of unstable eigenvalues. More details are given at Detection of bifurcation points of Equilibria.\n\n\n\n\n\n","category":"constant"},{"location":"EventCallback/#Examples","page":"Event handling and Callback","title":"Examples","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"We show how to use the different events. We first set up a problem as usual.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"using Revise, BifurcationKit, Setfield, ForwardDiff\nusing Plots\nconst BK = BifurcationKit\n####################################################################################################\n# test vector field for event detection\nfunction Feve(X, p)\n\tp1, p2, k = p\n\tx, y = X\n\tout = similar(X)\n\tout[1] = p1 + x - y - x^k/k\n\tout[2] = p1 + y + x - 2y^k/k\n\tout\nend\n\n# parameters for the vector field\npar = (p1 = -3., p2=-3., k=3)\n\n# bifurcation problem\nprob = BifurcationProblem(Feve, -2ones(2), par, (@lens _.p1);\n\trecord_from_solution = (x,p) -> x[1])\n\n# parameters for the continuation\nopts = ContinuationPar(dsmax = 0.1, ds = 0.001, max_steps = 128, p_min = -3., p_max = 4.0, plot_every_step = 10,\n newton_options = NewtonPar(tol = 1e-10, verbose = false, max_iterations = 5),\n # parameters specific to event detection\n detect_bifurcation = 0, detect_event = 2, n_inversion = 6, dsmin_bisection = 1e-9,\n max_bisection_steps = 15, detect_fold=false)\n\n# arguments for continuation\nargs = (prob, PALC(bls = MatrixBLS()), opts)\nkwargs = (plot = false, verbosity = 0,)\nnothing #hide","category":"page"},{"location":"EventCallback/#Example-of-continuous-event","page":"Event handling and Callback","title":"Example of continuous event","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"In this first example, we build an event to detect when the parameter value is -2 or when the first component of the solution is 1.","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br = continuation(args...; kwargs...,\n\tevent = BK.ContinuousEvent(2, \n\t\t(iter, state) -> (getp(state)+2, getx(state)[1]-1)),)\nnothing #hide\t\t","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"gives","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"This shows for example that the first component of the event was detected userC-1 first. This yields","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"plot(br)","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"You can also name the events as follows","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":" br = continuation(args...; kwargs...,\n \tevent = BK.ContinuousEvent(2, \n \t\t(iter, state) -> (getp(state)+2, getx(state)[1]-1),\n \t\t(\"event1\", \"event2\")))\nnothing #hide \t\t","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"And get:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"plot(br)","category":"page"},{"location":"EventCallback/#Example-of-discrete-event","page":"Event handling and Callback","title":"Example of discrete event","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"You can also use discrete events to detect a change. For example, the following detect when the parameter value equals -2:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br = continuation(args...; kwargs...,\n\tevent = BK.DiscreteEvent(1, \n\t\t(iter, state) -> getp(state)>-2))","category":"page"},{"location":"EventCallback/#Example-of-PairOfEvents-event","page":"Event handling and Callback","title":"Example of PairOfEvents event","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Let us be a bit more creative and combine a continuous event with a discrete one:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"br = continuation(args...; kwargs...,\n\tevent = BK.PairOfEvents(\n\t\tBK.ContinuousEvent(1, (iter, state) -> getp(state)),\n\t\tBK.DiscreteEvent(1, (iter, state) -> getp(state)>-2)))","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Here userD-1 means that the first component of the discrete event was detected. Of course, you can name the event like done above.","category":"page"},{"location":"EventCallback/#Example-of-set-of-events","page":"Event handling and Callback","title":"Example of set of events","text":"","category":"section"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"We can combine more events and chain them like we want using SetOfEvents. In this example, we show how to do bifurcation detection and event location altogether:","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"ev1 = BK.ContinuousEvent(1, (iter, state) -> getp(state)-1)\nev2 = BK.ContinuousEvent(2, (iter, state) -> (getp(state)-2, getp(state)-2.5))\n# event to detect bifurcation\nev3 = BK.BifDetectEvent\n# we combine the events together\neve = BK.SetOfEvents(ev1, ev2, ev3)\n\nbr = continuation(args...; kwargs...,\n\t\tevent = eve)","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"Which gives","category":"page"},{"location":"EventCallback/","page":"Event handling and Callback","title":"Event handling and Callback","text":"plot(br)","category":"page"},{"location":"Borderedarrays/#Bordered-Arrays","page":"Bordered arrays","title":"Bordered Arrays","text":"","category":"section"},{"location":"Borderedarrays/","page":"Bordered arrays","title":"Bordered arrays","text":"Here are some informations on a composite type which is used all over the package to hold a couple (array, array) or (array, scalar) while implementing the methods described in Requested methods for Custom State. ","category":"page"},{"location":"Borderedarrays/","page":"Bordered arrays","title":"Bordered arrays","text":"BorderedArray","category":"page"},{"location":"Borderedarrays/#BifurcationKit.BorderedArray","page":"Bordered arrays","title":"BifurcationKit.BorderedArray","text":"x = BorderedArray(vec1, vec2)\n\nThis defines an array (although not <: AbstractArray) to hold two arrays or an array and a scalar. This is useful when one wants to add constraints (phase, ...) to a functional for example. It is used throughout the package for the Pseudo Arc Length Continuation, for the continuation of Fold / Hopf points, for periodic orbits... It is also used to define periodic orbits as (orbit, period). As such, it is a convenient alternative to cat, vcat and friends. We chose not to make it a subtype of AbstractArray as we wish to apply the current package to general \"arrays\", see Requested methods for Custom State. Finally, it proves useful for the GPU where the operation x[end] can be slow.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/autocatalytic/#Modulated-fronts-in-1d-autocatalytic-model-(Manual)","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Pages = [\"autocatalytic.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We consider the following model [Balmforth][Malham] which is also treated in [Beyn]","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"beginarrayl\nu_t=a u_x x-u f(v) quad a0 u v mathbbR rightarrow mathbbR \nv_t=v_x x+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"where f(u) = u^m 1_ugeq 0. We chose the boundary conditions","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"left(u_- v_-right)=(01)quad left(u_+ v_+right)=(10)tagBC","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"It is straightforward to implement this problem as follows:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"using Revise\nusing ForwardDiff, SparseArrays\nusing BifurcationKit, LinearAlgebra, Plots, Setfield\nconst BK = BifurcationKit\n\n# supremum norm\nnorminf(x) = norm(x, Inf)\nf(u) = u^9 # solutions are positive, so remove the heaviside\n\n# helper function to plot solutions\nfunction plotsol!(x; k...)\n\tu = @view x[1:end÷2]\n\tv = @view x[end÷2:end]\n\tplot!(u; label=\"u\", k...)\n\tplot!(v; label=\"v\", k...)\nend\nplotsol(x; k...) = (plot();plotsol!(x; k...))\n\n# encode the nonlinearity\n@views function NL!(dest, U, p, t = 0.)\n\tN = p.N\n\tu = U[1:N]\n\tv = U[N+1:2N]\n\tdest[1:N] .= -u .* f.(v)\n\tdest[N+1:2N] .= -dest[1:N]#u .* f.(v)\n\treturn dest\nend\n\n# function for the differential with specific boundary conditions\n# for fronts\n@views function applyD_add!(f, U, p, a)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tc1 = 1 / (2p.h)\n\tf[1] += a * (uL - u[2] ) * c1\n\tf[end] += a * (v[n-1] - vR ) * c1\n\n\tf[n] += a * (u[n-1] - uR ) * c1\n\tf[n+1] += a * ( vL - v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += a * (u[i-1] - u[i+1]) * c1\n\t\tf[n+i] += a * (v[i-1] - v[i+1]) * c1\n\tend\n\treturn f\nend\n\n# function which encodes the full PDE\n@views function Fcat!(f, U, p, t = 0)\n\tuL = 0; uR = 1; vL = 1; vR = 0\n\tn = p.N\n\t# nonlinearity\n\tNL!(f, U, p)\n\n\t# Dirichlet boundary conditions\n\th2 = p.h * p.h\n\tc1 = 1 / h2\n\n\tu = U[1:n]\n\tv = U[n+1:2n]\n\n\tf[1] += p.a * (uL - 2u[1] + u[2] ) * c1\n\tf[end] += (v[n-1] - 2v[n] + vR ) * c1\n\n\tf[n] += p.a * (u[n-1] - 2u[n] + uR ) * c1\n\tf[n+1] += (vL - 2v[1] + v[2] ) * c1\n\n\t@inbounds for i=2:n-1\n\t\t f[i] += p.a * (u[i-1] - 2u[i] + u[i+1]) * c1\n\t\tf[n+i] += (v[i-1] - 2v[i] + v[i+1]) * c1\n\tend\n\treturn f\nend\nFcat(x, p, t = 0.) = Fcat!(similar(x), x, p, t)\nJcat(x,p) = sparse(ForwardDiff.jacobian(x -> Fcat(x, p), x))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We chose the following parameters:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"N = 200\nlx = 25.\nX = LinRange(-lx,lx, N)\npar_cat = (N = N, a = 0.18, h = 2lx/N)\n\nu0 = @. (tanh(2X)+1)/2\nU0 = vcat(u0, 1 .- u0)\n\n# we define a problem to hold the vector field\nprob = BifurcationProblem(Fcat, u0, par_cat, (@lens _.a); J = Jcat)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/#Freezing-method","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"Freezing method","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"The problem may feature fronts, that is solutions of the form u(xt) = tilde u(x-st) (same for v) for a fixed value of the profile tilde u and the speed s. The equation for the front profile is, up to an abuse of notations (we removed the tildes)","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"beginarrayl\n0=a u_xixi+scdot u_xi-u f(v)\n0=v_xixi+scdot v_xi+u f(v)\nendarray","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"with unknowns uvs. The front is solution of these equations but it is not uniquely determined because of the phase invariance. Hence, we add the phase condition (see [Beyn])","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"0 = leftlangle (uv) partial_xi (u_0v_0) rightrangle","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"where U_0=(u_0v_0) is some fixed profile. This is easily coded in the following functional","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"@views function FcatWave!(out, x, p)\n\tN = p.N\n\tU = x[1:end-1]\n\tFcat!(out[1:2N], U, p)\n\tapplyD_add!(out[1:2N], U, p, x[end])\n\t# phase condition\n\tout[2N+1] = dot(U, p.Du0)\n\treturn out\nend\nFcatWave(x, p, t = 0) = FcatWave!(similar(x), x, p)\nJcatWave(u, p) = sparse(ForwardDiff.jacobian(z -> FcatWave(z,p), u))\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We now define the U_0 profile","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"uold = vcat(u0, (1 .- u0))\nDuold = zero(uold); applyD_add!(Duold, uold, par_cat,1)\n\n# update problem parameters for front problem\npar_cat_wave = (par_cat..., u0Du0 = dot(uold, Duold), Du0 = Duold, uold = uold)\nnothing #hide","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Let us find the front using newton","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"# we define a problem for solving for the wave\nprobtw = BifurcationProblem(FcatWave, vcat(U0, -1.), par_cat_wave, (@lens _.a);J = JcatWave, record_from_solution = (x,p) -> (s = x[end], nrm = norm(x[1:end-1])),\nplot_solution = (x, p; k...) -> plotsol!(x[1:end-1];k...))\n\nfront = newton(probtw, NewtonPar())\nprintln(\"front speed s = \", front.u[end], \", norm = \", front.u[1:end-1] |> norminf)","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"plotsol(front.u[1:end-1], title=\"front solution\")","category":"page"},{"location":"tutorials/autocatalytic/#Continuation-of-front-solutions","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"Continuation of front solutions","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Following [Malham], the modulated fronts are solutions of the following DAE","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"beginarrayltagDAE\nu_t=a u_x x+scdot u_x-u f(v)\nv_t=v_x x+scdot v_x+u f(v)\n0 = leftlangle U partial_xi U_0\trightrangle\nendarray","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"which can be written with a PDE M_aU_t = G(u) with mass matrix M_a = (Id Id 0). We have already written the vector field of (MF) in the function FcatWave.","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Having found a front U^f, we can continue it as function of the parameter a and detect instabilities. The stability of the front is linked to the eigenelements (lambda V) solution of the generalized eigenvalue problem:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"lambda M_acdot V = dG(U^f)cdot V","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"However BifurcationKit does not provide a generalized eigenvalue solver for now, so we devise one:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"# we need a specific eigensolver\nstruct EigenWave <: BK.AbstractEigenSolver end\n\n# implementation of the solver for the generalized Eigen problem\nfunction (eig::EigenWave)(Jac, nev; k...)\n\tN = size(Jac,1)\n\tB = diagm(vcat(ones(N-1),0))\n\tF = eigen(Array(Jac), B)\n\tI = sortperm(F.values, by = real, rev = true)\n\tnev2 = min(nev, length(I))\n\tJ = findall( abs.(F.values[I]) .< 100000)\n\treturn Complex.(F.values[I[J[1:nev2]]]), Complex.(F.vectors[:, I[J[1:nev2]]]), true, 1\nend\n\noptn = NewtonPar(tol = 1e-8, verbose = true, eigsolver = EigenWave())\nopt_cont_br = ContinuationPar(p_min = 0.05, p_max = 1., newton_options = optn, ds= -0.001, plot_every_step = 2, detect_bifurcation = 3, nev = 10, n_inversion = 6)\n\tbr = continuation(probtw, PALC(), opt_cont_br)\nplot(br)","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts. Let us try to compute them.","category":"page"},{"location":"tutorials/autocatalytic/#Branch-of-modulated-fronts","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"Branch of modulated fronts","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"To branch from the Hopf bifurcation point, we just have to pass the mass matrix as follows:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"# we compute the periodic solutions using Mt time steps and a Trapezoidal time stepper\n# note that we pass the parameter massmatrix which\n# allows to solver the DAE\nMt = 30\nprobTP = PeriodicOrbitTrapProblem(M = Mt ;\n\t\tmassmatrix = spdiagm(0 => vcat(ones(2N),0.)),\n\t\tupdate_section_every_step = 1,\n\t\t# linear solver for the periodic orbit problem\n\t\t# OPTIONAL, one could use the default\n\t\tjacobian = :BorderedLU)\n\nopts_po_cont = ContinuationPar(dsmin = 0.0001, dsmax = 0.01, ds= -0.001, p_min = 0.05, max_steps = 130, newton_options = optn, nev = 7, tol_stability = 1e-3, detect_bifurcation = 0, plot_every_step = 1)\n\topts_po_cont = @set opts_po_cont.newton_options.max_iterations = 10\n\topts_po_cont = @set opts_po_cont.newton_options.tol = 1e-6\n\nbr_po = continuation(\n\t# we want to compute the bifurcated branch from\n\t# the first Hopf point\n\tbr, 1,\n\t# arguments for continuation\n\topts_po_cont,\n\t# this is how we pass the method to compute the periodic\n\tprobTP ;\n\t# OPTIONAL parameters\n\t# we want to jump on the new branch at phopf + δp\n\tδp = 0.0025,\n\t# tangent predictor\n\talg = PALC(tangent = Secant(),\n\t\t\t# linear solver specific to PALC\n\t\t\tbls = BorderingBLS(solver = DefaultLS(), check_precision = false)),\n\t# regular parameters for the continuation\n\t# a few parameters saved during run\n\trecord_from_solution = (u, p) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, u, (@set par_cat_wave.a=p))\n\t\tm = maximum(outt.u[end,:])\n\t\treturn (s = m, period = u[end])\n\tend,\n\t# plotting of a section\n\tplot_solution = (x, p; k...) -> begin\n\t\toutt = BK.get_periodic_orbit(p.prob, x, (@set par_cat_wave.a=p.p))\n\t\tplot!(outt.t, outt.u[end, :]; label = \"\", subplot=3)\n\t\tplot!(br, subplot=1)\n\tend,\n\t# print the Floquet exponent\n\tfinalise_solution = (z, tau, step, contResult; k...) -> begin\n\t\ttrue\n\tend,\n\tplot = true,\n\tnormC = norminf)\n\nplot(br);plot!(br_po, label = \"modulated fronts\")","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"Let us plot one modulated front:","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"modfront = BK.get_periodic_orbit(br_po, length(br_po))\nplot(plot(modfront.t, modfront.u[end,:], xlabel = \"t\", ylabel = \"s\", label = \"\"),\n\tcontour(modfront.t, X, modfront.u[1:N,:], color = :viridis, xlabel = \"t\", title = \"u for a = $(round(br_po.sol[length(br_po)].p,digits=4))\", fill = true, ylims=(-10,10)))","category":"page"},{"location":"tutorials/autocatalytic/#References","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"References","text":"","category":"section"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"[Balmforth]: N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"[Malham]: S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.","category":"page"},{"location":"tutorials/autocatalytic/","page":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","title":"🟤 Modulated fronts in 1d autocatalytic model (Manual)","text":"[Beyn]: Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.","category":"page"},{"location":"tutorials/tutorials2b/#sh2dgpu","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Pages = [\"tutorials2b.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Here we give an example where the continuation can be done entirely on the GPU, e.g. on a single V100 NIVDIA.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"info: Why this example?\nThis is not the simplest GPU example because we need a preconditioned linear solver and shift-invert eigen solver for this problem. On the other hand, you will be shown how to set up your own linear/eigen solver.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We choose the 2d Swift-Hohenberg as an example and consider a larger grid. See 2d Swift-Hohenberg equation for more details. Solving the sparse linear problem in v","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"-(I+Delta)^2 v+(l +2nu u-3u^2)v = rhs","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"with a direct solver becomes prohibitive. Looking for an iterative method, the conditioning of the jacobian is not good enough to have fast convergence, mainly because of the Laplacian operator. However, the above problem is equivalent to:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"-v + L cdot (d cdot v) = Lcdot rhs","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"where","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"L = ((I+Delta)^2 + I)^-1","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"is very well conditioned and","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"d = l+1+2nu v-3v^2","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Hence, to solve the previous equation, only a few GMRES iterations are required.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"In effect, the preconditioned PDE is an example of nonlocal problem.","category":"page"},{"location":"tutorials/tutorials2b/#Linear-Algebra-on-the-GPU","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Linear Algebra on the GPU","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We plan to use KrylovKit on the GPU. We define the following types so it is easier to switch to Float32 for example:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"using Revise, CUDA\n\n# this disable slow operations but errors if you use one of them\nCUDA.allowscalar(false)\n\n# type used for the arrays, can be Float32 if GPU requires it\nTY = Float64\n\n# put the AF = Array{TY} instead to make the code on the CPU\nAF = CuArray{TY}","category":"page"},{"location":"tutorials/tutorials2b/#Computing-the-inverse-of-the-differential-operator","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Computing the inverse of the differential operator","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"The issue now is to compute L but this is easy using Fourier transforms.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Hence, that's why we slightly modify the previous Example by considering periodic boundary conditions. Let us now show how to compute L. Although the code looks quite technical, it is based on two facts. First, the Fourier transform symbol associated to L is","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"l_1 = 1+(1-k_x^2-k_y^2)^2","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"which is pre-computed in the composite type SHLinearOp. Then, the effect of L on u is as simple as real.(ifft( l1 .* fft(u) )) and the inverse L\\u is real.(ifft( fft(u) ./ l1 )). However, in order to save memory on the GPU, we use inplace FFTs to reduce temporaries which explains the following code.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"using AbstractFFTs, FFTW, KrylovKit, Setfield, Parameters\nusing BifurcationKit, LinearAlgebra, Plots\nconst BK = BifurcationKit\n\n# the following struct encodes the operator L1\n# Making the linear operator a subtype of BK.AbstractLinearSolver is handy as it will be used\n# in the Newton iterations.\nstruct SHLinearOp{Treal, Tcomp, Tl1, Tplan, Tiplan} <: BK.AbstractLinearSolver\n\ttmp_real::Treal # temporary\n\ttmp_complex::Tcomp # temporary\n\tl1::Tl1\n\tfftplan::Tplan\n\tifftplan::Tiplan\nend\n\n# this is a constructor for the above struct\nfunction SHLinearOp(Nx, lx, Ny, ly; AF = Array{TY})\n\t# AF is a type, it could be CuArray{TY} to run the following on GPU\n\tk1 = vcat(collect(0:Nx/2), collect(Nx/2+1:Nx-1) .- Nx)\n\tk2 = vcat(collect(0:Ny/2), collect(Ny/2+1:Ny-1) .- Ny)\n\td2 = [(1-(pi/lx * kx)^2 - (pi/ly * ky)^2)^2 + 1. for kx in k1, ky in k2]\n\ttmpc = Complex.(AF(zeros(Nx, Ny)))\n\treturn SHLinearOp(AF(zeros(Nx, Ny)), tmpc, AF(d2), plan_fft!(tmpc), plan_ifft!(tmpc))\nend\n\nimport Base: *, \\\n\n# generic function to apply operator op to u\nfunction apply(c::SHLinearOp, u, multiplier, op = *)\n\tc.tmp_complex .= Complex.(u)\n\tc.fftplan * c.tmp_complex\n\tc.tmp_complex .= op.(c.tmp_complex, multiplier)\n\tc.ifftplan * c.tmp_complex\n\tc.tmp_real .= real.(c.tmp_complex)\n\treturn copy(c.tmp_real)\nend\n\n# action of L\n*(c::SHLinearOp, u) = apply(c, u, c.l1)\n\n# inverse of L\n\\(c::SHLinearOp, u) = apply(c, u, c.l1, /)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Before applying a Newton solver, we need to tell how to solve the linear equation arising in the Newton Algorithm.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"# inverse of the jacobian of the PDE\nfunction (sh::SHLinearOp)(J, rhs; shift = 0., tol = 1e-9)\n\tu, l, ν = J\n\tudiag = l .+ 1 .+ 2ν .* u .- 3 .* u.^2 .- shift\n\tres, info = KrylovKit.linsolve( du -> -du .+ sh \\ (udiag .* du), sh \\ rhs,\n\ttol = tol, maxiter = 6)\n\treturn res, true, info.numops\nend","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Now that we have our operator L, we can encode our functional:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"function F_shfft(u, p)\n\t@unpack l, ν, L = p\n\treturn -(L * u) .+ ((l+1) .* u .+ ν .* u.^2 .- u.^3)\nend","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Let us now show how to build our operator L and an initial guess sol0 using the above defined structures.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"using LinearAlgebra, Plots\n\n# to simplify plotting of the solution\nplotsol(x; k...) = heatmap(reshape(Array(x), Nx, Ny)'; color=:viridis, k...)\nplotsol!(x; k...) = heatmap!(reshape(Array(x), Nx, Ny)'; color=:viridis, k...)\nnorminf(x) = maximum(abs.(x))\n\n# norm compatible with CUDA\nnorminf(x) = maximum(abs.(x))\n\nNx = 2^10\nNy = 2^10\nlx = 8pi * 2\nly = 2*2pi/sqrt(3) * 2\n\nX = -lx .+ 2lx/(Nx) * collect(0:Nx-1)\nY = -ly .+ 2ly/(Ny) * collect(0:Ny-1)\n\nsol0 = [(cos(x) .+ cos(x/2) * cos(sqrt(3) * y/2) ) for x in X, y in Y]\n\t\tsol0 .= sol0 .- minimum(vec(sol0))\n\t\tsol0 ./= maximum(vec(sol0))\n\t\tsol0 = sol0 .- 0.25\n\t\tsol0 .*= 1.7\n\nL = SHLinearOp(Nx, lx, Ny, ly, AF = AF)\nJ_shfft(u, p) = (u, p.l, p.ν)\n\n# parameters of the PDE\npar = (l = -0.15, ν = 1.3, L = L)\n\n# Bifurcation Problem\nprob = BK.BifurcationProblem(F_shfft, AF(sol0), par, (@lens _.l) ;\n\tJ = J_shfft,\n\tplot_solution = (x, p;kwargs...) -> plotsol!(x; color=:viridis, kwargs...),\n\trecord_from_solution = (x, p) -> norm(x))","category":"page"},{"location":"tutorials/tutorials2b/#Newton-iterations-and-deflation","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Newton iterations and deflation","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We are now ready to perform Newton iterations:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"opt_new = NewtonPar(verbose = true, tol = 1e-6, max_iterations = 100, linsolver = L)\nsol_hexa = @time newton(prob, opt_new, normN = norminf)\nprintln(\"--> norm(sol) = \", maximum(abs.(sol_hexa.u)))\nplotsol(sol_hexa.u)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"You should see this:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"┌─────────────────────────────────────────────────────┐\n│ Newton step residual linear iterations │\n├─────────────┬──────────────────────┬────────────────┤\n│ 0 │ 3.3758e-01 │ 0 │\n│ 1 │ 8.0152e+01 │ 12 │\n│ 2 │ 2.3716e+01 │ 28 │\n│ 3 │ 6.7353e+00 │ 22 │\n│ 4 │ 1.9498e+00 │ 17 │\n│ 5 │ 5.5893e-01 │ 14 │\n│ 6 │ 1.0998e-01 │ 12 │\n│ 7 │ 1.1381e-02 │ 11 │\n│ 8 │ 1.6393e-04 │ 11 │\n│ 9 │ 7.3277e-08 │ 10 │\n└─────────────┴──────────────────────┴────────────────┘\n 0.317790 seconds (42.67 k allocations: 1.256 MiB)\n--> norm(sol) = 1.26017611779702","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Note that this is about the 10x faster than Example 2 but for a problem almost 100x larger! (On a V100 GPU)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"The solution is:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We can also use the deflation technique (see DeflationOperator and DeflatedProblem for more information) on the GPU as follows","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"deflationOp = DeflationOperator(2, dot, 1.0, [sol_hexa.u])\n\nopt_new = @set opt_new.max_iterations = 250\noutdef = @time newton(re_make(prob, u0 = AF(0.4 .* sol_hexa.u .* AF([exp(-1(x+0lx)^2/25) for x in X, y in Y]))),\n\t\tdeflationOp, opt_new, normN = x-> maximum(abs.(x)))\nprintln(\"--> norm(sol) = \", norm(outdef.u))\nplotsol(outdef.u) |> display\nBK.converged(outdef) && push!(deflationOp, outdef.u)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"and get:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2b/#Computation-of-the-branches","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"Computation of the branches","text":"","category":"section"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"Finally, we can perform continuation of the branches on the GPU:","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"opts_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.007, ds= -0.005,\n\tp_max = 0., p_min = -1.0, plot_every_step = 5, detect_bifurcation = 0,\n\tnewton_options = setproperties(opt_new; tol = 1e-6, max_iterations = 15), max_steps = 100)\n\nbr = @time continuation(re_make(prob, u0 = deflationOp[1]),\nPALC(bls = BorderingBLS(solver = L, check_precision = false)),\nopts_cont;\n\tplot = true, verbosity = 3,\n\tnormC = x -> maximum(abs.(x))\n\t)","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We did not detail how to compute the eigenvalues on the GPU and detect the bifurcations. It is based on a simple Shift-Invert strategy, please look at examples/SH2d-fronts-cuda.jl.","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"(Image: )","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"We have the following information about the branch of hexagons","category":"page"},{"location":"tutorials/tutorials2b/","page":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","title":"🟠 2d Swift-Hohenberg equation (non-local) on the GPU","text":"julia> br\nBranch number of points: 67\nBranch of Equilibrium\nBifurcation points:\n (ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`)\n- # 1, nd at p ≈ -0.21522461 ∈ (-0.21528614, -0.21522461), |δp|=6e-05, [converged], δ = ( 3, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3\n- # 2, nd at p ≈ -0.21469007 ∈ (-0.21479652, -0.21469007), |δp|=1e-04, [converged], δ = ( 2, 0), step = 25, eigenelements in eig[ 26], ind_ev = 5\n- # 3, nd at p ≈ -0.21216919 ∈ (-0.21264341, -0.21216919), |δp|=5e-04, [converged], δ = ( 2, 0), step = 27, eigenelements in eig[ 28], ind_ev = 7\n- # 4, nd at p ≈ -0.21052576 ∈ (-0.21110899, -0.21052576), |δp|=6e-04, [converged], δ = ( 2, 0), step = 28, eigenelements in eig[ 29], ind_ev = 9\n- # 5, nd at p ≈ -0.20630678 ∈ (-0.21052576, -0.20630678), |δp|=4e-03, [converged], δ = ( 8, 0), step = 29, eigenelements in eig[ 30], ind_ev = 17\n- # 6, nd at p ≈ -0.19896508 ∈ (-0.19897308, -0.19896508), |δp|=8e-06, [converged], δ = ( 6, 0), step = 30, eigenelements in eig[ 31], ind_ev = 23\n- # 7, nd at p ≈ -0.18621673 ∈ (-0.18748234, -0.18621673), |δp|=1e-03, [converged], δ = ( 2, 0), step = 33, eigenelements in eig[ 34], ind_ev = 25\n- # 8, nd at p ≈ -0.17258147 ∈ (-0.18096574, -0.17258147), |δp|=8e-03, [converged], δ = ( 4, 0), step = 35, eigenelements in eig[ 36], ind_ev = 29\n- # 9, nd at p ≈ -0.14951737 ∈ (-0.15113148, -0.14951737), |δp|=2e-03, [converged], δ = (-4, 0), step = 39, eigenelements in eig[ 40], ind_ev = 29\n- # 10, nd at p ≈ -0.14047758 ∈ (-0.14130979, -0.14047758), |δp|=8e-04, [converged], δ = (-2, 0), step = 41, eigenelements in eig[ 42], ind_ev = 25\n- # 11, nd at p ≈ -0.11304882 ∈ (-0.11315916, -0.11304882), |δp|=1e-04, [converged], δ = (-4, 0), step = 45, eigenelements in eig[ 46], ind_ev = 23\n- # 12, nd at p ≈ -0.09074623 ∈ (-0.09085968, -0.09074623), |δp|=1e-04, [converged], δ = (-6, 0), step = 49, eigenelements in eig[ 50], ind_ev = 19\n- # 13, nd at p ≈ -0.07062574 ∈ (-0.07246519, -0.07062574), |δp|=2e-03, [converged], δ = (-4, 0), step = 52, eigenelements in eig[ 53], ind_ev = 13\n- # 14, nd at p ≈ -0.06235903 ∈ (-0.06238787, -0.06235903), |δp|=3e-05, [converged], δ = (-2, 0), step = 54, eigenelements in eig[ 55], ind_ev = 9\n- # 15, nd at p ≈ -0.05358077 ∈ (-0.05404312, -0.05358077), |δp|=5e-04, [converged], δ = (-2, 0), step = 56, eigenelements in eig[ 57], ind_ev = 7\n- # 16, nd at p ≈ -0.02494422 ∈ (-0.02586444, -0.02494422), |δp|=9e-04, [converged], δ = (-2, 0), step = 60, eigenelements in eig[ 61], ind_ev = 5\n- # 17, nd at p ≈ -0.00484022 ∈ (-0.00665356, -0.00484022), |δp|=2e-03, [converged], δ = (-2, 0), step = 63, eigenelements in eig[ 64], ind_ev = 3\n- # 18, nd at p ≈ +0.00057801 ∈ (-0.00122418, +0.00057801), |δp|=2e-03, [converged], δ = ( 5, 0), step = 64, eigenelements in eig[ 65], ind_ev = 6\n- # 19, nd at p ≈ +0.00320921 ∈ (+0.00141327, +0.00320921), |δp|=2e-03, [converged], δ = (10, 0), step = 65, eigenelements in eig[ 66], ind_ev = 16\nFold points:\n- # 1, fold at p ≈ -0.21528694 ∈ (-0.21528694, -0.21528694), |δp|=-1e+00, [ guess], δ = ( 0, 0), step = 24, eigenelements in eig[ 24], ind_ev = 0","category":"page"},{"location":"abs-from-eq/#From-equilibria-to-equilibria","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"Pages = [\"abs-from-eq.md\"]\nDepth = 3","category":"page"},{"location":"abs-from-eq/#From-simple-branch-point-to-equilibria","page":"From equilibria to equilibria","title":"From simple branch point to equilibria","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"See Branch switching (branch point) for the precise method definition","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"You can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"continuation(br::ContResult, ind_bif::Int, optionsCont::ContinuationPar; kwargs...)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"where br is a branch computed after a call to continuation with detection of bifurcation points enabled. This call computes the branch bifurcating from the ind_bifth bifurcation point in br. An example of use is provided in 2d Bratu–Gelfand problem.","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"See Branch switching (branch point) precise method definition","category":"page"},{"location":"abs-from-eq/#Simple-example:-transcritical-bifurcation","page":"From equilibria to equilibria","title":"Simple example: transcritical bifurcation","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"using BifurcationKit, Setfield, Plots\n\n# vector field of transcritical bifurcation\nF(x, p) = [x[1] * (p.μ - x[1])]\n\n# parameters of the vector field\npar = (μ = -0.2, )\n\n# problem (automatic differentiation)\nprob = BifurcationProblem(F, [0.], par, (@lens _.μ); record_from_solution = (x, p) -> x[1])\n\n# compute branch of trivial equilibria and detect a bifurcation point\nopts_br = ContinuationPar()\nbr = continuation(prob, PALC(), opts_br)\n\t\n# perform branch switching on both sides of the bifurcation point\nbr1 = continuation(br, 1, setproperties(opts_br; max_steps = 14), bothside = true )\n\nscene = plot(br, br1; branchlabel = [\"br\", \"br1\"], legend = :topleft)","category":"page"},{"location":"abs-from-eq/#Simple-example:-pitchfork-bifurcation","page":"From equilibria to equilibria","title":"Simple example: pitchfork bifurcation","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"using BifurcationKit, Setfield, Plots\n\n# vector field of pitchfork bifurcation\nF(x, p) = [x[1] * (p.μ - x[1]^2)]\n\n# parameters of the vector field\npar = (μ = -0.2, )\n\n# problem (automatic differentiation)\nprob = BifurcationProblem(F, [0.], par, (@lens _.μ); record_from_solution = (x, p) -> x[1])\n\n# compute branch of trivial equilibria and \n# detect a bifurcation point with improved precision\nopts_br = ContinuationPar(n_inversion = 6)\nbr = continuation(prob, PALC(), opts_br)\n\t\n# perform branch switching on both sides of the bifurcation point\nbr1 = continuation(br, 1, setproperties(opts_br; max_steps = 14), bothside = true )\n\nscene = plot(br, br1; branchlabel = [\"br\", \"br1\"], legend = :topleft)","category":"page"},{"location":"abs-from-eq/#Algorithm","page":"From equilibria to equilibria","title":"Algorithm","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"the normal form is computed and non-trivial zeros are used to produce guesses for points on the bifurcated branch.","category":"page"},{"location":"abs-from-eq/#abs-simple-eq","page":"From equilibria to equilibria","title":"From non simple branch point to equilibria","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"We provide an automatic branch switching method in this case. The underlying method is to first compute the reduced equation (see Non-simple branch point) and its zeros. These zeros are then seeded as initial guess for continuation. Hence, you can perform automatic branch switching by calling continuation with the following options:","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"continuation(br::ContResult, \n\tind_bif::Int,\n\toptionsCont::ContinuationPar;\n\tkwargs...)","category":"page"},{"location":"abs-from-eq/#Examples","page":"From equilibria to equilibria","title":"Examples","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"An example of use is provided in 2d Bratu–Gelfand problem. A much simpler example is given now. It is a bit artificial because the vector field is its own normal form at the bifurcation point located at 0.","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"using BifurcationKit, Plots\n\nfunction FbpD6(x, p)\n return [p.μ * x[1] + (p.a * x[2] * x[3] - p.b * x[1]^3 - p.c*(x[2]^2 + x[3]^2) * x[1]),\n p.μ * x[2] + (p.a * x[1] * x[3] - p.b * x[2]^3 - p.c*(x[3]^2 + x[1]^2) * x[2]),\n p.μ * x[3] + (p.a * x[1] * x[2] - p.b * x[3]^3 - p.c*(x[2]^2 + x[1]^2) * x[3])]\nend\n\n# model parameters\npard6 = (μ = -0.2, a = 0.3, b = 1.5, c = 2.9)\n\n# problem\nprob = BifurcationProblem(FbpD6, zeros(3), pard6, (@lens _.μ);\n\trecord_from_solution = (x, p) -> (n = norminf(x)))\n\n# newton options\nopt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)\n\n# continuation options\nopts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.02, ds = 0.01, \n\t# parameter interval\n\tp_max = 0.4, p_min = -0.2, \n\tnev = 3, \n\tnewton_options = opt_newton, \n\tmax_steps = 1000, \n\tn_inversion = 6)\n\nbr = continuation(prob, PALC(), opts_br)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"You can now branch from the nd point","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"br2 = continuation(br, 1, opts_br; δp = 0.02)\n\nplot(br, br2...)","category":"page"},{"location":"abs-from-eq/#Assisted-branching-from-non-simple-bifurcation-point","page":"From equilibria to equilibria","title":"Assisted branching from non-simple bifurcation point","text":"","category":"section"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"It may happen that the general procedure fails. We thus expose the procedure multicontinuation in order to let the user tune it to its need.","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"The first step is to compute the reduced equation, say of the first bifurcation point in br.","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"bp = get_normal_form(br, 1)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"Next, we want to find the zeros of the reduced equation. This is usually achieved by calling the predictor","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"δp = 0.005\npred = predictor(bp, δp)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"which returns zeros of bp before and after the bifurcation point. You could also use your preferred procedure from Roots.jl (or other) to find the zeros of the polynomials bp(Val(:reducedForm), z, p).","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"We can use these zeros to form guesses to apply Newton for the full functional:","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"pts = BifurcationKit.get_first_points_on_branch(br, bp, pred, opts_br; δp = δp)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"We can then use this to continue the different branches","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"brbp = BifurcationKit.multicontinuation(br, bp, pts.before, pts.after, opts_br)\n\nplot(br, brbp...)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"Note that you can chose another predictor which uses all vertices of the cube as initial guesses","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"pred = predictor(bp, Val(:exhaustive), δp)\npts = BifurcationKit.get_first_points_on_branch(br, bp, pred, opts_br; δp = δp)","category":"page"},{"location":"abs-from-eq/","page":"From equilibria to equilibria","title":"From equilibria to equilibria","text":"brbp = BifurcationKit.multicontinuation(br, bp, pts.before, pts.after, opts_br)\n\nplot(br, brbp...)","category":"page"},{"location":"abs-from-eq/#predictors-@docsBifurcationKit.predictor(bp::BifurcationKit.NdBranchPoint,-δp::T;-k...)-where-T@docsBifurcationKit.predictor(bp::BifurcationKit.NdBranchPoint,-algo::Val{:exhaustive},-δp::T;k...)-where-T","page":"From equilibria to equilibria","title":"predictors @docsBifurcationKit.predictor(bp::BifurcationKit.NdBranchPoint, δp::T; k...) where T@docsBifurcationKit.predictor(bp::BifurcationKit.NdBranchPoint, algo::Val{:exhaustive}, δp::T;k...) where T","text":"","category":"section"},{"location":"linearsolver/#Linear-solvers-(LS)","page":"Linear solvers","title":"Linear solvers (LS)","text":"","category":"section"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"If you provide your own linear solver, it must be a subtype of AbstractLinearSolver otherwise BifurcationKit.jl will not recognize it. See example just below. ","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"The linear solvers provide a way of inverting the Jacobian J or solving J * x = rhs. Such linear solver linsolve will be called like sol, success, itnumber = linsolve(J, rhs; kwargs...) throughout the package.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Here is an example of the simplest one (see src/LinearSolver.jl for the true implementation) to give you an idea, the backslash operator:","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"struct DefaultLS <: AbstractLinearSolver end\n\nfunction (l::DefaultLS)(J, rhs; k...)\n\treturn J \\ rhs, true, 1\nend","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Note that for newton to work, the linear solver must return 3 arguments. The first one is the result, the second one is whether the computation was successful and the third is the number of iterations required to perform the computation.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"You can then call it as follows (and it will be called like this in newton)","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"ls = DefaultLS()\nJ = rand(2, 2) # example of linear operator\nls(J, rand(2))","category":"page"},{"location":"linearsolver/#List-of-implemented-linear-solvers","page":"Linear solvers","title":"List of implemented linear solvers","text":"","category":"section"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Default \\ solver based on LU or Cholesky depending on the type of the Jacobian. This works for sparse matrices as well. You can create one via linsolver = DefaultLS().\nGMRES from IterativeSolvers.jl. You can create one via linsolver = GMRESIterativeSolvers() and pass appropriate options.\nGMRES from KrylovKit.jl. You can create one via linsolver = GMRESKrylovKit() and pass appropriate options.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"tip: Different linear solvers\nBy tuning the options of GMRESKrylovKit, you can select CG, GMRES... see KrylovKit.jl.","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"note: Other solvers\nIt is very straightforward to implement the Conjugate Gradients from IterativeSolvers.jl by copying the interface done for gmres. Same goes for minres,... Not needing them, I did not implement this.","category":"page"},{"location":"linearsolver/#Preconditioner","page":"Linear solvers","title":"Preconditioner","text":"","category":"section"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"Preconditioners should be considered when using Matrix Free methods such as GMRES. GMRESIterativeSolvers provides a very simple interface for using them. For GMRESKrylovKit, we implemented a left preconditioner. Note that, for GMRESKrylovKit, you are not restricted to use Vectors anymore. Finally, here are some packages to use preconditioners","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"IncompleteLU.jl an ILU like preconditioner\nAlgebraicMultigrid.jl Algebraic Multigrid (AMG) preconditioners. This works especially well for symmetric positive definite matrices.\nPreconditioners.jl A convenient interface to conveniently called most of the above preconditioners using a single syntax.\nWe provide a preconditioner based on deflation of eigenvalues (also called preconditioner based on Leading Invariant Subspaces) using a partial Schur decomposition. There are two ways to define one i.e. PrecPartialSchurKrylovKit and PrecPartialSchurArnoldiMethod. ","category":"page"},{"location":"linearsolver/","page":"Linear solvers","title":"Linear solvers","text":"tip: Using Preconditioners\nApart from setting a preconditioner for a linear solver, it can be advantageous to change the preconditioner during computations, e.g. during a call to continuation or newton. This can be achieved by taking advantage of the callbacks to these methods. See the example 2d Ginzburg-Landau equation (finite differences, codim 2, Hopf aBS).","category":"page"},{"location":"waveEigen/#Wave-stability","page":"Eigen Solvers","title":"Wave stability","text":"","category":"section"},{"location":"waveEigen/#References","page":"Eigen Solvers","title":"References","text":"","category":"section"},{"location":"waveEigen/","page":"Eigen Solvers","title":"Eigen Solvers","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"waveEigen/","page":"Eigen Solvers","title":"Eigen Solvers","text":"[Sandstede]: Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.","category":"page"},{"location":"FoldContinuationPO/#fold-po","page":"Fold continuation (2 params)","title":"Continuation of Fold of periodic orbits","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"warning: Work in progress\nContinuation of Fold of POs is a recent addition. It has not been thoroughly tested.","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"In this page, we explain how to perform continuation of Fold points and detect the associated codim 2 bifurcations.","category":"page"},{"location":"FoldContinuationPO/#List-of-detected-codim-2-bifurcation-points","page":"Fold continuation (2 params)","title":"List of detected codim 2 bifurcation points","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"Bifurcation symbol used\nCusp cusp\nStrong resonance 1:1 bifurcation R1\nFold / Flip foldFlip\nFold / Neimark-Sacker foldNS","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"In a nutshell, all you have to do (see below) is to call continuation(br, ind_bif, lens2) to continue the bifurcation point stored in br.specialpoint[ind_bif] and set proper options.","category":"page"},{"location":"FoldContinuationPO/#Fold-continuation","page":"Fold continuation (2 params)","title":"Fold continuation","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"The continuation of Fold bifurcation points is based on a Minimally Augmented[Govaerts] formulation which is an efficient way to detect singularities (see Fold / Hopf Continuation). All the methods (see Periodic orbits computation) for computing periodic orbits are compatible with this algorithm. In particular, you can perform these computations in large dimensions.","category":"page"},{"location":"FoldContinuationPO/#Detection-of-codim-2-bifurcation-points","page":"Fold continuation (2 params)","title":"Detection of codim 2 bifurcation points","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"You can detect the following codim 2 bifurcation points by using the keyword argument detect_codim2_bifurcation in the method continuation ","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"the detection of Cusp (Cusp) is done by the detection of Fold bifurcation points along the curve of Folds by monitoring the parameter component of the tangent.\nthe detection the above bifurcation points is done by monitoring the number of eigenvalues lambda such that Relambda minlimits_nuinSigma(dF)Renu and Imlambda epsilon where epsilon is the Newton tolerance.","category":"page"},{"location":"FoldContinuationPO/#Setting-the-jacobian","page":"Fold continuation (2 params)","title":"Setting the jacobian","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"In order to apply the newton algorithm to the Fold functional, one needs to invert the jacobian. This is not completely trivial as one must compute this jacobian and then invert it. You can select the following jacobians for your computations (see below):","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"[Default] for jacobian_ma = :autodiff, automatic differentiation is applied to the Fold functional and the matrix is then inverted using the provided linear solver. In particular, the jacobian is formed. This is very well suited for small dimensions (say < 100)\nfor jacobian_ma = :finiteDifferences, same as jacobian_ma = :autodiff but the jacobian is computed using finite differences.\nfor jacobian_ma = :minaug, a specific procedure for evaluating the jacobian and inverting it (without forming the jacobian!) is used. This is well suited for large dimensions.","category":"page"},{"location":"FoldContinuationPO/#Codim-2-continuation","page":"Fold continuation (2 params)","title":"Codim 2 continuation","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"To compute the codim 2 curve of Fold points of periodic orbits, one can call continuation with the following options","category":"page"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":" continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int64,\n\t\t\t\tlens2::Lens, options_cont::ContinuationPar = br.contparams ;\n\t\t\t\tkwargs...)","category":"page"},{"location":"FoldContinuationPO/#BifurcationKit.continuation","page":"Fold continuation (2 params)","title":"BifurcationKit.continuation","text":"continuation(br, ind_bif, lens2; ...)\ncontinuation(\n br,\n ind_bif,\n lens2,\n options_cont;\n prob,\n start_with_eigen,\n detect_codim2_bifurcation,\n kwargs...\n)\n\n\nCodimension 2 continuation of Fold / Hopf points. This function turns an initial guess for a Fold / Hopf point into a curve of Fold / Hopf points based on a Minimally Augmented formulation. The arguments are as follows\n\nbr results returned after a call to continuation\nind_bif bifurcation index in br\nlens2 second parameter used for the continuation, the first one is the one used to compute br, e.g. getlens(br)\noptions_cont = br.contparams arguments to be passed to the regular continuation\n\nOptional arguments:\n\nbdlinsolver bordered linear solver for the constraint equation\nupdate_minaug_every_step update vectors a, b in Minimally Formulation every update_minaug_every_step steps\nstart_with_eigen = false whether to start the Minimally Augmented problem with information from eigen elements\ndetect_codim2_bifurcation ∈ {0,1,2} whether to detect Bogdanov-Takens, Bautin and Cusp. If equals 1 non precise detection is used. If equals 2, a bisection method is used to locate the bifurcations.\nkwargs keywords arguments to be passed to the regular continuation\n\nwhere the parameters are as above except that you have to pass the branch br from the result of a call to continuation with detection of bifurcations enabled and index is the index of Hopf point in br you want to refine.\n\ntip: ODE problems\nFor ODE problems, it is more efficient to use the Matrix based Bordered Linear Solver passing the option bdlinsolver = MatrixBLS()\n\ntip: start_with_eigen\nIt is recommended that you use the option start_with_eigen = true\n\n\n\n\n\n","category":"function"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"where br is a branch of periodic orbits and the options are as above except with have an additional parameter axis lens2 which is used to locate the bifurcation points.","category":"page"},{"location":"FoldContinuationPO/#References","page":"Fold continuation (2 params)","title":"References","text":"","category":"section"},{"location":"FoldContinuationPO/","page":"Fold continuation (2 params)","title":"Fold continuation (2 params)","text":"[Govaerts]: Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#[Lorenz-84-model,-take-2](@id-lorenz98-take2)","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"Pages = [\"lorenz84-PO.md\"]\nDepth = 3","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"In this tutorial, we study the extended Lorenz-84 model which is also treated in MatCont [Kuznetsov]. We use this model to showcase the automatic branch switching procedure to","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"Fold of periodic orbits from Bautin bifurcation point\nNS of periodic orbits from ZH bifurcation point\nNS of periodic orbits from HH bifurcation point.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"As this model has been studied in this tutorial, we do not give much details and refer to the corresponding tutorial to get the 2 parameters curves of Hopf / Fold bifurcations. ","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"The model is as follows","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"leftbeginarrayl\ndotX=-Y^2-Z^2-alpha X+alpha F-gamma U^2 \ndotY=X Y-beta X Z-Y+G \ndotZ=beta X Y+X Z-Z \ndotU=-delta U+gamma U X+T\nendarrayrighttagE","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"We recall the problem setting:","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"using Revise, ForwardDiff, Parameters, Plots, LinearAlgebra\nusing BifurcationKit\nconst BK = BifurcationKit\n\n# vector field\nfunction Lor(u, p, t = 0)\n\t@unpack α,β,γ,δ,G,F,T = p\n\tX,Y,Z,U = u\n\t[\n\t\t-Y^2 - Z^2 - α*X + α*F - γ*U^2,\n\t\tX*Y - β*X*Z - Y + G,\n\t\tβ*X*Y + X*Z - Z,\n\t\t-δ*U + γ*U*X + T\n\t]\nend\n\nparlor = (α = 1//4, β = 1., G = .25, δ = 1.04, γ = 0.987, F = 1.7620532879639, T = .0001265)\n\nz0 = [2.9787004394953343, -0.03868302503393752, 0.058232737694740085, -0.02105288273117459]\n\nrecordFromSolutionLor(x, p) = (u = BK.getVec(x);(X = u[1], Y = u[2], Z = u[3], U = u[4]))\nprob = BK.BifurcationProblem(Lor, z0, parlor, (@lens _.F);\n\trecord_from_solution = (x, p) -> (X = x[1], Y = x[2], Z = x[3], U = x[4]),)\n\nopts_br = ContinuationPar(p_min = -1.5, p_max = 3.0, ds = 0.002, dsmax = 0.05, n_inversion = 6, detect_bifurcation = 3, max_bisection_steps = 25, nev = 4, max_steps = 200, plot_every_step = 30)\n\t@set! opts_br.newton_options.verbose = false\n\t@set! opts_br.newton_options.tol = 1e-12\n\tbr = @time continuation(re_make(prob, params = setproperties(parlor;T=0.04,F=3.)),\n\t \tPALC(), opts_br;\n\t\tnormC = norminf, bothside = true)\n\nscene = plot(br, plotfold=false, markersize=4, legend=:topleft)","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#Two-parameters-curves-of-Fold-/-Hopf-bifurcation","page":"🟠 Lorenz-84 model, take 2","title":"Two parameters curves of Fold / Hopf bifurcation","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"We follow the Fold points in the parameter plane (TF). We tell the solver to consider br.specialpoint[5] and continue it.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"sn_codim2 = continuation(br, 5, (@lens _.T), ContinuationPar(opts_br, p_max = 3.2, p_min = -0.1, detect_bifurcation = 1, dsmin=1e-5, ds = -0.001, dsmax = 0.005, n_inversion = 10, save_sol_every_step = 1, max_steps = 130, max_bisection_steps = 55) ; plot = true,\n\tnormC = norminf,\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = false,\n\tbothside = false,\n\t)\n\nhp_codim2_1 = continuation(br, 3, (@lens _.T), ContinuationPar(opts_br, ds = -0.001, dsmax = 0.02, dsmin = 1e-4, n_inversion = 8, save_sol_every_step = 1, detect_bifurcation = 1) ; plot = false, verbosity = 0,\n\tnormC = norminf,\n\t# tangentAlgo = BorderedPred(),\n\tdetect_codim2_bifurcation = 2,\n\tupdate_minaug_every_step = 1,\n\tstart_with_eigen = true,\n\tbothside = true,\n\t)\n\nplot(sn_codim2, vars=(:F, :T), branchlabel = \"SN\")\nplot!(hp_codim2_1, vars=(:F, :T), branchlabel = \"Hopf1\", xlims = (1,2.7), ylims = (-0.06,0.06))","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#Fold-bifurcations-of-periodic-orbits-from-Bautin-bifurcation","page":"🟠 Lorenz-84 model, take 2","title":"Fold bifurcations of periodic orbits from Bautin bifurcation","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"We compute the branch of Fold of periodic orbits from the Bautin bifurcation (labelled :gh) in the previous figure. In this tutorial, we focus on orthogonal collocation but standard shooting would do too.","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"opts_fold_po = ContinuationPar(hp_codim2_1.contparams, dsmax = 0.01, detect_bifurcation = 0, max_steps = 30, detect_event = 0, ds = 0.001, plot_every_step = 10, a = 0.8)\n@set! opts_fold_po.newton_options.verbose = false\n@set! opts_fold_po.newton_options.tol = 1e-8\nfold_po = continuation(hp_codim2_1, 3, opts_fold_po, \n\t\tPeriodicOrbitOCollProblem(20, 3, meshadapt = false);\n\t\tnormC = norminf,\n\t\tδp = 0.02,\n\t\tupdate_minaug_every_step = 0,\n\t\tjacobian_ma = :minaug,\n\t\tverbosity = 0, plot = false,\n\t)\nplot!(fold_po, vars=(:F, :T), branchlabel = \"Fold-PO\")","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#NS-bifurcations-of-periodic-orbits-from-Hopf-Hopf-bifurcation","page":"🟠 Lorenz-84 model, take 2","title":"NS bifurcations of periodic orbits from Hopf-Hopf bifurcation","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"When we computed the curve of Hopf points, we detected a Hopf-Hopf bifurcation. We can branch from it to get the curve of NS points. This is done as follows:","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"opts_ns_po = ContinuationPar(hp_codim2_1.contparams, dsmax = 0.02, detect_bifurcation = 1, max_steps = 20, ds = -0.001, detect_event = 0)\n@set! opts_ns_po.newton_options.verbose = false\n@set! opts_ns_po.newton_options.tol = 1e-9\n@set! opts_ns_po.newton_options.max_iterations = 10\nns_po1 = continuation(hp_codim2_1, 4, opts_ns_po, \n\t\tPeriodicOrbitOCollProblem(20, 3, update_section_every_step = 1);\n\t\tdetect_codim2_bifurcation = 0,\n\t\tnormC = norminf,\n\t\tδp = 0.02,\n\t\tupdate_minaug_every_step = 1,\n\t\t# which of the 2 NS curves should we compute?\n\t\twhichns = 1,\n\t\tjacobian_ma = :minaug,\n\t\tverbosity = 3,\n\t\t)\nplot!(ns_po1, vars=(:F, :T), branchlabel = \"NS1\")","category":"page"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"ns_po2 = continuation(hp_codim2_1, 4, opts_ns_po, \n\t\tPeriodicOrbitOCollProblem(30, 3, update_section_every_step = 1);\n\t\tdetect_codim2_bifurcation = 0,\n\t\tnormC = norminf,\n\t\tδp = 0.02,\n\t\tupdate_minaug_every_step = 1,\n\t\t# which of the 2 NS curves should we compute?\n\t\twhichns = 2,\n\t\tjacobian_ma = :minaug,\n\t\t)\nplot!(ns_po2, vars=(:F, :T), branchlabel = \"NS2\")","category":"page"},{"location":"tutorials/ode/lorenz84-PO/#References","page":"🟠 Lorenz-84 model, take 2","title":"References","text":"","category":"section"},{"location":"tutorials/ode/lorenz84-PO/","page":"🟠 Lorenz-84 model, take 2","title":"🟠 Lorenz-84 model, take 2","text":"[Kuznetsov]: Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.","category":"page"},{"location":"ModulatedTW/#Modulated-travelling-wave-(MTW),-N_g1","page":"Modulated Travelling waves","title":"Modulated travelling wave (MTW), N_g=1","text":"","category":"section"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"warning: \nThis is work in progress","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"A modulated travelling wave with period T satisfies q(xt+T) = q(x-s Tt). Equivalently, using a moving frame to freeze the wave xi=x-st, it holds that tilde q(xit+T) = tilde q(xit) where tilde q(xit)=q(xi+stt). Hence, tilde q is a periodic solution to","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"partial_ttilde q = -sTcdottilde q+F(tilde qp)tageqMWP","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"Stability of the MTW is determined by the spectrum of the linearized time-T map associated with (eqMWP). ","category":"page"},{"location":"ModulatedTW/#References","page":"Modulated Travelling waves","title":"References","text":"","category":"section"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"[Beyn]: Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.","category":"page"},{"location":"ModulatedTW/","page":"Modulated Travelling waves","title":"Modulated Travelling waves","text":"[Sandstede]: Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.","category":"page"},{"location":"plotting/#Plotting","page":"Plot functions","title":"Plotting","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Pages = [\"plotting.md\"]\nDepth = 3","category":"page"},{"location":"plotting/#Standard-plots-using-the-plot-recipe-from-Plots.jl","page":"Plot functions","title":"Standard plots using the plot recipe from Plots.jl","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Plotting is provided by calling recipes to Plots.jl. It means that to plot a branch br, you just need to call","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"#]add Plots # You need to install Plots.jl before your first time using it!\nusing Plots\nplot(br)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"where br is a branch computed after a call to br = continuation(...). Plots can be customized using all the keyword arguments provided by Plots.jl. For example, we can change the plotting backend to the GR package and put a title on the plot by doing:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"gr()\nplot!(br, title = \"I have a branch!\")","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"or you can use a scatter plot","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"scatter(br)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Then to save the plot, use savefig, for example:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"savefig(\"myplot.png\")","category":"page"},{"location":"plotting/#Specific-plotting-keyword-arguments","page":"Plot functions","title":"Specific plotting keyword arguments","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The available arguments specific to our plotting methods are","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plotfold = true: plot the fold points with black dots\nputspecialptlegend = true: display the legend corresponding to the bifurcation points\nvars = nothing: see below\nplotstability = true: display the stability of the branch\nplotspecialpoints = true: plot the special (bifurcation) points on the branch\nbranchlabel = \"fold branch\": assign label to a branch which is printed in the legend\nlinewidthunstable: set the linewidth for the unstable part of the branch\nlinewidthstable: set the linewidth for the stable part of the branch\nplotcirclesbif = false use circles to plot bifurcation points\napplytoX = identity apply transformation applytoX to x-axis\napplytoY = identity apply transformation applytoY to y-axis","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"If you have several branches br1, br2, you can plot them in the same figure by doing","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br1, br2)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"in place of","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br1)\nplot!(br2)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"warn: Plot of bifurcation points\nThe bifurcation points for which the bisection was successful are indicated with circles and with squares otherwise.","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Note that the plot recipes use the parameter axis as xlabel, and the passed variable as ylabel.","category":"page"},{"location":"plotting/#Choosing-Variables","page":"Plot functions","title":"Choosing Variables","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"You can select which variables to plot using the keyword argument vars, for example:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br, vars = (:param, :x))","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The available symbols are :x, :param, :itnewton, :itlinear, :ds, :θ, :n_unstable, :n_imag, :stable, :step,... and:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"x if record_from_solution (see continuation) returns a Number.\nx1, x2,... if record_from_solution returns a Tuple.\nthe keys of the NamedTuple returned by record_from_solution.","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The available symbols are provided by calling propertynames(br.branch).","category":"page"},{"location":"plotting/#Plotting-bifurcation-diagrams","page":"Plot functions","title":"Plotting bifurcation diagrams","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"To do this, you just need to call","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(diagram)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"where diagram is a branch computed after a call to diagram = bifurcationdiagram(...). You can use the keywords provided by Plots.jl and the different backends. You can thus call scatter(diagram). In addition to the options for plotting branches (see above), there are specific arguments available for bifurcation diagrams","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"code specify the part of the bifurcation diagram to plot. For example code = (1,1,) plots the part after the first branch of the first branch of the root branch.\nlevel = (-Inf, Inf) restrict the branching level for plotting.","category":"page"},{"location":"plotting/#Plotting-without-the-plot-recipe","page":"Plot functions","title":"Plotting without the plot recipe","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"What if you don't want to use Plots.jl? You can define your own plotting functions using the internal fields of br which is of type ContResult. For example, in PyPlot, Gadfly, GR, etc., you can do the following to plot the branch (like the plot recipe plot(br, vars = (:param, :x))):","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"plot(br.branch.param, br.branch.x)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"You can also have access to the stability of the points by using br.stable. More information concerning the fields can be found in ContResult. For example, you can change the color depending on the stability:","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"col = [stb ? :green : :red for stb in br.stable]\nplot(br.param, br.x, color=col)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"You can also plot the spectrum at a specific continuation step::Int by calling","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"# get the eigenvalues\neigvals = br.eig[step].eigenvals\n\n# plot them in the complex plane\nscatter(real.(eigvals), imag.(eigvals))","category":"page"},{"location":"plotting/#Standard-plots-using-the-Makie.jl-[Experimental]","page":"Plot functions","title":"Standard plots using the Makie.jl [Experimental]","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"Plotting is also provided by calling recipes to Makie.jl. It means that to plot a branch br, you just need to call","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"#]add GLMakie # You need to install GLMakie.jl before your first time using it!\nusing GLMakie\nBifurcationKit.plot(br)","category":"page"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"The keyword arguments to BifurcationKit.plot are the same as decribed above in the page. You can also combine diagrams with BifurcationKit.plot(br1, br2) or use BifurcationKit.plot!(ax, br) to add a branch to an existing plot.","category":"page"},{"location":"plotting/#Example","page":"Plot functions","title":"Example","text":"","category":"section"},{"location":"plotting/","page":"Plot functions","title":"Plot functions","text":"using Revise, GLMakie, BifurcationKit\nMakie.inline!(true)\nq = 1/0\nk = 2\nF(x, p) = (@. p + x - x^(k+1)/(k+1))\nprob = BifurcationProblem(F, [0.8], 1., (@lens _); record_from_solution = (x,p) -> x[1])\nopts = ContinuationPar(dsmax = 0.1, dsmin = 1e-3, ds = -0.001, p_min = -1., p_max = 1.)\nbr = continuation(prob, PALC(), opts)\nBifurcationKit.plot(br)","category":"page"},{"location":"pd/#Period-doubling-point","page":"Period-doubling","title":"Period-doubling point","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"Pages = [\"pd.md\"]\nDepth = 2","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"At a period-doubling (PD) bifurcation of a periodic orbit gamma (with period T) for parameter value p_0 for the Cauchy problem ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"fracdudt=F(up)tagE","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"the eigenvalues (Floquet coefficients) of the monodromy operator mathcal M=Y(T) solution to","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"fracdYdt=A(t)Y(t) Y(0)=I_n","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"contain the simple eigenvalue mu=-1.","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"There are two ways to compute the normal form of this bifurcation","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"using the Poincaré return map [Kuznetsov]\nusing the method of [Iooss] see also [Kuz2]","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"You can obtain the normal form of a PD bifurcation using ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"pd = get_normal_form(br, ind; prm = false)","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where prm indicates whether you want to use the method based on Poincaré return map (PRM) or the one based on Iooss method.","category":"page"},{"location":"pd/#Normal-form-based-on-Poincaré-return-map","page":"Period-doubling","title":"Normal form based on Poincaré return map","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"Given a transversal section Sigma to gamma at gamma(0), the Poincaré return map mathcal P associates to each point xinSigma close to gamma(0) the first point mathcal P(xp)inSigma where the orbit of (E) with initial condition x intersects again Sigma at mathcal P(xp). Hence, the discrete map x_n+1=mathcal P(x_np) has normal form","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"x_n+1 = -x_n+cx_n^3+","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where [Kuz2]","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"c =frac16leftlangle p^* mathcalC(p p p)+3 mathcalBleft(pleft(I_n-1-mathcalAright)^-1 mathcalB(p p)right)rightrangle","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where mathcal C=d^3mathcal P(gamma(0)), mathcal B = d^2mathcal P(gamma(0)) and mathcal A = dmathcal P(gamma(0)). Also:","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"mathcalA p=-p mathcalA^mathrmT p^*=-p^*","category":"page"},{"location":"pd/#Normal-form-based-on-Iooss-method","page":"Period-doubling","title":"Normal form based on Iooss method","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"This is based on [Iooss],[Kuz2]. Suppose that the T periodic orbit gamma(tau) has a Period-Doubling bifurcation for a parameter value p_0. Locally, the orbits can be represented by ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"x(tau) = gamma(tau)+Q_0(tau)xi+Phi(tau xi)","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"where ","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"leftbeginarrayl\nfracd taud t=1+a_0cdot(p-p_0)+a xi^2+cdots \nfracd xid tau=c_0cdot(p-p_0)xi+c xi^3+cdots\nendarrayright","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"with center manifold correction Phi(tau xi) being 2T periodic in tau and Q_0(tau) is the Floquet operator.","category":"page"},{"location":"pd/#References","page":"Period-doubling","title":"References","text":"","category":"section"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"[Kuznetsov]: Yu. A. Kuznetsov, \"Elements of Applied Bifurcation Theory\", 2nd ed., 1998.","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"[Kuz2]: Kuznetsov et al., “Numerical Periodic Normalization for Codim 1 Bifurcations of Limit Cycles.”","category":"page"},{"location":"pd/","page":"Period-doubling","title":"Period-doubling","text":"[Iooss]: Iooss, \"Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.\", 1988","category":"page"},{"location":"MooreSpence/#Moore-Penrose-continuation","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"warning: WIP\nThis is work in progress. The interface will be improved in the future.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"This is one of the various continuation methods implemented in BifurcationKit.jl. It is set by the option alg = MoorePenrose() in continuation. See also MoorePenrose for more information.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"For solving","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"mathbb R^nni F(xp) = 0 quadtagE","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"using a Newton algorithm, we miss an equation. Hence, we proceed as follows [Meijer]. Starting from a predictor (x_1p_1), we look for the solution to (E) that is closest to (x_1p_1). Hence, we optimise","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"min_(xp) (xp)-(x_1p_1) text such that F(xp)=0 tagMS","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"It can be interpreted as a PALC in which the hyperplane is adapted at every step. ","category":"page"},{"location":"MooreSpence/#Predictor","page":"Moore-Penrose continuation","title":"Predictor","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"The possible predictors tangent::AbstractTangentPredictor are listed in Predictors - Correctors. They can be used to create a Moore-Penrose algorithm like MoorePenrose(tangent = PALC())","category":"page"},{"location":"MooreSpence/#Corrector","page":"Moore-Penrose continuation","title":"Corrector","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"The corrector is the Gauss Newton algorithm applied to (MS).","category":"page"},{"location":"MooreSpence/#Linear-Algebra","page":"Moore-Penrose continuation","title":"Linear Algebra","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"Let us discuss more about the norm and dot product. First, the option normC continuation specifies the norm used to evaluate the distance in (MS). The dot product (resp. norm) used in the (iterative) linear solvers is LinearAlgebra.dot (resp. LinearAlgebra.norm). It can be changed by importing these functions and redefining it. Note that by default, the L^2 norm is used.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"The linear solver for the linear problem associated to (MS) is set by the option linearAlgo in continuation: it is one of Bordered linear solvers (BLS).","category":"page"},{"location":"MooreSpence/#Algorithm-for-solving-(MS)","page":"Moore-Penrose continuation","title":"Algorithm for solving (MS)","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"Let us write yequiv(xp)inmathbb R^N+1. In order to solve for the argmin, we apply the newton algorithm with jacobian belonging to mathbb R^Ntimes (N+1):","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"y^k+1 = y^k -d_yF(y^k)^+F(y^k)","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"where the superscript ^+ indicates the Moore-Penrose pseudoinverse of rank N.","category":"page"},{"location":"MooreSpence/#Direct-case","page":"Moore-Penrose continuation","title":"Direct case","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"In this case, triggered by the option MoorePenrose(method = BifurcationKit.direct), the pseudoinverse is computed with \\.","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"the option MoorePenrose(method = BifurcationKit.pInv), the pseudoinverse is computed with pinv.","category":"page"},{"location":"MooreSpence/#Iterative-case","page":"Moore-Penrose continuation","title":"Iterative case","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"In this case, triggered by the option MoorePenrose(method = BifurcationKit.iterative), the pseudoinverse is computed with an iterative method described in [Meijer]:","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"leftbeginarrayl\ny_1^j+1=y_1^j-left(beginarrayc\nF_yleft(y_1^jright) \nleft(phi_1^jright)^top\nendarrayright)^-1left(beginarrayc\nFleft(y_1^jright) \n0\nendarrayright) \nphi_1^j+1=left(beginarrayc\nF_yleft(y_1^j+1right) \nleft(phi_1^jright)^top\nendarrayright)^-1left(beginarrayl\n0 \n1\nendarrayright) quad j=012 ldots\nendarrayright","category":"page"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"We initialise phi_1^0 with the tangent.","category":"page"},{"location":"MooreSpence/#Step-size-control","page":"Moore-Penrose continuation","title":"Step size control","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"Each time the corrector fails, the step size ds is halved. This has the disadvantage of having lost Newton iterations (which costs time) and imposing small steps (which can be slow as well). To prevent this, the step size is controlled internally with the idea of having a constant number of Newton iterations per point. This is in part controlled by the aggressiveness factor a in ContinuationPar.","category":"page"},{"location":"MooreSpence/#References","page":"Moore-Penrose continuation","title":"References","text":"","category":"section"},{"location":"MooreSpence/","page":"Moore-Penrose continuation","title":"Moore-Penrose continuation","text":"[Meijer]: Meijer, Dercole, and Oldeman, “Numerical Bifurcation Analysis.”","category":"page"}] } diff --git a/dev/simplebp/index.html b/dev/simplebp/index.html index 413c5f31..feb269d1 100644 --- a/dev/simplebp/index.html +++ b/dev/simplebp/index.html @@ -1,3 +1,3 @@ Simple branch point · Bifurcation Analysis in Julia

      Simple bifurcation branch point

      References

      The general method is exposed in Golubitsky, Martin, David G Schaeffer, and Ian Stewart. Singularities and Groups in Bifurcation Theory. New York: Springer-Verlag, 1985, VI.1.d page 295

      A simple branch point $(x_0,p_0)$ for the problem $F(x,p)=0$ satisfies $\dim \ker dF(x_0,p_0) = 1$. At such point, we can apply Lyapunov-Schmidt reduction to transform the initial problem in large dimensions to a scalar polynomial ($\delta p \equiv p-p_0$):

      \[a\delta p + z\left(b_1\delta p + \frac{b_2}{2}z + \frac{b_3}{6}z^2\right) = 0 \tag{E}\]

      whose solutions give access to all solutions in a neighborhood of $(x,p)$.

      More precisely, if $\ker dF(x_0,p_0) = \mathbb R\zeta$, one can show that $x_0+z\zeta$ is close to a solution on a new branch, thus satisfying $F(x_0+z\zeta,p_0+\delta p)\approx 0$.

      In the above scalar equation,

      • if $a\neq 0$, this is a Saddle-Node bifurcation
      • if $a=0,b_2\neq 0$, the bifurcation point is a Transcritical one where the bifurcated branch exists on each side of $p$.
      • if $a=0,b_2=0, b_3\neq 0$, the bifurcation point is a Pitchfork one where the bifurcated branch only exists on one side of $p$. If it exists at smaller values then $p$, this is a subcritical Pitchfork bifurcation. In the other case, this is a supercritical Pitchfork bifurcation.

      Normal form computation

      The reduced equation (E) can be automatically computed as follows

      get_normal_form(br::ContResult, ind_bif::Int ;
      -	verbose = false, ζs = nothing, lens = getlens(br))

      where prob is the bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BranchPoint.

      Note

      You should not need to call get_normal_form except if you need the full information about the branch point.

      + verbose = false, ζs = nothing, lens = getlens(br))

      where prob is the bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type BranchPoint.

      Note

      You should not need to call get_normal_form except if you need the full information about the branch point.

      diff --git a/dev/simplehopf/index.html b/dev/simplehopf/index.html index 4d84d90b..82c0be31 100644 --- a/dev/simplehopf/index.html +++ b/dev/simplehopf/index.html @@ -3,5 +3,5 @@ -\mathbf{J} \Psi_{001} &=\mathbf{F}_{01} \\ (2 i \omega-\mathbf{J}) \Psi_{200} &=\mathbf{F}_{20}(\zeta, \zeta) \\ -\mathbf{J} \Psi_{110} &=2 \mathbf{F}_{20}(\zeta, \bar{\zeta}). -\end{aligned}\]

      Normal form computation

      The normal form (E) is automatically computed as follows

      get_normal_form(br::ContResult, ind_bif::Int ;
      -	verbose = false, ζs = nothing, lens = getlens(br))

      where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The above call returns an object of type Hopf.

      Note

      You should not need to call get_normal_form except if you need the full information about the branch point.

      References

      • Haragus

        Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

      +\end{aligned}\]

      and where

      $

      \mathbf{F}(x,p)-\mathbf{J}x := \sum{1\leq q+l\leq p}\mathbf{F}{ql}(x^{(q)},p^{(l)})+o(\|u\|+\|p\|)^p. $

      with $\mathbf{F}_{ql}$ a $(q+l)$-linear map

      Normal form computation

      The normal form (E) is automatically computed as follows

      get_normal_form(br::ContResult, ind_bif::Int ;
      +	verbose = false, ζs = nothing, lens = getlens(br))

      where prob is a bifurcation problem. br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The above call returns an object of type Hopf.

      Note

      You should not need to call get_normal_form except if you need the full information about the branch point.

      References

      • Haragus

        Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

      diff --git a/dev/tutorials/BrusselatorFF/index.html b/dev/tutorials/BrusselatorFF/index.html index 49d68973..a8085d57 100644 --- a/dev/tutorials/BrusselatorFF/index.html +++ b/dev/tutorials/BrusselatorFF/index.html @@ -170,4 +170,4 @@ plot = true, verbosity = 3, plot_solution = (x,p ; kw...) -> plot!(x[1:nx];kw...), - normC = x->norm(x,Inf))

      which leads to

      References

      • Tzou

        Tzou, J. C., Y.-P. Ma, A. Bayliss, B. J. Matkowsky, and V. A. Volpert. Homoclinic Snaking near a Codimension-Two Turing-Hopf Bifurcation Point in the Brusselator Model.” Physical Review E 87, no. 2 (February 14, 2013): 022908. https://doi.org/10.1103/PhysRevE.87.022908.

      + normC = x->norm(x,Inf))

      which leads to

      References

      • Tzou

        Tzou, J. C., Y.-P. Ma, A. Bayliss, B. J. Matkowsky, and V. A. Volpert. Homoclinic Snaking near a Codimension-Two Turing-Hopf Bifurcation Point in the Brusselator Model.” Physical Review E 87, no. 2 (February 14, 2013): 022908. https://doi.org/10.1103/PhysRevE.87.022908.

      diff --git a/dev/tutorials/Langmuir/index.html b/dev/tutorials/Langmuir/index.html index 14f47d55..532844d8 100644 --- a/dev/tutorials/Langmuir/index.html +++ b/dev/tutorials/Langmuir/index.html @@ -94,55 +94,55 @@ └─────────────┴──────────────────────┴────────────────┘
      scene = plot(X, out.u)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We then continue the previous guess and find this very nice folded structure with many Hopf bifurcation points.

      # careful here, in order to use Arpack.eig, you need rather big space
       # or compute ~100 eigenvalues
       opts_cont = ContinuationPar(
      @@ -167,542 +167,542 @@
       scene = plot(br, title="N=$N")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      plot(layout = grid(4, 3))
       for (ii, s) in pairs(br.sol)
       	plot!(X, s.x, xlabel = "ν = $(round(s.p,digits=3))", subplot = ii, label="",tickfont = (7, :black), ylims=(-1,1.5))
      @@ -710,412 +710,412 @@
       title!("")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of Hopf and Fold points

      Let us study the continuation of Hopf and Fold points and show that they merge at a Bogdanov-Takens bifurcation point:

      # compute branch of Fold points from 7th bifurcation point on br
       sn_codim2 = continuation(br, 7, (@lens _.Δx),
       	ContinuationPar(opts_cont, p_min = -2, p_max = 0.12, ds = -0.01, dsmax = 0.01, tol_stability = 1e-8, max_steps = 325, nev=23) ;
      @@ -1149,75 +1149,75 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of periodic orbits (FD)

      We would like to compute the branches of periodic solutions from the Hopf points. We do this automatic branch switching as follows

      # parameters for newton
       opt_po = NewtonPar(tol =  1e-10, verbose = true, max_iterations = 50)
       
      @@ -1248,4 +1248,4 @@ 

      and we obtain the following graph. It is interesting to note that the periodic solutions converge to an homoclinic orbit here with a very large period.

      We can do this for the other Hopf points as well. Note that, we have to increase the number of time sections M to improve the convergence to the homoclinic orbits.

      Here are some examples of periodic solutions.

      • Köpf

        Köpf and Thiele, Emergence of the Bifurcation Structure of a Langmuir–Blodgett Transfer Model., 2014

      + normC = norminf)

      and we obtain the following graph. It is interesting to note that the periodic solutions converge to an homoclinic orbit here with a very large period.

      We can do this for the other Hopf points as well. Note that, we have to increase the number of time sections M to improve the convergence to the homoclinic orbits.

      Here are some examples of periodic solutions.

      • Köpf

        Köpf and Thiele, Emergence of the Bifurcation Structure of a Langmuir–Blodgett Transfer Model., 2014

      diff --git a/dev/tutorials/Swift-Hohenberg1d/index.html b/dev/tutorials/Swift-Hohenberg1d/index.html index 35b8f739..71b135f6 100644 --- a/dev/tutorials/Swift-Hohenberg1d/index.html +++ b/dev/tutorials/Swift-Hohenberg1d/index.html @@ -93,4 +93,4 @@ - # 3, bp at λ ≈ +0.48386330 ∈ (+0.48386287, +0.48386330), |δp|=4e-07, [converged], δ = ( 1, 0), step = 43, eigenelements in eig[ 44], ind_ev = 3 - # 4, bp at λ ≈ +0.53115107 ∈ (+0.53070912, +0.53115107), |δp|=4e-04, [converged], δ = ( 1, 0), step = 47, eigenelements in eig[ 48], ind_ev = 4 - # 5, bp at λ ≈ +0.86889123 ∈ (+0.86887742, +0.86889123), |δp|=1e-05, [converged], δ = ( 1, 0), step = 71, eigenelements in eig[ 72], ind_ev = 5 -- # 6, endpoint at λ ≈ +1.00000000, step = 81

      We can access the different branches with BK.getBranch(diagram, (1,)). Alternatively, you can plot a specific branch:

      plot(diagram; code = (1,), plotfold = false,  markersize = 2, putspecialptlegend = false, xlims=(-1,1))

      References

      +- # 6, endpoint at λ ≈ +1.00000000, step = 81

      We can access the different branches with BK.getBranch(diagram, (1,)). Alternatively, you can plot a specific branch:

      plot(diagram; code = (1,), plotfold = false,  markersize = 2, putspecialptlegend = false, xlims=(-1,1))

      References

      diff --git a/dev/tutorials/autocatalytic/index.html b/dev/tutorials/autocatalytic/index.html index 4ae7baa2..9165d87a 100644 --- a/dev/tutorials/autocatalytic/index.html +++ b/dev/tutorials/autocatalytic/index.html @@ -110,54 +110,54 @@ plot_solution = (x, p; k...) -> plotsol!(x[1:end-1];k...)) front = newton(probtw, NewtonPar()) -println("front speed s = ", front.u[end], ", norm = ", front.u[1:end-1] |> norminf)
      front speed s = -0.262712550492746, norm = 1.0000000000000002
      plotsol(front.u[1:end-1], title="front solution")
      +println("front speed s = ", front.u[end], ", norm = ", front.u[1:end-1] |> norminf)
      front speed s = -0.2627125504927461, norm = 1.0000000000000002
      plotsol(front.u[1:end-1], title="front solution")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of front solutions

      Following [Malham], the modulated fronts are solutions of the following DAE

      \[\begin{array}{l}\tag{DAE} u_{t}=a u_{x x}+s\cdot u_x-u f(v)\\ v_{t}=v_{x x}+s\cdot v_x+u f(v)\\ @@ -182,66 +182,66 @@

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts. Let us try to compute them.

      Branch of modulated fronts

      To branch from the Hopf bifurcation point, we just have to pass the mass matrix as follows:

      # we compute the periodic solutions using Mt time steps and a Trapezoidal time stepper
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +

      We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts. Let us try to compute them.

      Branch of modulated fronts

      To branch from the Hopf bifurcation point, we just have to pass the mass matrix as follows:

      # we compute the periodic solutions using Mt time steps and a Trapezoidal time stepper
       # note that we pass the parameter massmatrix which
       # allows to solver the DAE
       Mt = 30
      @@ -291,201 +291,6 @@ 

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Let us plot one modulated front:

      modfront = BK.get_periodic_orbit(br_po, length(br_po))
      +plot(br);plot!(br_po, label = "modulated fronts")

      Let us plot one modulated front:

      modfront = BK.get_periodic_orbit(br_po, length(br_po))
       plot(plot(modfront.t, modfront.u[end,:], xlabel = "t", ylabel = "s", label = ""),
      -	contour(modfront.t, X, modfront.u[1:N,:], color = :viridis, xlabel = "t", title = "u for a = $(round(br_po.sol[length(br_po)].p,digits=4))", fill = true, ylims=(-10,10)))
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      References

      • Balmforth

        N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.

      • Malham

        S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.

      • Beyn

        Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.

      + contour(modfront.t, X, modfront.u[1:N,:], color = :viridis, xlabel = "t", title = "u for a = $(round(br_po.sol[length(br_po)].p,digits=4))", fill = true, ylims=(-10,10)))

      References

      • Balmforth

        N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.

      • Malham

        S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.

      • Beyn

        Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.

      diff --git a/dev/tutorials/autocatalyticAuto/index.html b/dev/tutorials/autocatalyticAuto/index.html index 218a73ef..e3a5a7d9 100644 --- a/dev/tutorials/autocatalyticAuto/index.html +++ b/dev/tutorials/autocatalyticAuto/index.html @@ -121,56 +121,56 @@ │ 3 │ 9.5457e-03 │ 1 │ │ 4 │ 4.0213e-05 │ 1 │ │ 5 │ 8.7134e-10 │ 1 │ -│ 6 │ 1.3845e-14 │ 1 │ +│ 6 │ 1.2310e-14 │ 1 │ └─────────────┴──────────────────────┴────────────────┘ -norm front = 1.0, speed = 0.2627125504927469
      plotsol(front.u[1:end-1], title="front solution")
      +norm front = 1.0, speed = 0.26271255049274705
      plotsol(front.u[1:end-1], title="front solution")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of front solutions

      Following [Malham], the modulated fronts are solutions of the following DAE

      \[\begin{array}{l}\tag{DAE} u_{t}=a u_{x x}+s\cdot u_x-u f(v)\\ v_{t}=v_{x x}+s\cdot v_x+u f(v)\\ @@ -181,67 +181,67 @@

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts.

      References

      • Balmforth

        N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.

      • Malham

        S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.

      • Beyn

        Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We have detected a Hopf instability in front dynamics, this will give rise of modulated fronts.

      References

      • Balmforth

        N. J. Balmforth, R. V. Craster, and S. J. A. Malham. Unsteady fronts in an autocatalytic system. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 455(1984):1401–1433, 1999.

      • Malham

        S. J. A. Malham and M. Oliver. Accelerating fronts in autocatalysis. R. Soc. Lond. Proc. Ser. A Math. Phys. Eng. Sci., 456(1999):1609–1624, 2000.

      • Beyn

        Beyn, Wolf-Jürgen, and Vera Thümmler. “Phase Conditions, Symmetries and PDE Continuation.” In Numerical Continuation Methods for Dynamical Systems: Path Following and Boundary Value Problems Springer Netherlands, 2007. https://doi.org/10.1007/978-1-4020-6356-5_10.

      diff --git a/dev/tutorials/cgl1dwave/index.html b/dev/tutorials/cgl1dwave/index.html index 8e56be49..05ce518e 100644 --- a/dev/tutorials/cgl1dwave/index.html +++ b/dev/tutorials/cgl1dwave/index.html @@ -98,9 +98,9 @@ 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 r ≈ +0.00000138 ∈ (-0.00000276, +0.00000138), |δp|=4e-06, [converged], δ = ( 2, 2), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, nd at r ≈ +0.99868554 ∈ (+0.99868473, +0.99868554), |δp|=8e-07, [converged], δ = ( 4, 4), step = 16, eigenelements in eig[ 17], ind_ev = 6 -- # 3, endpoint at r ≈ +2.50000000, step = 24 +- # 1, hopf at r ≈ +0.00000138 ∈ (-0.00000276, +0.00000138), |δp|=4e-06, [converged], δ = ( 2, 2), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, nd at r ≈ +0.99868554 ∈ (+0.99868473, +0.99868554), |δp|=8e-07, [converged], δ = ( 4, 4), step = 16, eigenelements in eig[ 17], ind_ev = 6 +- # 3, endpoint at r ≈ +2.50000000, step = 24

      The first bifurcation point is a regular Hopf bifurcation in the zero mode, i.e. $u(x, t) = u_0\cos(\omega t +\phi)$ with no spatial structure. The second bifurcation point, labelled nd is a Hopf bifurcation with $O(2)$ symmetry group generated by the translations $T_z\cdot u(x) = u(x+y)$ and the reflection $S\cdot u(x) = u(-x)$.

      Computation of the travelling wave

      We focus on the $O(2)$-Hopf (second bifurcation point in br), with frequency $\omega>0$, for which no normal form is currently implemented in BifurcationKit.jl. We write $\zeta_0,\zeta_1$ two eigenvectors associated with the eigenvalue $i\omega$ such that

      \[T_z\cdot\zeta_0 = e^{im z}\zeta_0,\quad T_z\cdot\zeta_1 = e^{-im z}\zeta_1,\quad S\cdot\zeta_0 = \zeta_1,\quad S\cdot\zeta_1 = \zeta_0.\]

      By the center manifold theory[Haragus], one has

      \[u = A(t)\zeta_0+B(t)\zeta_1+\overline{A(t)\zeta_0}+\overline{B(t)\zeta_1}+\text{small terms}\]

      Using the normal form, one finds standing waves $(A(t),B(t)) = (r_0e^{i\omega t}, r_0e^{i\omega t})$ with $r_0\geq 0$ and travelling waves $(A(t),B(t)) = (r_0e^{i\omega t}, 0)$ at first order in $A,B$. This provides us with a way to compute the initial guess for the travelling waves as written in the following function:

      function guessFromHopfO2(branch, ind_hopf, eigsolver, M, A, B = 0.; phase = 0, k = 1.)
       	specialpoint = branch.specialpoint[ind_hopf]
       
      @@ -139,51 +139,51 @@
       plot!(uold, color = :blue, label="guess")
      - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Note that in the following code, a generalized eigensolver is automatically created during the call to continuation which properly computes the stability of the wave.

      amplitude(x) = maximum(x) - minimum(x)
       optn = NewtonPar(tol = 1e-8, verbose = true, max_iterations = 10)
       opt_cont_br = ContinuationPar(p_min = 0.015, p_max = 2.5, newton_options = optn, ds= 0.001, dsmax = 0.1, detect_bifurcation = 3, nev = 10, max_steps = 190, n_inversion = 6)
      @@ -198,160 +198,152 @@
       plot(br, br_TW, legend = :bottomright, branchlabel =["","TW"])
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      We note that the branch of travelling wave solutions has a Hopf bifurcation point at which point Modulated Travelling waves will emerge. This will be analyzed in the future.

      References

      • Haragus

        Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We note that the branch of travelling wave solutions has a Hopf bifurcation point at which point Modulated Travelling waves will emerge. This will be analyzed in the future.

      References

      • Haragus

        Haragus, Mariana, and Gérard Iooss. Local Bifurcations, Center Manifolds, and Normal Forms in Infinite-Dimensional Dynamical Systems. London: Springer London, 2011. https://doi.org/10.1007/978-0-85729-112-7.

      diff --git a/dev/tutorials/detonationEngine/index.html b/dev/tutorials/detonationEngine/index.html index 73cf675d..a65f65fc 100644 --- a/dev/tutorials/detonationEngine/index.html +++ b/dev/tutorials/detonationEngine/index.html @@ -101,492 +101,492 @@ Scene = title!("") - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      br
       ┌─ Curve type: EquilibriumCont
        ├─ Number of points: 152
      @@ -598,13 +598,13 @@
       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 up ≈ +0.56970295 ∈ (+0.56970262, +0.56970295), |δp|=3e-07, [converged], δ = ( 2,  2), step =  74, eigenelements in eig[ 75], ind_ev =   2
      -- #  2,     hopf at up ≈ +0.58997693 ∈ (+0.58997627, +0.58997693), |δp|=7e-07, [converged], δ = ( 2,  2), step =  76, eigenelements in eig[ 77], ind_ev =   4
      -- #  3,     hopf at up ≈ +0.67245132 ∈ (+0.67243040, +0.67245132), |δp|=2e-05, [converged], δ = ( 2,  2), step =  84, eigenelements in eig[ 85], ind_ev =   6
      -- #  4,     hopf at up ≈ +0.86069748 ∈ (+0.86069747, +0.86069748), |δp|=1e-08, [converged], δ = (-2, -2), step = 102, eigenelements in eig[103], ind_ev =   6
      -- #  5,     hopf at up ≈ +1.05349842 ∈ (+1.05349825, +1.05349842), |δp|=2e-07, [converged], δ = (-2, -2), step = 120, eigenelements in eig[121], ind_ev =   4
      -- #  6,     hopf at up ≈ +1.15401807 ∈ (+1.15401772, +1.15401807), |δp|=3e-07, [converged], δ = (-2, -2), step = 129, eigenelements in eig[130], ind_ev =   2
      -- #  7, endpoint at up ≈ +1.40000000,                                                                     step = 151
      +- #  1,     hopf at up ≈ +0.56970295 ∈ (+0.56970262, +0.56970295), |δp|=3e-07, [converged], δ = ( 2,  2), step =  74, eigenelements in eig[ 75], ind_ev =   2
      +- #  2,     hopf at up ≈ +0.58997693 ∈ (+0.58997627, +0.58997693), |δp|=7e-07, [converged], δ = ( 2,  2), step =  76, eigenelements in eig[ 77], ind_ev =   4
      +- #  3,     hopf at up ≈ +0.67245132 ∈ (+0.67243040, +0.67245132), |δp|=2e-05, [converged], δ = ( 2,  2), step =  84, eigenelements in eig[ 85], ind_ev =   6
      +- #  4,     hopf at up ≈ +0.86069748 ∈ (+0.86069747, +0.86069748), |δp|=1e-08, [converged], δ = (-2, -2), step = 102, eigenelements in eig[103], ind_ev =   6
      +- #  5,     hopf at up ≈ +1.05349842 ∈ (+1.05349825, +1.05349842), |δp|=2e-07, [converged], δ = (-2, -2), step = 120, eigenelements in eig[121], ind_ev =   4
      +- #  6,     hopf at up ≈ +1.15401807 ∈ (+1.15401772, +1.15401807), |δp|=3e-07, [converged], δ = (-2, -2), step = 129, eigenelements in eig[130], ind_ev =   2
      +- #  7, endpoint at up ≈ +1.40000000,                                                                     step = 151
       

      We have detected 6 Hopf bifurcations. We now study the periodic orbits branching from them.

      Computing the branches of Travelling waves

      The periodic orbits emanating from the Hopf points look like travelling waves. This is intuitive because the equation is mostly advective as the diffusion coefficients $\nu_i$ are small. We will thus seek for travelling waves instead of periodic orbits. The advantage is that the possible Neimark-Sacker bifurcation is transformed into a regular Hopf one which allows the study of modulated travelling waves.

      As we will do the same thing 3 times, we bundle the procedure in functions. We first use the regular Hopf normal form to create a guess for the travelling wave:

      function getGuess(br, nb; δp = 0.005)
       	nf = get_normal_form(br, nb; verbose  = false)
       	pred = predictor(nf, δp)
      @@ -639,860 +639,858 @@
       Scene = title!("")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Building the full diagram

      branches = [computeBranch(br, i) for i in 1:3]
       plot(br, branches..., legend=:topleft, xlims = (0.5, 1.25), ylims=(0.5, 2.3))
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      References

      • Koch

        Koch, James, Mitsuru Kurosaka, Carl Knowlen, and J. Nathan Kutz. “Multi-Scale Physics of Rotating Detonation Engines: Autosolitons and Modulational Instabilities.” ArXiv:2003.06655 [Nlin, Physics:Physics], March 14, 2020. http://arxiv.org/abs/2003.06655.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      References

      • Koch

        Koch, James, Mitsuru Kurosaka, Carl Knowlen, and J. Nathan Kutz. “Multi-Scale Physics of Rotating Detonation Engines: Autosolitons and Modulational Instabilities.” ArXiv:2003.06655 [Nlin, Physics:Physics], March 14, 2020. http://arxiv.org/abs/2003.06655.

      diff --git a/dev/tutorials/ks1d/index.html b/dev/tutorials/ks1d/index.html index 9594cdcf..bf67ceb8 100644 --- a/dev/tutorials/ks1d/index.html +++ b/dev/tutorials/ks1d/index.html @@ -64,4 +64,4 @@ )

      Plotting the result can be done using

      plot(diagram; code = (), plotfold = false,  markersize = 3, putspecialptlegend = false,
       	 plotcirclesbif = true, applytoX = x->2/x, vars = (:param, :nrm),
       	 xlim = (0,150), ylim=(0,8))
      -title!("#branches = $(size(diagram))")

      +title!("#branches = $(size(diagram))")

      diff --git a/dev/tutorials/mittelmann/index.html b/dev/tutorials/mittelmann/index.html index 125a04da..b1c7cd7f 100644 --- a/dev/tutorials/mittelmann/index.html +++ b/dev/tutorials/mittelmann/index.html @@ -98,293 +98,293 @@ If `br` is the name of the branch, ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]` -- # 1, bp at λ ≈ +0.36787944 ∈ (+0.36787944, +0.36787944), |δp|=2e-10, [converged], δ = ( 1, 0), step = 18, eigenelements in eig[ 19], ind_ev = 1 -- # 2, nd at λ ≈ +0.27255474 ∈ (+0.27255474, +0.27255937), |δp|=5e-06, [converged], δ = ( 2, 0), step = 33, eigenelements in eig[ 34], ind_ev = 3 -- # 3, bp at λ ≈ +0.15215124 ∈ (+0.15215124, +0.15215818), |δp|=7e-06, [converged], δ = ( 1, 0), step = 48, eigenelements in eig[ 49], ind_ev = 4 -- # 4, nd at λ ≈ +0.03551852 ∈ (+0.03551852, +0.03554981), |δp|=3e-05, [converged], δ = ( 2, 0), step = 76, eigenelements in eig[ 77], ind_ev = 6 -- # 5, endpoint at λ ≈ +0.02500000, step = 83

      You should see the following result:

      title!("")
      +- # 1, bp at λ ≈ +0.36787944 ∈ (+0.36787944, +0.36787944), |δp|=2e-10, [converged], δ = ( 1, 0), step = 18, eigenelements in eig[ 19], ind_ev = 1 +- # 2, nd at λ ≈ +0.27255474 ∈ (+0.27255474, +0.27255937), |δp|=5e-06, [converged], δ = ( 2, 0), step = 33, eigenelements in eig[ 34], ind_ev = 3 +- # 3, bp at λ ≈ +0.15215124 ∈ (+0.15215124, +0.15215818), |δp|=7e-06, [converged], δ = ( 1, 0), step = 48, eigenelements in eig[ 49], ind_ev = 4 +- # 4, nd at λ ≈ +0.03551852 ∈ (+0.03551852, +0.03554981), |δp|=3e-05, [converged], δ = ( 2, 0), step = 76, eigenelements in eig[ 77], ind_ev = 6 +- # 5, endpoint at λ ≈ +0.02500000, step = 83

      You should see the following result:

      title!("")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We note several simple bifurcation points for which the dimension of the kernel of the jacobian is one dimensional. In the above box, δ = ( 1, 0) gives the change in the stability. In this case, there is one vector in the kernel which is real. The bifurcation point 2 has a 2d kernel and is thus not amenable to automatic branch switching.

      Automatic branch switching at simple branch points

      We can compute the branch off the third bifurcation point:

      br1 = continuation(br, 3, setproperties(opts_br;ds = 0.001, max_steps = 40); kwargsC...)
       title!("")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      You can also plot the two branches together plot(br, br1, plotfold=false) and get

      scene = plot(br,br1,plotfold=false)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We continue our journey and compute the branch bifurcating of the first bifurcation point from the last branch we computed:

      br2 = continuation(br1, 1, setproperties(opts_br;ds = 0.001, max_steps = 40); kwargsC...)
       scene = plot(br,br1,br2)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Automatic branch switching at the 2d-branch points

      We now show how to perform automatic branch switching at the nonsimple branch points. However, we think it is important that the user is able to use the previous tools in case automatic branch switching fails. This is explained in the next sections.

      The call for automatic branch switching is the same as in the case of simple branch points (see above) except that many branches are returned.

      branches = continuation(br, 2,
       	setproperties(opts_br; detect_bifurcation = 3, ds = 0.001, p_min = 0.01, max_steps = 32 ) ;
         alg = PALC(tangent = Bordered()),
      @@ -1292,530 +1294,530 @@ 

      bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 -- # 3, endpoint at λ ≈ +0.05858415, step = 33 +- # 1, bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 +- # 3, endpoint at λ ≈ +0.05858415, step = 33 ┌─ Curve type: EquilibriumCont from NonSimpleBranchPoint bifurcation point. ├─ Number of points: 33 ├─ Type of vectors: Vector{Float64} - ├─ Parameter λ starts at 0.2725547358342202, ends at 0.06561509102988644 + ├─ Parameter λ starts at 0.2725547358342202, ends at 0.06561509103333556 ├─ 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, bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 -- # 3, endpoint at λ ≈ +0.05858415, step = 33 +- # 1, bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 +- # 3, endpoint at λ ≈ +0.05858415, step = 33 ┌─ Curve type: EquilibriumCont from NonSimpleBranchPoint bifurcation point. ├─ Number of points: 33 ├─ Type of vectors: Vector{Float64} - ├─ Parameter λ starts at 0.2725547358342202, ends at 0.065615091034702 + ├─ Parameter λ starts at 0.2725547358342202, ends at 0.06561509103413903 ├─ 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, bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 -- # 3, endpoint at λ ≈ +0.05858415, step = 33 +- # 1, bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 +- # 3, endpoint at λ ≈ +0.05858415, step = 33 ┌─ Curve type: EquilibriumCont from NonSimpleBranchPoint bifurcation point. ├─ Number of points: 33 ├─ Type of vectors: Vector{Float64} - ├─ Parameter λ starts at 0.2725547358342202, ends at 0.06561509101868651 + ├─ Parameter λ starts at 0.2725547358342202, ends at 0.06561509103148445 ├─ 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, bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 -- # 3, endpoint at λ ≈ +0.05858415, step = 33 +- # 1, bp at λ ≈ +0.27255723 ∈ (+0.27255723, +0.27255723), |δp|=7e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.14417711 ∈ (+0.14417711, +0.14422343), |δp|=5e-05, [converged], δ = ( 1, 0), step = 24, eigenelements in eig[ 25], ind_ev = 3 +- # 3, endpoint at λ ≈ +0.05858415, step = 33 ┌─ Curve type: EquilibriumCont from NonSimpleBranchPoint bifurcation point. ├─ Number of points: 33 ├─ Type of vectors: Vector{Float64} - ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792373005376713 + ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792373019703421 ├─ 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, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 -- # 3, endpoint at λ ≈ +0.07731989, step = 33 +- # 1, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 +- # 3, endpoint at λ ≈ +0.07731989, step = 33 ┌─ Curve type: EquilibriumCont from NonSimpleBranchPoint bifurcation point. ├─ Number of points: 33 ├─ Type of vectors: Vector{Float64} - ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792372993533058 + ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792373018849287 ├─ 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, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 -- # 3, endpoint at λ ≈ +0.07731989, step = 33 +- # 1, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 +- # 3, endpoint at λ ≈ +0.07731989, step = 33 ┌─ Curve type: EquilibriumCont from NonSimpleBranchPoint bifurcation point. ├─ Number of points: 33 ├─ Type of vectors: Vector{Float64} - ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792373018132525 + ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792373020341703 ├─ 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, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 -- # 3, endpoint at λ ≈ +0.07731989, step = 33 +- # 1, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 +- # 3, endpoint at λ ≈ +0.07731989, step = 33 ┌─ Curve type: EquilibriumCont from NonSimpleBranchPoint bifurcation point. ├─ Number of points: 33 ├─ Type of vectors: Vector{Float64} - ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792373017908335 + ├─ Parameter λ starts at 0.2725547358342202, ends at 0.09792373003113512 ├─ 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, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 -- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 -- # 3, endpoint at λ ≈ +0.07731989, step = 33 +- # 1, bp at λ ≈ +0.27255724 ∈ (+0.27255724, +0.27255724), |δp|=9e-10, [converged], δ = ( 1, 0), step = 1, eigenelements in eig[ 2], ind_ev = 2 +- # 2, bp at λ ≈ +0.27868664 ∈ (+0.27868664, +0.27868709), |δp|=4e-07, [converged], δ = (-1, 0), step = 15, eigenelements in eig[ 16], ind_ev = 2 +- # 3, endpoint at λ ≈ +0.07731989, step = 33

      You can plot the branches using

      scene = plot(br, branches...)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Analysis at the 2d-branch points (manual)

      The second bifurcation point on the branch br of homogeneous solutions has a 2d kernel. we provide two methods to deal with such case

      • automatic local bifurcation diagram (see below)
      • branch switching with deflation (see next section)

      We provide a generic way to study branch points of arbitrary dimensions by computing a reduced equation. The general method is based on a Lyapunov-Schmidt reduction. We can compute the information about the branch point using the generic function (valid for simple branch points, Hopf bifurcation points,...)

      bp2d = get_normal_form(br, 2;  verbose=true, nev = 50)
      Non simple bifurcation point at λ ≈ 0.2725547358342202. 
       Kernel dimension = 2
       Normal form:
      - + -73.8978 * x1 ⋅ p + -0.0128 ⋅ x1³ + 0.0063 ⋅ x1² ⋅ x2 + 0.0327 ⋅ x1 ⋅ x2² + -0.002 ⋅ x2³
      - + -73.8978 * x2 ⋅ p + 0.0022 ⋅ x1³ + 0.0327 ⋅ x1² ⋅ x2 + -0.0066 ⋅ x1 ⋅ x2² + -0.0128 ⋅ x2³
      + + -73.8978 * x1 ⋅ p + -0.0103 ⋅ x1³ + 0.0288 ⋅ x1² ⋅ x2 + 0.0141 ⋅ x1 ⋅ x2² + -0.0114 ⋅ x2³
      + + -73.8978 * x2 ⋅ p + 0.0058 ⋅ x1³ + 0.0252 ⋅ x1² ⋅ x2 + -0.0276 ⋅ x1 ⋅ x2² + -0.0066 ⋅ x2³
       
       

      Note that this is a multivariate polynomials. For more information, see Non-simple branch point.

      You can evaluate this polynomial as follows bp2d(Val(:reducedForm),[0.1,0.2], 0.01) which returns a 2d vector or bp2d([0.1,0.2], 0.01). This last expression actually returns a vector corresponding to the PDE problem.

      You need to solve these equations to compute the bifurcation diagram in the neighborhood of the bifurcation point. In the present case, we do it using brute force. We suggest to use IntervalConstraintProgramming.jl for a more precise way.

      using ProgressMeter
       Nd = 200; L = 0.9
      @@ -1871,4 +1873,4 @@ 

      + kwargsC...)

      thereby providing the following bifurcation diagram with plot(br,br1,br2,brdef1, brdef2,plotfold=false, putbifptlegend = false)

      diff --git a/dev/tutorials/mittelmannAuto/index.html b/dev/tutorials/mittelmannAuto/index.html index b29dd775..ebadcf09 100644 --- a/dev/tutorials/mittelmannAuto/index.html +++ b/dev/tutorials/mittelmannAuto/index.html @@ -123,4 +123,4 @@ callback_newton = cb, finalise_solution = finSol, usedeflation = true, - normC = norminf)

      This gives the following diagram. Using this call, you can pinpoint the particular location where to refine the diagram.

      + normC = norminf)

      This gives the following diagram. Using this call, you can pinpoint the particular location where to refine the diagram.

      diff --git a/dev/tutorials/mittelmannGridap/index.html b/dev/tutorials/mittelmannGridap/index.html index de981cf3..863eaec0 100644 --- a/dev/tutorials/mittelmannGridap/index.html +++ b/dev/tutorials/mittelmannGridap/index.html @@ -90,4 +90,4 @@ callback_newton = BifurcationKit.cbMaxNorm(100), ) -plot(br, br1, br2, br3...)

      +plot(br, br1, br2, br3...)

      diff --git a/dev/tutorials/ode/Colpitts/index.html b/dev/tutorials/ode/Colpitts/index.html index 898edfe9..2c784b91 100644 --- a/dev/tutorials/ode/Colpitts/index.html +++ b/dev/tutorials/ode/Colpitts/index.html @@ -68,72 +68,72 @@ scene = plot(br, vars = (:param, :x1)) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Periodic orbits with Multiple Standard Shooting

      We use shooting to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl.

      Thanks to [Lamour], we can just compute the Floquet coefficients to get the nonlinear stability of the periodic orbit. Two period doubling bifurcations are detected.

      Note that we use Automatic Branch Switching from a Hopf bifurcation despite the fact the normal form implemented in BifurcationKit.jl is not valid for DAE. For example, it predicts a subciritical Hopf point whereas we see below that it is supercritical. Nevertheless, it provides a

      using DifferentialEquations
       
       # this is the ODEProblem used with `DiffEqBase.solve`
      @@ -176,16 +176,16 @@ 

      ┌─ Curve type: PeriodicOrbitCont from Hopf bifurcation point. ├─ Number of points: 38 ├─ Type of vectors: Vector{Float64} - ├─ Parameter μ starts at 0.7642229295455085, ends at 0.6352549726060122 + ├─ Parameter μ starts at 0.7642229295455085, ends at 0.6352549726298775 ├─ 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, pd at μ ≈ +0.73116245 ∈ (+0.73116245, +0.73152250), |δp|=4e-04, [converged], δ = ( 1, 1), step = 17, eigenelements in eig[ 18], ind_ev = 1 -- # 2, pd at μ ≈ +0.67272920 ∈ (+0.67272920, +0.67310008), |δp|=4e-04, [converged], δ = (-1, -1), step = 27, eigenelements in eig[ 28], ind_ev = 1 -- # 3, endpoint at μ ≈ +0.63525497, step = 37 +- # 1, pd at μ ≈ +0.73116245 ∈ (+0.73116245, +0.73152250), |δp|=4e-04, [converged], δ = ( 1, 1), step = 17, eigenelements in eig[ 18], ind_ev = 1 +- # 2, pd at μ ≈ +0.67272920 ∈ (+0.67272920, +0.67310008), |δp|=4e-04, [converged], δ = (-1, -1), step = 27, eigenelements in eig[ 28], ind_ev = 1 +- # 3, endpoint at μ ≈ +0.63525497, step = 37

      with detailed information

       ┌─ Curve type: PeriodicOrbitCont from Hopf bifurcation point.
        ├─ Number of points: 38
        ├─ Type of vectors: Vector{Float64}
      @@ -205,55 +205,49 @@ 

      - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +

      and after the bifurcation

      probFreez_ode = ODEProblem(prob_dae, br.specialpoint[1].x .+ 0.01rand(4), (0., 200.), @set par_Colpitts.μ = 0.72)
       
       solFreez = @time solve(probFreez_ode, Rodas4(), progress = true;reltol = 1e-10, abstol = 1e-13)
      @@ -261,53 +255,49 @@ 

      - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      References

      • Rabier

        Rabier, Patrick J. “The Hopf Bifurcation Theorem for Quasilinear Differential-Algebraic Equations.” Computer Methods in Applied Mechanics and Engineering 170, no. 3–4 (March 1999): 355–71. https://doi.org/10.1016/S0045-7825(98)00203-5.

      • Lamour

        Lamour, René, Roswitha März, and Renate Winkler. “How Floquet Theory Applies to Index 1 Differential Algebraic Equations.” Journal of Mathematical Analysis and Applications 217, no. 2 (January 1998): 372–94. https://doi.org/10.1006/jmaa.1997.5714.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      References

      • Rabier

        Rabier, Patrick J. “The Hopf Bifurcation Theorem for Quasilinear Differential-Algebraic Equations.” Computer Methods in Applied Mechanics and Engineering 170, no. 3–4 (March 1999): 355–71. https://doi.org/10.1016/S0045-7825(98)00203-5.

      • Lamour

        Lamour, René, Roswitha März, and Renate Winkler. “How Floquet Theory Applies to Index 1 Differential Algebraic Equations.” Journal of Mathematical Analysis and Applications 217, no. 2 (January 1998): 372–94. https://doi.org/10.1006/jmaa.1997.5714.

      diff --git a/dev/tutorials/ode/NME-MTK/index.html b/dev/tutorials/ode/NME-MTK/index.html index 49fa37b8..55eee203 100644 --- a/dev/tutorials/ode/NME-MTK/index.html +++ b/dev/tutorials/ode/NME-MTK/index.html @@ -34,7 +34,12 @@ # we collect the differentials together in a problem prob = BifurcationProblem(F, odeprob.u0, par_tm, (@lens _[id_E0]); J = J, - record_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]))

      We first compute the branch of equilibria

      # continuation options
      +    record_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]))
      WARNING: Method definition isapprox(IntervalSets.AbstractInterval{T} where T, IntervalSets.AbstractInterval{T} where T) in module IntervalSets at /home/runner/.julia/packages/IntervalSets/viB6k/src/IntervalSets.jl:144 overwritten in module DomainSets at /home/runner/.julia/packages/DomainSets/aafhp/src/domains/interval.jl:52.
      +ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.
      +WARNING: Method definition isapprox(IntervalSets.AbstractInterval{T} where T, IntervalSets.AbstractInterval{T} where T) in module IntervalSets at /home/runner/.julia/packages/IntervalSets/viB6k/src/IntervalSets.jl:144 overwritten in module DomainSets at /home/runner/.julia/packages/DomainSets/aafhp/src/domains/interval.jl:52.
      +ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.
      +WARNING: Method definition isapprox(IntervalSets.AbstractInterval{T} where T, IntervalSets.AbstractInterval{T} where T) in module IntervalSets at /home/runner/.julia/packages/IntervalSets/viB6k/src/IntervalSets.jl:144 overwritten in module DomainSets at /home/runner/.julia/packages/DomainSets/aafhp/src/domains/interval.jl:52.
      +ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.

      We first compute the branch of equilibria

      # continuation options
       opts_br = ContinuationPar(p_min = -10.0, p_max = -0.9,
       	# parameters to have a smooth result
       	ds = 0.04, dsmax = 0.05,
      @@ -49,124 +54,124 @@
       scene = plot(br, plotfold=false, markersize=3, legend=:topleft)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      With detailed information:

      br
       ┌─ Curve type: EquilibriumCont
        ├─ Number of points: 72
        ├─ Type of vectors: Vector{Float64}
      @@ -177,11 +182,11 @@
       If `br` is the name of the branch,
       ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
       
      -- #  1,       bp at p ≈ -1.46302733 ∈ (-1.46302733, -1.46302733), |δp|=4e-12, [converged], δ = ( 1,  0), step =  12, eigenelements in eig[ 13], ind_ev =   1
      -- #  2,     hopf at p ≈ -1.85012462 ∈ (-1.85012462, -1.85012459), |δp|=3e-08, [converged], δ = ( 2,  2), step =  32, eigenelements in eig[ 33], ind_ev =   3
      -- #  3,       bp at p ≈ -1.86522391 ∈ (-1.86522391, -1.86522391), |δp|=2e-14, [converged], δ = (-1,  0), step =  36, eigenelements in eig[ 37], ind_ev =   3
      -- #  4,     hopf at p ≈ -1.15105821 ∈ (-1.15106071, -1.15105821), |δp|=2e-06, [converged], δ = (-2, -2), step =  65, eigenelements in eig[ 66], ind_ev =   2
      -- #  5, endpoint at p ≈ -0.90000000,                                                                     step =  71
      +- #  1,       bp at p ≈ -1.46302733 ∈ (-1.46302733, -1.46302733), |δp|=4e-12, [converged], δ = ( 1,  0), step =  12, eigenelements in eig[ 13], ind_ev =   1
      +- #  2,     hopf at p ≈ -1.85012462 ∈ (-1.85012462, -1.85012459), |δp|=3e-08, [converged], δ = ( 2,  2), step =  32, eigenelements in eig[ 33], ind_ev =   3
      +- #  3,       bp at p ≈ -1.86522391 ∈ (-1.86522391, -1.86522391), |δp|=2e-14, [converged], δ = (-1,  0), step =  36, eigenelements in eig[ 37], ind_ev =   3
      +- #  4,     hopf at p ≈ -1.15105821 ∈ (-1.15106071, -1.15105821), |δp|=2e-06, [converged], δ = (-2, -2), step =  65, eigenelements in eig[ 66], ind_ev =   2
      +- #  5, endpoint at p ≈ -0.90000000,                                                                     step =  71
       

      Branch of periodic orbits with Collocation method

      We then compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use finite differences to discretize the problem of finding periodic orbits. Obviously, this will be problematic when the period of the limit cycle grows unbounded close to the homoclinic orbit.

      # newton parameters
       optn_po = NewtonPar(tol = 1e-8,  max_iterations = 10)
       
      @@ -221,130 +226,130 @@
       plot!(scene, br_pocoll.param, br_pocoll.min, label = "")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We plot the maximum (resp. minimum) of the limit cycle. We can see that the min converges to the smallest equilibrium indicating a homoclinic orbit.

      Plot of some of the periodic orbits as function of $E_0$

      We can plot some of the previously computed periodic orbits in the plane $(E,x)$ as function of $E_0$:

      plot()
       # fetch the saved solutions
       for sol in br_pocoll.sol[1:2:40]
      @@ -357,65 +362,65 @@
       title!("")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -

      References

      • Cortes

        Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.

      +

      References

      • Cortes

        Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.

      diff --git a/dev/tutorials/ode/lorenz84-PO/index.html b/dev/tutorials/ode/lorenz84-PO/index.html index 5e434dc6..80175c59 100644 --- a/dev/tutorials/ode/lorenz84-PO/index.html +++ b/dev/tutorials/ode/lorenz84-PO/index.html @@ -38,113 +38,112 @@ scene = plot(br, plotfold=false, markersize=4, legend=:topleft)

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Two parameters curves of Fold / Hopf bifurcation

      We follow the Fold points in the parameter plane $(T,F)$. We tell the solver to consider br.specialpoint[5] and continue it.

      sn_codim2 = continuation(br, 5, (@lens _.T), ContinuationPar(opts_br, p_max = 3.2, p_min = -0.1, detect_bifurcation = 1, dsmin=1e-5, ds = -0.001, dsmax = 0.005, n_inversion = 10, save_sol_every_step = 1, max_steps = 130, max_bisection_steps = 55) ; plot = true,
      -	verbosity = 0,
       	normC = norminf,
       	detect_codim2_bifurcation = 2,
       	update_minaug_every_step = 1,
      @@ -165,66 +164,66 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Fold bifurcations of periodic orbits from Bautin bifurcation

      We compute the branch of Fold of periodic orbits from the Bautin bifurcation (labelled :gh) in the previous figure. In this tutorial, we focus on orthogonal collocation but standard shooting would do too.

      opts_fold_po = ContinuationPar(hp_codim2_1.contparams, dsmax = 0.01, detect_bifurcation = 0, max_steps = 30, detect_event = 0, ds = 0.001, plot_every_step = 10, a = 0.8)
       @set! opts_fold_po.newton_options.verbose = false
       @set! opts_fold_po.newton_options.tol = 1e-8
      @@ -239,68 +238,68 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      NS bifurcations of periodic orbits from Hopf-Hopf bifurcation

      When we computed the curve of Hopf points, we detected a Hopf-Hopf bifurcation. We can branch from it to get the curve of NS points. This is done as follows:

      opts_ns_po = ContinuationPar(hp_codim2_1.contparams, dsmax = 0.02, detect_bifurcation = 1, max_steps = 20, ds = -0.001, detect_event = 0)
       @set! opts_ns_po.newton_options.verbose = false
       @set! opts_ns_po.newton_options.tol = 1e-9
      @@ -319,70 +318,70 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      ns_po2 = continuation(hp_codim2_1, 4, opts_ns_po,
       		PeriodicOrbitOCollProblem(30, 3, update_section_every_step = 1);
       		detect_codim2_bifurcation = 0,
      @@ -396,70 +395,70 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      References

      • Kuznetsov

        Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      References

      • Kuznetsov

        Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.

      diff --git a/dev/tutorials/ode/lorenz84/index.html b/dev/tutorials/ode/lorenz84/index.html index 2009956a..5100a274 100644 --- a/dev/tutorials/ode/lorenz84/index.html +++ b/dev/tutorials/ode/lorenz84/index.html @@ -42,85 +42,85 @@ scene = plot(br, plotfold=false, markersize=4, legend=:topleft)

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      With detailed information:

      br
       ┌─ Curve type: EquilibriumCont
        ├─ Number of points: 33
        ├─ Type of vectors: Vector{Float64}
      @@ -131,12 +131,12 @@
       If `br` is the name of the branch,
       ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
       
      -- #  1, endpoint at F ≈ +3.00000000,                                                                     step =   0
      -- #  2,     hopf at F ≈ +2.85996783 ∈ (+2.85986480, +2.85996783), |δp|=1e-04, [converged], δ = ( 2,  2), step =   1, eigenelements in eig[  2], ind_ev =   4
      -- #  3,     hopf at F ≈ +2.46723305 ∈ (+2.46720734, +2.46723305), |δp|=3e-05, [converged], δ = (-2, -2), step =   3, eigenelements in eig[  4], ind_ev =   4
      -- #  4,     hopf at F ≈ +1.61975642 ∈ (+1.61959602, +1.61975642), |δp|=2e-04, [converged], δ = ( 2,  2), step =   9, eigenelements in eig[ 10], ind_ev =   4
      -- #  5,       bp at F ≈ +1.54664839 ∈ (+1.54664837, +1.54664839), |δp|=1e-08, [converged], δ = (-1,  0), step =  11, eigenelements in eig[ 12], ind_ev =   4
      -- #  6, endpoint at F ≈ +3.00000000,                                                                     step =  32
      +- #  1, endpoint at F ≈ +3.00000000,                                                                     step =   0
      +- #  2,     hopf at F ≈ +2.85996783 ∈ (+2.85986480, +2.85996783), |δp|=1e-04, [converged], δ = ( 2,  2), step =   1, eigenelements in eig[  2], ind_ev =   4
      +- #  3,     hopf at F ≈ +2.46723305 ∈ (+2.46720734, +2.46723305), |δp|=3e-05, [converged], δ = (-2, -2), step =   3, eigenelements in eig[  4], ind_ev =   4
      +- #  4,     hopf at F ≈ +1.61975642 ∈ (+1.61959602, +1.61975642), |δp|=2e-04, [converged], δ = ( 2,  2), step =   9, eigenelements in eig[ 10], ind_ev =   4
      +- #  5,       bp at F ≈ +1.54664839 ∈ (+1.54664837, +1.54664839), |δp|=1e-08, [converged], δ = (-1,  0), step =  11, eigenelements in eig[ 12], ind_ev =   4
      +- #  6, endpoint at F ≈ +3.00000000,                                                                     step =  32
       

      Continuation of Fold points

      We follow the Fold points in the parameter plane $(T,F)$. We tell the solver to consider br.specialpoint[5] and continue it.

      # function to record the current state
       sn_codim2 = continuation(br, 5, (@lens _.T), ContinuationPar(opts_br, p_max = 3.2, p_min = -0.1, detect_bifurcation = 1, dsmin=1e-5, ds = -0.001, dsmax = 0.005, n_inversion = 10, max_steps = 130, max_bisection_steps = 55) ; normC = norminf,
       	# detection of codim 2 bifurcations with bisection
      @@ -151,57 +151,57 @@
       scene = plot(sn_codim2, vars=(:X, :U), branchlabel = "Folds", ylims=(-0.5, 0.5))
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      with detailed information

      sn_codim2
       ┌─ Curve type: FoldCont
        ├─ Number of points: 82
        ├─ Type of vectors: Vector{Float64}
      @@ -212,11 +212,11 @@
       If `br` is the name of the branch,
       ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
       
      -- #  1,       bt at T ≈ +0.02094017 ∈ (+0.02094017, +0.02094017), |δp|=3e-11, [converged], δ = ( 0,  0), step =  12, eigenelements in eig[ 13], ind_ev =   0
      -- #  2,       zh at T ≈ +0.00012654 ∈ (+0.00012654, +0.00012654), |δp|=9e-10, [converged], δ = ( 0,  0), step =  29, eigenelements in eig[ 30], ind_ev =   0
      -- #  3,       zh at T ≈ -0.00012654 ∈ (-0.00012654, -0.00012654), |δp|=1e-11, [converged], δ = ( 0,  0), step =  32, eigenelements in eig[ 33], ind_ev =   0
      -- #  4,       bt at T ≈ -0.02094018 ∈ (-0.02094018, -0.02094017), |δp|=7e-09, [converged], δ = ( 0,  0), step =  49, eigenelements in eig[ 50], ind_ev =   0
      -- #  5, endpoint at T ≈ -0.10000000,                                                                     step =  81
      +- #  1,       bt at T ≈ +0.02094017 ∈ (+0.02094017, +0.02094017), |δp|=3e-11, [converged], δ = ( 0,  0), step =  12, eigenelements in eig[ 13], ind_ev =   0
      +- #  2,       zh at T ≈ +0.00012654 ∈ (+0.00012654, +0.00012654), |δp|=9e-10, [converged], δ = ( 0,  0), step =  29, eigenelements in eig[ 30], ind_ev =   0
      +- #  3,       zh at T ≈ -0.00012654 ∈ (-0.00012654, -0.00012654), |δp|=1e-11, [converged], δ = ( 0,  0), step =  32, eigenelements in eig[ 33], ind_ev =   0
      +- #  4,       bt at T ≈ -0.02094018 ∈ (-0.02094018, -0.02094017), |δp|=7e-09, [converged], δ = ( 0,  0), step =  49, eigenelements in eig[ 50], ind_ev =   0
      +- #  5, endpoint at T ≈ -0.10000000,                                                                     step =  81
       

      For example, we can compute the following normal form

      get_normal_form(sn_codim2, 1; nev = 4)
      Bogdanov-Takens bifurcation point at (:F, :T) ≈ (1.4467167009620112, 0.020940169656439418).
       Normal form (B, β1 + β2⋅B + b⋅A⋅B + a⋅A²)
       Normal form coefficients:
      @@ -243,84 +243,84 @@
       	ylims!(-0.7,0.7);xlims!(1,1.3)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      hp_codim2_1
       ┌─ Curve type: HopfCont
        ├─ Number of points: 229
        ├─ Type of vectors: Vector{Float64}
      - ├─ Parameter T starts at 0.02094016977820847, ends at -0.11830225185207591
      + ├─ Parameter T starts at 0.02094016977821997, ends at -0.11830225185207596
        ├─ 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, endpoint at T ≈ +0.02094017,                                                                     step =   0
      -- #  2,       bt at T ≈ +0.02094017 ∈ (+0.02094017, +0.02094017), |δp|=1e-10, [converged], δ = ( 0,  0), step =   0, eigenelements in eig[  1], ind_ev =   0
      -- #  3,       gh at T ≈ +0.05019747 ∈ (+0.05019363, +0.05019747), |δp|=4e-06, [converged], δ = ( 0,  0), step =  19, eigenelements in eig[ 20], ind_ev =   0
      -- #  4,       hh at T ≈ +0.02627369 ∈ (+0.02627369, +0.02627462), |δp|=9e-07, [converged], δ = (-2, -2), step =  35, eigenelements in eig[ 36], ind_ev =   2
      -- #  5, endpoint at T ≈ -0.11849955,                                                                     step = 229
      -

      For example, we can compute the following normal form

      get_normal_form(hp_codim2_1, 3; nev = 4)
      Bautin bifurcation point at (:F, :T) ≈ (2.376359555697585, 0.05019747303611745).
      -ω = 0.69036727287789
      -Second lyapunov coefficient l₂ = 0.15578807525671282
      +- #  1, endpoint at T ≈ +0.02094017,                                                                     step =   0
      +- #  2,       bt at T ≈ +0.02094017 ∈ (+0.02094017, +0.02094017), |δp|=9e-11, [converged], δ = ( 0,  0), step =   0, eigenelements in eig[  1], ind_ev =   0
      +- #  3,       gh at T ≈ +0.05019747 ∈ (+0.05019363, +0.05019747), |δp|=4e-06, [converged], δ = ( 0,  0), step =  19, eigenelements in eig[ 20], ind_ev =   0
      +- #  4,       hh at T ≈ +0.02627369 ∈ (+0.02627369, +0.02627462), |δp|=9e-07, [converged], δ = (-2, -2), step =  35, eigenelements in eig[ 36], ind_ev =   2
      +- #  5, endpoint at T ≈ -0.11849955,                                                                     step = 229
      +

      For example, we can compute the following normal form

      get_normal_form(hp_codim2_1, 3; nev = 4)
      Bautin bifurcation point at (:F, :T) ≈ (2.3763595556975923, 0.05019747303611703).
      +ω = 0.6903672728778927
      +Second lyapunov coefficient l₂ = 0.15578807525689253
       Normal form: i⋅ω⋅u + l₂⋅u⋅|u|⁴
       

      Continuation of Hopf points from the Bogdanov-Takens point

      When we computed the curve of Fold points, we detected a Bogdanov-Takens bifurcation. We can branch from it to get the curve of Hopf points. This is done as follows:

      hp_from_bt = continuation((@set sn_codim2.alg.tangent = Bordered()), 4, ContinuationPar(opts_br, ds = -0.001, dsmax = 0.02, dsmin = 1e-4,
       	n_inversion = 6, detect_bifurcation = 1) ; normC = norminf,
      @@ -338,78 +338,78 @@
       	ylims!(-0.7,0.75);xlims!(0.95,1.3)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      with detailed information

      hp_from_bt
       ┌─ Curve type: HopfCont from BogdanovTakens bifurcation point.
        ├─ Number of points: 201
        ├─ Type of vectors: Vector{Float64}
      @@ -420,9 +420,9 @@
       If `br` is the name of the branch,
       ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
       
      -- #  1,       gh at T ≈ -0.05019669 ∈ (-0.05020126, -0.05019669), |δp|=5e-06, [converged], δ = ( 0,  0), step =  23, eigenelements in eig[ 24], ind_ev =   0
      -- #  2,       hh at T ≈ -0.02627323 ∈ (-0.02627485, -0.02627323), |δp|=2e-06, [converged], δ = (-2, -2), step =  26, eigenelements in eig[ 27], ind_ev =   2
      -- #  3, endpoint at T ≈ +0.11483750,                                                                     step = 201
      +- #  1,       gh at T ≈ -0.05019669 ∈ (-0.05020126, -0.05019669), |δp|=5e-06, [converged], δ = ( 0,  0), step =  23, eigenelements in eig[ 24], ind_ev =   0
      +- #  2,       hh at T ≈ -0.02627323 ∈ (-0.02627485, -0.02627323), |δp|=2e-06, [converged], δ = (-2, -2), step =  26, eigenelements in eig[ 27], ind_ev =   2
      +- #  3, endpoint at T ≈ +0.11483750,                                                                     step = 201
       

      Continuation of Hopf points from the Zero-Hopf point

      When we computed the curve of Fold points, we detected a Zero-Hopf bifurcation. We can branch from it to get the curve of Hopf points. This is done as follows:

      hp_from_zh = continuation((@set sn_codim2.alg.tangent = Bordered()), 2, ContinuationPar(opts_br, ds = 0.001, dsmax = 0.02, dsmin = 1e-4, n_inversion = 6, detect_bifurcation = 1, max_steps = 150) ;
       	normC = norminf,
       	detect_codim2_bifurcation = 2,
      @@ -440,79 +440,79 @@
       	ylims!(-0.7,0.75);xlims!(0.95,1.3)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      with detailed information

      hp_from_zh
       ┌─ Curve type: HopfCont from BifurcationKit.ZeroHopf bifurcation point.
        ├─ Number of points: 151
        ├─ Type of vectors: Vector{Float64}
      @@ -523,8 +523,8 @@
       If `br` is the name of the branch,
       ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
       
      -- #  1,       gh at T ≈ +0.00012653 ∈ (+0.00012653, +0.00012653), |δp|=9e-13, [   guessL], δ = ( 0,  0), step =   1, eigenelements in eig[  2], ind_ev =   0
      -- #  2,       zh at T ≈ +0.00012654 ∈ (+0.00012653, +0.00012654), |δp|=1e-08, [converged], δ = (-1,  0), step =   2, eigenelements in eig[  3], ind_ev =   1
      -- #  3,       hh at T ≈ +0.02627399 ∈ (+0.02627369, +0.02627399), |δp|=3e-07, [converged], δ = ( 2,  2), step =  27, eigenelements in eig[ 28], ind_ev =   2
      -- #  4, endpoint at T ≈ +0.41476034,                                                                     step = 151
      -

      References

      • Kuznetsov

        Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.

      +- # 1, gh at T ≈ +0.00012653 ∈ (+0.00012653, +0.00012653), |δp|=9e-13, [ guessL], δ = ( 0, 0), step = 1, eigenelements in eig[ 2], ind_ev = 0 +- # 2, zh at T ≈ +0.00012654 ∈ (+0.00012653, +0.00012654), |δp|=1e-08, [converged], δ = (-1, 0), step = 2, eigenelements in eig[ 3], ind_ev = 1 +- # 3, hh at T ≈ +0.02627399 ∈ (+0.02627369, +0.02627399), |δp|=3e-07, [converged], δ = ( 2, 2), step = 27, eigenelements in eig[ 28], ind_ev = 2 +- # 4, endpoint at T ≈ +0.41476034, step = 151 +

      References

      • Kuznetsov

        Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68.

      diff --git a/dev/tutorials/ode/steinmetz/index.html b/dev/tutorials/ode/steinmetz/index.html index d1283c3a..fc07c740 100644 --- a/dev/tutorials/ode/steinmetz/index.html +++ b/dev/tutorials/ode/steinmetz/index.html @@ -49,57 +49,57 @@ plot(sol) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We generate a shooting problem form the computed trajectories and continue the periodic orbits as function of $k_8$

      probsh, cish = generate_ci_problem( ShootingProblem(M=4), prob, prob_de, sol, 16.; reltol = 1e-10, abstol = 1e-12, parallel = true)
       
       opts_po_cont = ContinuationPar(p_min = 0., p_max = 20.0, ds = 0.002, dsmax = 0.05, n_inversion = 8, detect_bifurcation = 3, max_bisection_steps = 25, nev = 4, max_steps = 60, save_eigenvectors = true, tol_stability = 1e-3)
      @@ -111,16 +111,16 @@
       	argspo...)
       ┌─ Curve type: PeriodicOrbitCont
        ├─ Number of points: 61
        ├─ Type of vectors: Vector{Float64}
      - ├─ Parameter k8 starts at 0.75, ends at 0.8227646032724317
      + ├─ Parameter k8 starts at 0.75, ends at 0.819138808928067
        ├─ 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,       ns at k8 ≈ +0.82521359 ∈ (+0.82521140, +0.82521359), |δp|=2e-06, [converged], δ = ( 2,  2), step =  18, eigenelements in eig[ 19], ind_ev =   2
      -- #  2,       bp at k8 ≈ +0.84391360 ∈ (+0.84391360, +0.84391360), |δp|=2e-11, [converged], δ = (-1,  0), step =  28, eigenelements in eig[ 29], ind_ev =   2
      -- #  3, endpoint at k8 ≈ +0.82507279,                                                                     step =  61
      +- #  1,       ns at k8 ≈ +0.82521361 ∈ (+0.82521357, +0.82521361), |δp|=4e-08, [converged], δ = ( 2,  2), step =  21, eigenelements in eig[ 22], ind_ev =   2
      +- #  2,       bp at k8 ≈ +0.84391360 ∈ (+0.84391360, +0.84391360), |δp|=6e-10, [converged], δ = (-1,  0), step =  32, eigenelements in eig[ 33], ind_ev =   2
      +- #  3, endpoint at k8 ≈ +0.81637318,                                                                     step =  61
       

      Curve of Fold points of periodic orbits

      opts_posh_fold = ContinuationPar(br_sh.contparams, detect_bifurcation = 2, max_steps = 35, p_max = 1.9, plot_every_step = 10, dsmax = 4e-2, ds = 1e-2)
       @set! opts_posh_fold.newton_options.tol = 1e-12
       @set! opts_posh_fold.newton_options.verbose = true
      @@ -144,4 +144,4 @@
       		jacobian_ma = :minaug,
       		normC = norminf,
       		callback_newton = BK.cbMaxNorm(1e1),
      -		)
      plot(ns_po_sh, fold_po_sh, branchlabel = ["NS","Fold"])
      + )
      plot(ns_po_sh, fold_po_sh, branchlabel = ["NS","Fold"])
      diff --git a/dev/tutorials/ode/tutorialCO/index.html b/dev/tutorials/ode/tutorialCO/index.html index b87eba82..b83a93c9 100644 --- a/dev/tutorials/ode/tutorialCO/index.html +++ b/dev/tutorials/ode/tutorialCO/index.html @@ -36,166 +36,166 @@ 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 q2 ≈ +1.04106765 ∈ (+1.04084579, +1.04106765), |δp|=2e-04, [converged], δ = ( 2, 2), step = 36, eigenelements in eig[ 37], ind_ev = 2 -- # 2, bp at q2 ≈ +1.05219982 ∈ (+1.05219332, +1.05219982), |δp|=6e-06, [converged], δ = (-1, 0), step = 40, eigenelements in eig[ 41], ind_ev = 2 -- # 3, bp at q2 ≈ +1.04204863 ∈ (+1.04204863, +1.04204865), |δp|=3e-08, [converged], δ = ( 1, 0), step = 48, eigenelements in eig[ 49], ind_ev = 2 -- # 4, hopf at q2 ≈ +1.05223978 ∈ (+1.05085807, +1.05223978), |δp|=1e-03, [converged], δ = (-2, -2), step = 52, eigenelements in eig[ 53], ind_ev = 2 -- # 5, endpoint at q2 ≈ +1.69888900, step = 101 +- # 1, hopf at q2 ≈ +1.04106765 ∈ (+1.04084579, +1.04106765), |δp|=2e-04, [converged], δ = ( 2, 2), step = 36, eigenelements in eig[ 37], ind_ev = 2 +- # 2, bp at q2 ≈ +1.05219982 ∈ (+1.05219332, +1.05219982), |δp|=6e-06, [converged], δ = (-1, 0), step = 40, eigenelements in eig[ 41], ind_ev = 2 +- # 3, bp at q2 ≈ +1.04204863 ∈ (+1.04204863, +1.04204865), |δp|=3e-08, [converged], δ = ( 1, 0), step = 48, eigenelements in eig[ 49], ind_ev = 2 +- # 4, hopf at q2 ≈ +1.05223978 ∈ (+1.05085807, +1.05223978), |δp|=1e-03, [converged], δ = (-2, -2), step = 52, eigenelements in eig[ 53], ind_ev = 2 +- # 5, endpoint at q2 ≈ +1.69888900, step = 101
      # plot the branch
       scene = plot(br, xlims = (0.8,1.8))
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of Fold points

      We follow the Fold points in the parameter plane $(q_2, k)$. We tell the solver to consider br.specialpoint[2] and continue it.

      sn_codim2 = continuation(br, 2, (@lens _.k),
       	ContinuationPar(opts_br, p_max = 2.2, ds = -0.001, dsmax = 0.05);
       	normC = norminf,
      @@ -210,166 +210,166 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of Hopf points

      We tell the solver to consider br.specialpoint[1] and continue it.

      hp_codim2 = continuation(br, 1, (@lens _.k),
       	ContinuationPar(opts_br, p_max = 2.8, ds = -0.001, dsmax = 0.05) ;
       	normC = norminf,
      @@ -389,172 +389,172 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      References

      • Govaerts

        Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      References

      • Govaerts

        Govaerts, Willy J. F. Numerical Methods for Bifurcations of Dynamical Equilibria. Philadelphia, Pa: Society for Industrial and Applied Mathematics, 2000.

      diff --git a/dev/tutorials/ode/tutorialPP2/index.html b/dev/tutorials/ode/tutorialPP2/index.html index 982c4f6e..24d0a82f 100644 --- a/dev/tutorials/ode/tutorialPP2/index.html +++ b/dev/tutorials/ode/tutorialPP2/index.html @@ -44,409 +44,409 @@ scene = plot(diagram; code = (), title="$(size(diagram)) branches", legend = false)

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Branch of periodic orbits with finite differences

      As you can see on the diagram, there is a Hopf bifurcation indicated by a red dot. Let us compute the periodic orbit branching from the Hopf point.

      We first find the branch

      # branch of the diagram with Hopf point
       brH = get_branch(diagram, (2,1)).γ
      @@ -465,10 +465,13 @@ 

      +plot(diagram); plot!(br_po, branchlabel = "Periodic orbits", legend = :bottomright)

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Let us now plot an orbit

      # extract the different components
       orbit = get_periodic_orbit(br_po, 10)
      -plot(orbit.t, orbit.u[1,:]; label = "u1", markersize = 2)
      -plot!(orbit.t, orbit.u[2,:]; label = "u2", xlabel = "time", title = "period = $(orbit.t[end])")
      +plot(orbit.t, orbit[1,:]; label = "u1", markersize = 2) +plot!(orbit.t, orbit[2,:]; label = "u2", xlabel = "time", title = "period = $(orbit.t[end])")
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tutorials/ode/tutorials1/index.html b/dev/tutorials/ode/tutorials1/index.html index 704b0d10..a0bfb840 100644 --- a/dev/tutorials/ode/tutorials1/index.html +++ b/dev/tutorials/ode/tutorials1/index.html @@ -30,575 +30,575 @@ │ 3 │ 2.4336e-06 │ 1 │ │ 4 │ 6.7452e-12 │ 1 │ └─────────────┴──────────────────────┴────────────────┘ - 0.001202 seconds (345 allocations: 1.262 MiB)

      Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.

      We can perform numerical continuation w.r.t. the parameter $\alpha$. This time, we need to provide additional parameters, but now for the continuation method:

      optcont = ContinuationPar(max_steps = 150,
      +  0.000944 seconds (362 allocations: 2.302 MiB)

      Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.

      We can perform numerical continuation w.r.t. the parameter $\alpha$. This time, we need to provide additional parameters, but now for the continuation method:

      optcont = ContinuationPar(max_steps = 150,
       	p_min = 0., p_max = 4.2,
       	newton_options =optnewton)

      Next, we call the continuation routine as follows.

      br = continuation(prob, PALC(), optcont; plot = true)
       nothing #hide

      The parameter axis lens = @lens _.α is used to extract the component of par corresponding to α. Internally, it is used as get(par, lens) which returns 3.3.

      Tip

      We don't need to call newton first in order to use continuation.

      You should see

      scene = title!("") #hide
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -

      The left figure is the norm of the solution as function of the parameter $p=\alpha$, the y-axis can be changed by passing a different recordFromSolution to BifurcationProblem. The top right figure is the value of $\alpha$ as function of the iteration number. The bottom right is the solution for the current value of the parameter. This last plot can be modified by changing the argument plotSolution to BifurcationProblem.

      Bif. point detection

      Two Fold points were detected. This can be seen by looking at br.specialpoint, by the black dots on the continuation plots when doing plot(br, plotfold=true) or by typing br in the REPL. Note that the bifurcation points are located in br.specialpoint.

      What if we want to compute to continue both ways in one call?

      br = continuation(prob, PALC(), optcont; bothside = true)
      +

      The left figure is the norm of the solution as function of the parameter $p=\alpha$, the y-axis can be changed by passing a different record_from_solution to BifurcationProblem. The top right figure is the value of $\alpha$ as function of the iteration number. The bottom right is the solution for the current value of the parameter. This last plot can be modified by changing the argument plot_solution to BifurcationProblem.

      Bif. point detection

      Two Fold points were detected. This can be seen by looking at show(br) or br.specialpoint, by the black dots on the continuation plots when doing plot(br, plotfold=true) or by typing br in the REPL. Note that the bifurcation points are located in br.specialpoint.

      What if we want to compute to continue both ways in one call?

      br = continuation(prob, PALC(), optcont; bothside = true)
       plot(br)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tutorials/ode/tutorialsBasic1/index.html b/dev/tutorials/ode/tutorialsBasic1/index.html index cb461d18..2b055268 100644 --- a/dev/tutorials/ode/tutorialsBasic1/index.html +++ b/dev/tutorials/ode/tutorialsBasic1/index.html @@ -40,113 +40,113 @@ scene = plot(br, legend=:topleft)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      With detailed information:

      br
       ┌─ Curve type: EquilibriumCont
        ├─ Number of points: 61
        ├─ Type of vectors: Vector{Float64}
      @@ -157,12 +157,12 @@
       If `br` is the name of the branch,
       ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
       
      -- #  1, endpoint at E0 ≈ -4.00000000,                                                                     step =   0
      -- #  2,       bp at E0 ≈ -1.46309794 ∈ (-1.46309794, -1.46302753), |δp|=7e-05, [converged], δ = ( 1,  0), step =  30, eigenelements in eig[ 31], ind_ev =   1
      -- #  3,     hopf at E0 ≈ -1.85075293 ∈ (-1.85075293, -1.84970242), |δp|=1e-03, [converged], δ = ( 2,  2), step =  40, eigenelements in eig[ 41], ind_ev =   3
      -- #  4,       bp at E0 ≈ -1.86522340 ∈ (-1.86522340, -1.86494948), |δp|=3e-04, [converged], δ = (-1,  0), step =  42, eigenelements in eig[ 43], ind_ev =   3
      -- #  5,     hopf at E0 ≈ -1.14947379 ∈ (-1.15202958, -1.14947379), |δp|=3e-03, [converged], δ = (-2, -2), step =  57, eigenelements in eig[ 58], ind_ev =   2
      -- #  6, endpoint at E0 ≈ -0.90000000,                                                                     step =  60
      +- #  1, endpoint at E0 ≈ -4.00000000,                                                                     step =   0
      +- #  2,       bp at E0 ≈ -1.46309794 ∈ (-1.46309794, -1.46302753), |δp|=7e-05, [converged], δ = ( 1,  0), step =  30, eigenelements in eig[ 31], ind_ev =   1
      +- #  3,     hopf at E0 ≈ -1.85075293 ∈ (-1.85075293, -1.84970242), |δp|=1e-03, [converged], δ = ( 2,  2), step =  40, eigenelements in eig[ 41], ind_ev =   3
      +- #  4,       bp at E0 ≈ -1.86522340 ∈ (-1.86522340, -1.86494948), |δp|=3e-04, [converged], δ = (-1,  0), step =  42, eigenelements in eig[ 43], ind_ev =   3
      +- #  5,     hopf at E0 ≈ -1.14947379 ∈ (-1.15202958, -1.14947379), |δp|=3e-03, [converged], δ = (-2, -2), step =  57, eigenelements in eig[ 58], ind_ev =   2
      +- #  6, endpoint at E0 ≈ -0.90000000,                                                                     step =  60
       

      If you don't want to compute just the branch without the bifurcations (more information is provided here ), change the continuation options to

      opts_br = ContinuationPar(p_min = -4.0, p_max = -0.9,
       	detect_bifurcation = 0)
       
      @@ -175,48 +175,48 @@
       scene = plot(br, plotfold=true)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      References

      • Cortes

        Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      References

      • Cortes

        Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.

      diff --git a/dev/tutorials/ode/tutorialsCodim2PO/index.html b/dev/tutorials/ode/tutorialsCodim2PO/index.html index 60a42089..d96c7d85 100644 --- a/dev/tutorials/ode/tutorialsCodim2PO/index.html +++ b/dev/tutorials/ode/tutorialsCodim2PO/index.html @@ -35,53 +35,53 @@ plot(sol) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Utility functions

      We start with two helper functions that record and plot the periodic orbits. The following works for shooting, collocation and trapezoid methods for computing periodic orbits.

      argspo = (record_from_solution = (x, p) -> begin
       		xtt = get_periodic_orbit(p.prob, x, p.p)
       		return (max = maximum(xtt[1,:]),
      @@ -106,101 +106,101 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We continue w.r.t. to $\epsilon$ and find a period-doubling bifurcation.

      prob2 = @set probtrap.prob_vf.lens = @lens _.ϵ
       brpo_pd = continuation(prob2, ci, PALC(), opts_po_cont;
       	verbosity = 3, plot = true,
      @@ -209,108 +209,108 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Periodic orbits with parallel standard shooting

      We are now ready to build a periodic orbit problem from a solution sol::ODEProblem.

      probsh, cish = generate_ci_problem( ShootingProblem(M=3),
       	prob, prob_de, sol, 2.; alg = Rodas5())
       
      @@ -323,101 +323,101 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We continue w.r.t. to $\epsilon$ and find a period-doubling bifurcation.

      probsh2 = @set probsh.lens = @lens _.ϵ
       brpo_pd_sh = continuation(probsh2, cish, PALC(), opts_po_cont;
       	verbosity = 3, plot = true,
      @@ -426,108 +426,108 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Periodic orbits with orthogonal collocation

      We do the same as in the previous section but using orthogonal collocation. This is the most reliable and precise method for ODE. When the dimension of the ODE is large, it becomes prohibitive.

      # this is the function which builds probcoll from sol
       probcoll, ci = generate_ci_problem(PeriodicOrbitOCollProblem(26, 3; update_section_every_step = 0),
       	prob, sol, 2.)
      @@ -540,101 +540,101 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We continue w.r.t. to $\epsilon$ and find a period-doubling bifurcation.

      prob2 = @set probcoll.prob_vf.lens = @lens _.ϵ
       brpo_pd = continuation(prob2, ci, PALC(), ContinuationPar(opts_po_cont, dsmax = 5e-3);
       	verbosity = 3, plot = true,
      @@ -644,98 +644,98 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of Fold / PD of periodic orbits with Shooting

      We continue the previously detected fold/period-doubling bifurcations as function of two parameters and detect codim 2 bifurcations. We first start with the computation of the curve of Folds.

      opts_posh_fold = ContinuationPar(br_fold_sh.contparams, detect_bifurcation = 3, max_steps = 100, p_min = 0.01, p_max = 1.2)
       @set! opts_posh_fold.newton_options.tol = 1e-12
       
      @@ -756,19 +756,18 @@ 

      ┌─ Curve type: FoldPeriodicOrbitCont - ├─ Number of points: 117 + ├─ Number of points: 88 ├─ Type of vectors: BorderedArray{Vector{Float64}, Float64} - ├─ Parameter ϵ starts at 0.01, ends at 0.5162494727653699 + ├─ Parameter ϵ starts at 0.01, ends at 1.0920168450454657 ├─ 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, endpoint at ϵ ≈ +0.01000000, step = 0 -- # 2, R1 at ϵ ≈ +0.60338359 ∈ (+0.60336986, +0.60338359), |δp|=1e-05, [converged], δ = ( 1, 0), step = 48, eigenelements in eig[ 49], ind_ev = 1 -- # 3, R1 at ϵ ≈ +0.60337895 ∈ (+0.60337895, +0.60338238), |δp|=3e-06, [converged], δ = (-1, 0), step = 110, eigenelements in eig[111], ind_ev = 1 -- # 4, endpoint at ϵ ≈ +0.50217707, step = 117 +- # 1, endpoint at ϵ ≈ +0.01000000, step = 0 +- # 2, cusp at ϵ ≈ +1.09201685 ∈ (+1.09198532, +1.09201685), |δp|=3e-05, [ guessL], δ = ( 0, 0), step = 87, eigenelements in eig[ 88], ind_ev = 0 +- # 3, endpoint at ϵ ≈ +1.09201685, step = 87

      We turn to the computation of the curve of PD points.

      par_pop2 = @set par_pop.b0 = 0.45
       sol2 = solve(remake(prob_de, p = par_pop2, u0 = [0.1,0.1,1,0], tspan=(0,1000)), Rodas5())
       sol2 = solve(remake(sol2.prob, tspan = (0,10), u0 = sol2[end]), Rodas5())
      @@ -800,62 +799,65 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      References

      • Kuznetsov

        Yu.A. Kuznetsov, S. Muratori, and S. Rinaldi. Bifurcations and chaos in a periodic predator-prey model, Internat. J. Bifur. Chaos Appl. Sci. Engr., 2 (1992), 117-128.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      References

      • Kuznetsov

        Yu.A. Kuznetsov, S. Muratori, and S. Rinaldi. Bifurcations and chaos in a periodic predator-prey model, Internat. J. Bifur. Chaos Appl. Sci. Engr., 2 (1992), 117-128.

      diff --git a/dev/tutorials/ode/tutorialsODE-PD/index.html b/dev/tutorials/ode/tutorialsODE-PD/index.html index 7ed45291..bd6e4cef 100644 --- a/dev/tutorials/ode/tutorialsODE-PD/index.html +++ b/dev/tutorials/ode/tutorialsODE-PD/index.html @@ -27,7 +27,7 @@ # bifurcation problem prob = BifurcationProblem(lur!, z0, par_lur, (@lens _.α); record_from_solution = recordFromSolution)

      We first compute the branch of equilibria

      # continuation options
      -opts_br = ContinuationPar(p_min = -1.4, p_max = 1.8, ds = 0.01, dsmax = 0.01, plot_every_step = 20, max_steps = 1000)
      +opts_br = ContinuationPar(p_min = -1.4, p_max = 1.8, dsmax = 0.01, max_steps = 1000)
       
       # computation of the branch
       br = continuation(prob, PALC(), opts_br)
      @@ -35,251 +35,251 @@
       scene = plot(br)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      With detailed information:

      br
       ┌─ Curve type: EquilibriumCont
        ├─ Number of points: 200
        ├─ Type of vectors: Vector{Float64}
      @@ -290,8 +290,8 @@
       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 α ≈ +1.00022831 ∈ (+0.99934442, +1.00022831), |δp|=9e-04, [converged], δ = (-2, -2), step = 142, eigenelements in eig[143], ind_ev =   2
      -- #  2, endpoint at α ≈ +1.80000000,                                                                     step = 199
      +- #  1,     hopf at α ≈ +1.00022831 ∈ (+0.99934442, +1.00022831), |δp|=9e-04, [converged], δ = (-2, -2), step = 142, eigenelements in eig[143], ind_ev =   2
      +- #  2, endpoint at α ≈ +1.80000000,                                                                     step = 199
       

      We note the Hopf bifurcation point which we shall investigate now.

      Branch of periodic orbits with finite differences

      We compute the branch of periodic orbits from the Hopf bifurcation point. We first define a plotting function and a record function which are used for all cases below:

      # plotting function
       function plotPO(x, p; k...)
       	xtt = get_periodic_orbit(p.prob, x, p.p)
      @@ -305,17 +305,13 @@
       	xtt = get_periodic_orbit(p.prob, x, p.p)
       	period = getperiod(p.prob, x, p.p)
       	return (max = maximum(xtt[1,:]), min = minimum(xtt[1,:]), period = period)
      -end
      recordPO (generic function with 1 method)

      We use finite differences to discretize the problem for finding periodic orbits. We appeal to automatic branch switching as follows

      # newton parameters
      -optn_po = NewtonPar(tol = 1e-8,  max_iterations = 25)
      -
      -# continuation parameters
      -opts_po_cont = ContinuationPar(dsmax = 0.02, ds= 0.01, dsmin = 1e-4, p_max = 1.8, p_min=-1., max_steps = 80, newton_options =  optn_po, tol_stability = 1e-4)
      +end
      recordPO (generic function with 1 method)

      We use finite differences to discretize the problem for finding periodic orbits. We appeal to automatic branch switching as follows

      # continuation parameters
      +opts_po_cont = ContinuationPar(dsmax = 0.02, ds= 0.01, dsmin = 1e-4, p_max = 1.1, max_steps = 80, tol_stability = 1e-4)
       
       Mt = 120 # number of time sections
       br_po = continuation(
       	br, 1, opts_po_cont,
       	PeriodicOrbitTrapProblem(M = Mt);
      -	δp = 0.01,
       	record_from_solution = recordPO,
       	plot_solution = (x, p; k...) -> begin
       		plotPO(x, p; k...)
      @@ -327,340 +323,340 @@
       scene = plot(br, br_po)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Two period doubling bifurcations were detected. We shall now compute the branch of periodic orbits from these PD points. We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.

      # aBS from PD
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +

      Two period doubling bifurcations were detected. We shall now compute the branch of periodic orbits from these PD points. We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.

      # aBS from PD
       br_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40);
      -	verbosity = 3, plot = true,
      +	plot = true,
       	ampfactor = .2, δp = -0.005,
       	usedeflation = true,
       	plot_solution = (x, p; k...) -> begin
      @@ -671,705 +667,19 @@
       	record_from_solution = recordPO,
       	normC = norminf
       	)
      -Scene = title!("")
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      plot(br, br_po, br_po_pd)
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Periodic orbits with Parallel Standard Shooting

      We use a different method to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl. This way of computing periodic orbits should be more precise than the previous one. We use a particular instance called multiple shooting which is computed in parallel. This is an additional advantage compared to the previous method. Finally, please note the close similarity to the code of the previous part. As before, we first rely on Hopf aBS.

      using DifferentialEquations
      +Scene = title!("")
      plot(br, br_po, br_po_pd)

      Periodic orbits with Parallel Standard Shooting

      We use a different method to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl. This way of computing periodic orbits should be more precise than the previous one. We use a particular instance called multiple shooting which is computed in parallel. This is an additional advantage compared to the previous method. Finally, please note the close similarity to the code of the previous part. As before, we first rely on Hopf aBS.

      using DifferentialEquations
       
       # ODE problem for using DifferentialEquations
      -probsh = ODEProblem(lur!, copy(z0), (0., 1000.), par_lur; abstol = 1e-10, reltol = 1e-7)
      -
      -# newton parameters
      -optn_po = NewtonPar(tol = 1e-7, max_iterations = 25)
      +probsh = ODEProblem(lur!, copy(z0), (0., 1000.), par_lur; abstol = 1e-11, reltol = 1e-9)
       
       # continuation parameters
      -opts_po_cont = ContinuationPar(dsmax = 0.02, ds= -0.001, dsmin = 1e-4, max_steps = 130, newton_options = optn_po, tol_stability = 1e-5, detect_bifurcation = 3, plot_every_step = 10, n_inversion = 6, nev = 2)
      +opts_po_cont = ContinuationPar(dsmax = 0.02, ds= -0.001, dsmin = 1e-4, max_steps = 130, tol_stability = 1e-5,plot_every_step = 10)
       
       br_po = continuation(
       	br, 1, opts_po_cont,
       	# parallel shooting functional with 15 sections
       	ShootingProblem(15, probsh, Rodas5(); parallel = true);
      -	# first parameter value on the branch
      -	δp = 0.005,
      -	verbosity = 3, plot = true,
      +	plot = true,
       	record_from_solution = recordPO,
       	plot_solution = plotPO,
       	# limit the residual, useful to help DifferentialEquations
      @@ -1379,346 +689,344 @@ 

      - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -

      We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.

      # aBS from PD
      +

      We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.

      # aBS from PD
       br_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40, dsmax = 0.01, plot_every_step = 10, ds = 0.01);
      -	verbosity = 3, plot = true,
      +	plot = true,
       	ampfactor = .1, δp = -0.005,
       	plot_solution = (x, p; k...) -> begin
       		plotPO(x, p; k...)
      @@ -1730,203 +1038,13 @@ 

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Periodic orbits with orthogonal collocation

      We now rely on a the state of the art method for computing periodic orbits of ODE: orthogonal collocation.

      # newton parameters
      -optn_po = NewtonPar(tol = 1e-10,  max_iterations = 10)
      -
      -# continuation parameters
      -opts_po_cont = ContinuationPar(opts_br, dsmax = 0.03, ds= 0.01, dsmin = 1e-4, max_steps = 80, newton_options = optn_po, tol_stability = 1e-4, plot_every_step = 20, n_inversion = 6)
      +scene = plot(br, br_po, br_po_pd)

      Periodic orbits with orthogonal collocation

      We now rely on a the state of the art method for computing periodic orbits of ODE: orthogonal collocation.

      # continuation parameters
      +opts_po_cont = ContinuationPar(opts_br, dsmax = 0.03, ds = 0.01, dsmin = 1e-4, max_steps = 70, tol_stability = 1e-4, plot_every_step = 20)
       
       br_po = continuation(
       	br, 1, opts_po_cont,
      -	PeriodicOrbitOCollProblem(20, 4);
      -	ampfactor = 1., δp = 0.01,
      -	verbosity = 2,	plot = true,
      +	PeriodicOrbitOCollProblem(40, 4);
      +	plot = true,
       	record_from_solution = recordPO,
       	plot_solution = (x, p; k...) -> begin
       		plotPO(x, p; k...)
      @@ -1938,341 +1056,330 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      We do not provide Automatic Branch Switching as we do not have the PD normal form computed in BifurcationKit. Hence, it takes some trial and error to find the ampfactor of the PD branch.

      # aBS from PD
      -br_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 40, ds = 0.01, dsmax = 0.05, plot_every_step = 10);
      -	verbosity = 3, plot = true,
      +br_po_pd = continuation(br_po, 1, setproperties(br_po.contparams, max_steps = 80, dsmax = 0.02, plot_every_step = 10);
      +	plot = true,
       	ampfactor = .3, δp = -0.005,
       	plot_solution = (x, p; k...) -> begin
       		plotPO(x, p; k...)
      @@ -2287,173 +1394,206 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tutorials/ode/tutorialsODE/index.html b/dev/tutorials/ode/tutorialsODE/index.html index f80899be..bdb78bfd 100644 --- a/dev/tutorials/ode/tutorialsODE/index.html +++ b/dev/tutorials/ode/tutorialsODE/index.html @@ -20,7 +20,7 @@ end # parameter values -par_tm = (α = 1.5, τ = 0.013, J = 3.07, E0 = -2.0, τD = 0.200, U0 = 0.3, τF = 1.5, τS = 0.007) +par_tm = (α = 1.4, τ = 0.013, J = 3.07, E0 = -2.0, τD = 0.20, U0 = 0.3, τF = 1.5) # initial condition z0 = [0.238616, 0.982747, 0.367876] @@ -28,9 +28,7 @@ # Bifurcation Problem prob = BifurcationProblem(TMvf!, z0, par_tm, (@lens _.E0); record_from_solution = (x, p) -> (E = x[1], x = x[2], u = x[3]),)

      We first compute the branch of equilibria

      # continuation options
      -opts_br = ContinuationPar(p_min = -10.0, p_max = -0.9,
      -	# parameters to have a smooth continuation curve
      -	ds = 0.04, dsmax = 0.05,)
      +opts_br = ContinuationPar(p_min = -2.0, p_max = -1.)
       
       # continuation of equilibria
       br = continuation(prob, PALC(tangent=Bordered()), opts_br; normC = norminf)
      @@ -38,145 +36,118 @@
       scene = plot(br, plotfold=false, markersize=3, legend=:topleft)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      With detailed information:

      br
       ┌─ Curve type: EquilibriumCont
      - ├─ Number of points: 72
      + ├─ Number of points: 42
        ├─ Type of vectors: Vector{Float64}
      - ├─ Parameter E0 starts at -2.0, ends at -0.9
      + ├─ Parameter E0 starts at -2.0, ends at -1.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,       bp at E0 ≈ -1.46305839 ∈ (-1.46305839, -1.46303832), |δp|=2e-05, [converged], δ = ( 1,  0), step =  12, eigenelements in eig[ 13], ind_ev =   1
      -- #  2,     hopf at E0 ≈ -1.85048559 ∈ (-1.85048559, -1.84996020), |δp|=5e-04, [converged], δ = ( 2,  2), step =  32, eigenelements in eig[ 33], ind_ev =   3
      -- #  3,       bp at E0 ≈ -1.86515932 ∈ (-1.86522355, -1.86515932), |δp|=6e-05, [converged], δ = (-1,  0), step =  36, eigenelements in eig[ 37], ind_ev =   3
      -- #  4,     hopf at E0 ≈ -1.15095615 ∈ (-1.15223365, -1.15095615), |δp|=1e-03, [converged], δ = (-2, -2), step =  65, eigenelements in eig[ 66], ind_ev =   2
      -- #  5, endpoint at E0 ≈ -0.90000000,                                                                     step =  71
      -

      Branch of periodic orbits with Trapezoid method

      We then compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use finite differences to discretize the problem of finding periodic orbits. Obviously, this will be problematic when the period of the limit cycle grows unbounded close to the homoclinic orbit.

      # newton parameters for the computation of periodic orbits
      -optn_po = NewtonPar(tol = 1e-8,  max_iterations = 12)
      -
      -# continuation parameters
      +- #  1,       bp at E0 ≈ -1.34913909 ∈ (-1.34938031, -1.34913909), |δp|=2e-04, [converged], δ = ( 1,  0), step =  11, eigenelements in eig[ 12], ind_ev =   1
      +- #  2,     hopf at E0 ≈ -1.83157834 ∈ (-1.83157834, -1.83112490), |δp|=5e-04, [converged], δ = ( 2,  2), step =  23, eigenelements in eig[ 24], ind_ev =   3
      +- #  3,       bp at E0 ≈ -1.84196262 ∈ (-1.84196538, -1.84196262), |δp|=3e-06, [converged], δ = (-1,  0), step =  25, eigenelements in eig[ 26], ind_ev =   3
      +- #  4,     hopf at E0 ≈ -1.13421119 ∈ (-1.13429114, -1.13421119), |δp|=8e-05, [converged], δ = (-2, -2), step =  39, eigenelements in eig[ 40], ind_ev =   2
      +- #  5, endpoint at E0 ≈ -1.00000000,                                                                     step =  41
      +

      Branch of periodic orbits with Trapezoid method

      We then compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use finite differences to discretize the problem of finding periodic orbits. Obviously, this will be problematic when the period of the limit cycle grows unbounded close to the homoclinic orbit.

      # continuation parameters
       opts_po_cont = ContinuationPar(opts_br, dsmax = 0.1, ds = -0.001, dsmin = 1e-4,
      -	max_steps = 90, newton_options = optn_po, tol_stability = 1e-8)
      +	max_steps = 80, tol_stability = 1e-8)
       
       # arguments for periodic orbits
       # one function to record information and one
      @@ -208,232 +179,7 @@
       	)
       
       scene = plot(br, br_potrap, markersize = 3)
      -plot!(scene, br_potrap.param, br_potrap.min, label = "")
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      We plot the maximum (resp. minimum) of the limit cycle. We can see that the min converges to the smallest equilibrium indicating a homoclinic orbit.

      Plot of some of the periodic orbits as function of $E_0$

      We can plot some of the previously computed periodic orbits in the plane $(E,x)$ as function of $E_0$:

      plot()
      +plot!(scene, br_potrap.param, br_potrap.min, label = "")

      We plot the maximum (resp. minimum) of the limit cycle. We can see that the min converges to the smallest equilibrium indicating a homoclinic orbit.

      Plot of some of the periodic orbits as function of $E_0$

      We can plot some of the previously computed periodic orbits in the plane $(E,x)$ as function of $E_0$:

      plot()
       # fetch the saved solutions
       for sol in br_potrap.sol[1:2:40]
       	# periodic orbit
      @@ -442,86 +188,18 @@
       	traj = get_periodic_orbit(br_potrap.prob, po, @set par_tm.E0 = sol.p)
       	plot!(traj[1,:], traj[2,:], xlabel = "E", ylabel = "x", label = "")
       end
      -title!("")
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Branch of periodic orbits with Orthogonal Collocation

      We compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use Orthogonal Collocation to discretize the problem of finding periodic orbits. This is vastly more precise than the previous method because we use mesh adaptation.

      # continuation parameters
      -opts_po_cont = ContinuationPar(opts_br, dsmax = 0.15, ds= -0.001, dsmin = 1e-4,
      -	max_steps = 100, newton_options = (@set optn_po.tol = 1e-8),
      +title!("")

      Branch of periodic orbits with Orthogonal Collocation

      We compute the branch of periodic orbits from the last Hopf bifurcation point (on the right). We use Orthogonal Collocation to discretize the problem of finding periodic orbits. This is vastly more precise than the previous method because we use mesh adaptation.

      # continuation parameters
      +opts_po_cont = ContinuationPar(opts_br, ds= 0.001, dsmin = 1e-4, dsmax = 0.1,
      +	max_steps = 150,
       	tol_stability = 1e-5)
       
       br_pocoll = @time continuation(
       	# we want to branch form the 4th bif. point
       	br, 4, opts_po_cont,
       	# we want to use the Collocation method to locate PO, with polynomial degree 4
      -	PeriodicOrbitOCollProblem(30, 4; meshadapt = true);
      +	PeriodicOrbitOCollProblem(40, 4; meshadapt = true);
       	# regular continuation options
      -	verbosity = 2, plot = true,
      +	plot = true,
       	# we reject the newton step if the residual is high
       	callback_newton = BK.cbMaxNorm(100.),
       	args_po...)
      @@ -529,810 +207,1003 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + +

      Periodic orbits with Parallel Standard Shooting

      We use a different method to compute periodic orbits: we rely on a fixed point of the flow. To compute the flow, we use DifferentialEquations.jl. This way of computing periodic orbits should be more precise than the Trapezoid method. We use a particular instance called multiple shooting which is computed in parallel. This is an additional advantage compared to the two previous methods.

      using DifferentialEquations
       
       # this is the ODEProblem used with `DiffEqBase.solve`
       probsh = ODEProblem(TMvf!, copy(z0), (0., 1.), par_tm; abstol = 1e-12, reltol = 1e-10)
       
      -opts_po_cont = ContinuationPar(opts_br, dsmax = 0.1, ds= -0.0001, dsmin = 1e-4, max_steps = 100, tol_stability = 1e-4)
      +opts_po_cont = ContinuationPar(opts_br, dsmax = 0.1, ds= -0.0001, dsmin = 1e-4, max_steps = 110, tol_stability = 1e-4)
       
       br_posh = @time continuation(
       	br, 4, opts_po_cont,
       	# this is where we tell that we want Standard Shooting
       	# with 15 time sections
       	ShootingProblem(15, probsh, Rodas5(), parallel = true);
      -	# this to help branching:
      -	# specify guess for parameter value
      -	δp = 0.0005,
       	# regular continuation parameters
      -	verbosity = 2, plot = true,
      +	plot = true,
       	args_po...,
       	# we reject the step when the residual is high
       	callback_newton = BK.cbMaxNorm(10)
      @@ -1341,2207 +1212,2476 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + -

      References

      • Cortes

        Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.

      +

      References

      • Cortes

        Cortes, Jesus M., Mathieu Desroches, Serafim Rodrigues, Romain Veltz, Miguel A. Muñoz, and Terrence J. Sejnowski. Short-Term Synaptic Plasticity in the Deterministic Tsodyks–Markram Model Leads to Unpredictable Network Dynamics.” Proceedings of the National Academy of Sciences 110, no. 41 (October 8, 2013): 16610–15. https://doi.org/10.1073/pnas.1316071110.

      diff --git a/dev/tutorials/tutorialCarrier/index.html b/dev/tutorials/tutorialCarrier/index.html index cf98ce29..bf785fa5 100644 --- a/dev/tutorials/tutorialCarrier/index.html +++ b/dev/tutorials/tutorialCarrier/index.html @@ -51,7 +51,7 @@ │ 5 │ 5.4726e-07 │ 1 │ │ 6 │ 1.2302e-12 │ 1 │ └─────────────┴──────────────────────┴────────────────┘ - 3.047772 seconds (3.56 M allocations: 240.963 MiB, 2.33% gc time, 99.98% compilation time)

      First try with automatic bifurcation diagram

      We can start by using our Automatic bifurcation method.

      optcont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= -0.01, p_min = 0.05, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, max_iterations = 20, verbose = true), max_steps = 300, detect_bifurcation = 3, nev = 40)
      +  3.180670 seconds (3.07 M allocations: 206.702 MiB, 4.22% gc time, 99.98% compilation time)

      First try with automatic bifurcation diagram

      We can start by using our Automatic bifurcation method.

      optcont = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= -0.01, p_min = 0.05, plot_every_step = 10, newton_options = NewtonPar(tol = 1e-8, max_iterations = 20, verbose = true), max_steps = 300, detect_bifurcation = 3, nev = 40)
       
       diagram = bifurcationdiagram(prob,
           # particular bordered linear solver to use
      @@ -64,244 +64,244 @@
       scene = plot(diagram)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      However, this is a bit disappointing as we only find two branches.

      Second try with deflated continuation

      # deflation operator to hold solutions
       deflationOp = DeflationOperator(2, dot, 1.0, [sol.u])
       
      @@ -332,4 +332,4 @@
         verbosity = 0,
       	)
       
      -plot(br...)

      We obtain the following result which is remarkable because it contains many more disconnected branches which we did not find in the first try.

      +plot(br...)

      We obtain the following result which is remarkable because it contains many more disconnected branches which we did not find in the first try.

      diff --git a/dev/tutorials/tutorials/index.html b/dev/tutorials/tutorials/index.html index 94aba76c..44106df4 100644 --- a/dev/tutorials/tutorials/index.html +++ b/dev/tutorials/tutorials/index.html @@ -1,2 +1,2 @@ -Tutorials · Bifurcation Analysis in Julia

      Tutorials

      The tutorials are rated by the following scale of difficulty

      1. 🟢 basic knowledge of (numerical) bifurcation theory (following equilibria / periodic orbits)
      2. 🟡 advanced knowledge of (numerical) bifurcation theory (codim 2 bifurcations of equilibria)
      3. 🟠 high level of knowledge of (numerical) bifurcation theory (codim 2 bifurcations of periodic orbits, tweaking the methods)
      4. 🟤 very advanced tutorial, research level

      There are three levels of automatization of the computation in these tutorials:

      1. fully automatic bifurcation diagram (aBD) computation (only for equilibria): one uses bifurcationdiagram and let it compute the diagram fully automatically. Another possibility is to use deflated continuation.
      2. semi-automatic bifurcation diagram computation: one uses automatic branch switching (aBS) to compute branches at specified bifurcation points
      3. manual bifurcation diagram computation: one does not use automatic branch switching. This has only educational purposes or for complex problems where aBS fails.

      ODE examples

      These examples are specific to ODEs.

      Computation of equilibria

      Codimension 2 bifurcations of equilibria

      Periodic orbits

      We provide some examples focused on the computation of periodic orbits. Here is one where we present the different ways to compute periodic orbits.

      Here is one for aBS from period-doubling bifurcations of periodic orbits

      In the next tutorial, we show how to refine a periodic orbit guess obtained from numerical simulation. We also show how to perform continuation of PD/NS points using Shooting or Collocation.

      In the next tutorial, we showcase the detection of Chenciner bifurcations. This is a relatively advanced tutorial, so we don't give much explanations. The reader should get first familiar with the above simpler examples.

      In the next tutorial, we showcase aBS from Bautin/HH to curve of Fold/NS of periodic orbits.

      Homoclinic orbits

      Based on the package HclinicBifurcationKit.jl and its docs.

      DAE examples

      DDE examples

      See the tutorials of DDEBifurcationKit.jl.

      Examples based on ModelingToolkit

      PDEs: bifurcations of equilibria

      PDEs: automatic bifurcation diagram

      PDEs: bifurcations of periodic orbits

      PDEs based on FEM with Gridap.jl

      Symmetries, freezing, waves, fronts

      +Tutorials · Bifurcation Analysis in Julia

      Tutorials

      The tutorials are rated by the following scale of difficulty

      1. 🟢 basic knowledge of (numerical) bifurcation theory (following equilibria / periodic orbits)
      2. 🟡 advanced knowledge of (numerical) bifurcation theory (codim 2 bifurcations of equilibria)
      3. 🟠 high level of knowledge of (numerical) bifurcation theory (codim 2 bifurcations of periodic orbits, tweaking the methods)
      4. 🟤 very advanced tutorial, research level

      There are three levels of automatization of the computation in these tutorials:

      1. fully automatic bifurcation diagram (aBD) computation (only for equilibria): one uses bifurcationdiagram and let it compute the diagram fully automatically. Another possibility is to use deflated continuation.
      2. semi-automatic bifurcation diagram computation: one uses automatic branch switching (aBS) to compute branches at specified bifurcation points
      3. manual bifurcation diagram computation: one does not use automatic branch switching. This has only educational purposes or for complex problems where aBS fails.

      ODE examples

      These examples are specific to ODEs.

      Computation of equilibria

      Codimension 2 bifurcations of equilibria

      Periodic orbits

      We provide some examples focused on the computation of periodic orbits. Here is one where we present the different ways to compute periodic orbits.

      Here is one for aBS from period-doubling bifurcations of periodic orbits

      In the next tutorial, we show how to refine a periodic orbit guess obtained from numerical simulation. We also show how to perform continuation of PD/NS points using Shooting or Collocation.

      In the next tutorial, we showcase the detection of Chenciner bifurcations. This is a relatively advanced tutorial, so we don't give much explanations. The reader should get first familiar with the above simpler examples.

      In the next tutorial, we showcase aBS from Bautin/HH to curve of Fold/NS of periodic orbits.

      Homoclinic orbits

      Based on the package HclinicBifurcationKit.jl and its docs.

      DAE examples

      DDE examples

      See the tutorials of DDEBifurcationKit.jl.

      Examples based on ModelingToolkit

      PDEs: bifurcations of equilibria

      PDEs: automatic bifurcation diagram

      PDEs: bifurcations of periodic orbits

      PDEs based on FEM with Gridap.jl

      Symmetries, freezing, waves, fronts

      diff --git a/dev/tutorials/tutorials1/index.html b/dev/tutorials/tutorials1/index.html index 36d7e460..4fc265ad 100644 --- a/dev/tutorials/tutorials1/index.html +++ b/dev/tutorials/tutorials1/index.html @@ -29,259 +29,259 @@ │ 3 │ 2.4336e-06 │ 1 │ │ 4 │ 6.7452e-12 │ 1 │ └─────────────┴──────────────────────┴────────────────┘ - 0.001161 seconds (342 allocations: 1.262 MiB)

      Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.

      We can perform numerical continuation w.r.t. the parameter $\alpha$. This time, we need to provide additional parameters, but now for the continuation method:

      optcont = ContinuationPar(dsmin = 0.01, dsmax = 0.2, ds= 0.1, p_min = 0., p_max = 4.2,
      +  0.001383 seconds (361 allocations: 2.302 MiB)

      Note that, in this case, we did not give the Jacobian. It was computed internally using Automatic Differentiation.

      We can perform numerical continuation w.r.t. the parameter $\alpha$. This time, we need to provide additional parameters, but now for the continuation method:

      optcont = ContinuationPar(dsmin = 0.01, dsmax = 0.2, ds= 0.1, p_min = 0., p_max = 4.2,
       	newton_options = NewtonPar(max_iterations = 10, tol = 1e-9))

      Next, we call the continuation routine as follows.

      br = continuation(prob, PALC(), optcont; plot = true)
       nothing #hide

      The parameter axis lens = @lens _.α is used to extract the component of par corresponding to α. Internally, it is used as get(par, lens) which returns 3.3.

      Tip

      We don't need to call newton first in order to use continuation.

      You should see

      scene = title!("") #hide
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      The left figure is the norm of the solution as function of the parameter $p=\alpha$, the y-axis can be changed by passing a different recordFromSolution to BifurcationProblem. The top right figure is the value of $\alpha$ as function of the iteration number. The bottom right is the solution for the current value of the parameter. This last plot can be modified by changing the argument plotSolution to BifurcationProblem.

      Bif. point detection

      Two Fold points were detected. This can be seen by looking at br.specialpoint, by the black dots on the continuation plots when doing plot(br, plotfold=true) or by typing br in the REPL. Note that the bifurcation points are located in br.specialpoint.

      Continuation of Fold points

      We get a summary of the branch by doing

      br
       ┌─ Curve type: EquilibriumCont
        ├─ Number of points: 58
      @@ -293,9 +293,9 @@
       If `br` is the name of the branch,
       ind_ev = index of the bifurcating eigenvalue e.g. `br.eig[idx].eigenvals[ind_ev]`
       
      -- #  1,       bp at α ≈ +4.04103799 ∈ (+4.04103799, +4.04115545), |δp|=1e-04, [converged], δ = ( 1,  0), step =   5, eigenelements in eig[  6], ind_ev =   3
      -- #  2,       bp at α ≈ +3.15565319 ∈ (+3.15565221, +3.15565319), |δp|=1e-06, [converged], δ = (-1,  0), step =  23, eigenelements in eig[ 24], ind_ev =   3
      -- #  3, endpoint at α ≈ +4.20000000,                                                                     step =  57
      +- #  1,       bp at α ≈ +4.04103799 ∈ (+4.04103799, +4.04115545), |δp|=1e-04, [converged], δ = ( 1,  0), step =   5, eigenelements in eig[  6], ind_ev =   3
      +- #  2,       bp at α ≈ +3.15565319 ∈ (+3.15565221, +3.15565319), |δp|=1e-06, [converged], δ = (-1,  0), step =  23, eigenelements in eig[ 24], ind_ev =   3
      +- #  3, endpoint at α ≈ +4.20000000,                                                                     step =  57
       

      We can take the first Fold point, which has been guessed during the previous continuation run and locate it precisely. However, this only works well when the jacobian is computed analytically. We use automatic differentiation for that

      # index of the Fold bifurcation point in br.specialpoint
       indfold = 2
       
      @@ -310,51 +310,51 @@
       scene = plot(outfoldco, plotfold = true, legend = :bottomright)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Tip

      The performances for computing the curve of Fold is not that great. It is because we use the default solver tailored for ODE. If you pass jacobian_ma = :minaug to the last continuation call, you should see a great improvement in performances.

      Using GMRES or another linear solver

      We continue the previous example but now using Matrix Free methods. The user can pass its own solver by implementing a version of LinearSolver. Some linear solvers have been implemented from KrylovKit.jl and IterativeSolvers.jl (see Linear solvers (LS) for more information), we can use them here. Note that we can also use preconditioners as shown below. The same functionality is present for the eigensolver.

      # derivative of N
       dN(x; a = 0.5, b = 0.01) = (1-b*x^2+2*a*x)/(1+b*x^2)^2
       
      @@ -397,7 +397,7 @@
       │       3     │       2.4336e-06     │       74       │
       │       4     │       5.6275e-12     │       63       │
       └─────────────┴──────────────────────┴────────────────┘
      -  1.871537 seconds (2.66 M allocations: 188.173 MiB, 8.94% gc time, 99.82% compilation time)

      We can improve this computation, i.e. reduce the number of Linear-Iterations, by using a preconditioner

      using SparseArrays
      +  1.215387 seconds (1.43 M allocations: 96.503 MiB, 5.77% gc time, 99.58% compilation time)

      We can improve this computation, i.e. reduce the number of Linear-Iterations, by using a preconditioner

      using SparseArrays
       
       # define preconditioner which is basically Δ
       P = spdiagm(0 => -2 * (n-1)^2 * ones(n), -1 => (n-1)^2 * ones(n-1), 1 => (n-1)^2 * ones(n-1))
      @@ -417,4 +417,4 @@
       │       4     │       4.8929e-09     │        3       │
       │       5     │       5.6333e-12     │        4       │
       └─────────────┴──────────────────────┴────────────────┘
      -  1.606638 seconds (2.26 M allocations: 154.697 MiB, 9.82% gc time, 99.96% compilation time)
      + 1.316931 seconds (2.42 M allocations: 166.614 MiB, 8.07% gc time, 99.92% compilation time)
      diff --git a/dev/tutorials/tutorials1b/index.html b/dev/tutorials/tutorials1b/index.html index 72666f38..a197006c 100644 --- a/dev/tutorials/tutorials1b/index.html +++ b/dev/tutorials/tutorials1b/index.html @@ -66,4 +66,4 @@ linear_algo = BorderingBLS(solver = DefaultLS(), check_precision = false), plot_solution = (x, p; kwargs...) -> plot!(x; label = "l = $(length(x))", kwargs...), verbosity = 2, - normC = x -> norm(x, Inf64))
      + normC = x -> norm(x, Inf64))

      diff --git a/dev/tutorials/tutorials2/index.html b/dev/tutorials/tutorials2/index.html index fff51fa5..dd6f1efe 100644 --- a/dev/tutorials/tutorials2/index.html +++ b/dev/tutorials/tutorials2/index.html @@ -139,4 +139,4 @@ PALC(), optcont; plot = true)

      and using plot(br, br1), we obtain:

      Note that the plot provides the stability of solutions and bifurcation points. Interested readers should consult the associated file example/SH2d-fronts.jl in the example folder.

      Automatic branch switching

      Instead of relying on deflated newton, we can use Branch switching to compute the different branches emanating from the bifurcation point. For example, the following code will perform automatic branch switching from the second bifurcation point of br:

      br2 = continuation(br, 2, setproperties(optcont; ds = -0.001, detect_bifurcation = 3, plot_every_step = 5, max_steps = 170);  nev = 30,
       	plot = true, verbosity = 2,
      -	normC = norminf)

      We can then plot the branches using plot(br, br2, br3) and get

      + normC = norminf)

      We can then plot the branches using plot(br, br2, br3) and get

      diff --git a/dev/tutorials/tutorials2b/index.html b/dev/tutorials/tutorials2b/index.html index d8c31fbd..9c176ec1 100644 --- a/dev/tutorials/tutorials2b/index.html +++ b/dev/tutorials/tutorials2b/index.html @@ -152,4 +152,4 @@ - # 18, nd at p ≈ +0.00057801 ∈ (-0.00122418, +0.00057801), |δp|=2e-03, [converged], δ = ( 5, 0), step = 64, eigenelements in eig[ 65], ind_ev = 6 - # 19, nd at p ≈ +0.00320921 ∈ (+0.00141327, +0.00320921), |δp|=2e-03, [converged], δ = (10, 0), step = 65, eigenelements in eig[ 66], ind_ev = 16 Fold points: -- # 1, fold at p ≈ -0.21528694 ∈ (-0.21528694, -0.21528694), |δp|=-1e+00, [ guess], δ = ( 0, 0), step = 24, eigenelements in eig[ 24], ind_ev = 0

      +- # 1, fold at p ≈ -0.21528694 ∈ (-0.21528694, -0.21528694), |δp|=-1e+00, [ guess], δ = ( 0, 0), step = 24, eigenelements in eig[ 24], ind_ev = 0

      diff --git a/dev/tutorials/tutorials3/index.html b/dev/tutorials/tutorials3/index.html index 08139e15..3c2e1ce5 100644 --- a/dev/tutorials/tutorials3/index.html +++ b/dev/tutorials/tutorials3/index.html @@ -87,192 +87,192 @@ 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 l ≈ +0.51133101 ∈ (+0.51130339, +0.51133101), |δp|=3e-05, [converged], δ = ( 2, 2), step = 19, eigenelements in eig[ 20], ind_ev = 2 -- # 2, hopf at l ≈ +1.02261272 ∈ (+1.02260927, +1.02261272), |δp|=3e-06, [converged], δ = ( 2, 2), step = 56, eigenelements in eig[ 57], ind_ev = 4 -- # 3, hopf at l ≈ +1.53388407 ∈ (+1.53388364, +1.53388407), |δp|=4e-07, [ guessL], δ = ( 2, 2), step = 93, eigenelements in eig[ 94], ind_ev = 6 -- # 4, endpoint at l ≈ +1.90000000, step = 119 +- # 1, hopf at l ≈ +0.51133101 ∈ (+0.51130339, +0.51133101), |δp|=3e-05, [converged], δ = ( 2, 2), step = 19, eigenelements in eig[ 20], ind_ev = 2 +- # 2, hopf at l ≈ +1.02261272 ∈ (+1.02260927, +1.02261272), |δp|=3e-06, [converged], δ = ( 2, 2), step = 56, eigenelements in eig[ 57], ind_ev = 4 +- # 3, hopf at l ≈ +1.53388407 ∈ (+1.53388364, +1.53388407), |δp|=4e-07, [ guessL], δ = ( 2, 2), step = 93, eigenelements in eig[ 94], ind_ev = 6 +- # 4, endpoint at l ≈ +1.90000000, step = 119

      We obtain the following bifurcation diagram with 3 Hopf bifurcation points

      scene = plot(br)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Normal form computation

      We can compute the normal form of the Hopf points as follows

      hopfpt = get_normal_form(br, 1)
      SuperCritical - Hopf bifurcation point at l ≈ 0.5113310149554013.
      -Frequency ω ≈ 2.1394991675560213
      -Period of the periodic orbit ≈ 2.9367552006841646
      +Frequency ω ≈ 2.139499167556009
      +Period of the periodic orbit ≈ 2.9367552006841815
       Normal form z⋅(iω + a⋅δp + b⋅|z|²):
      -┌─ a = 0.8799938241566385 + 0.5689771353701978im
      -└─ b = -0.0015608102901474054 + 0.0015634810970086219im
      +┌─ a = 0.879995762292243 + 0.5689799205320438im
      +└─ b = -0.0015608102901474297 + 0.0015634810970086418im
       

      Continuation of Hopf points

      We use the bifurcation points guesses located in br.specialpoint to turn them into precise bifurcation points. For the second one, we have

      # index of the Hopf point in br.specialpoint
       ind_hopf = 2
       
       # newton iterations to compute the Hopf point
       hopfpoint = newton(br, ind_hopf; normN = norminf)
      -BK.converged(hopfpoint) && printstyled(color=:red, "--> We found a Hopf Point at l = ", hopfpoint.u.p[1], ", ω = ", hopfpoint.u.p[2], ", from l = ", br.specialpoint[ind_hopf].param, "\n")
      --> We found a Hopf Point at l = 1.022612527227387, ω = -2.139509289533431, from l = 1.022612721393132

      We now perform a Hopf continuation with respect to the parameters l, β

      Tip

      You don't need to call newton first in order to use continuation.

      optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)
      +BK.converged(hopfpoint) && printstyled(color=:red, "--> We found a Hopf Point at l = ", hopfpoint.u.p[1], ", ω = ", hopfpoint.u.p[2], ", from l = ", br.specialpoint[ind_hopf].param, "\n")
      --> We found a Hopf Point at l = 1.0226125272271296, ω = -2.1395092895332235, from l = 1.022612721393132

      We now perform a Hopf continuation with respect to the parameters l, β

      Tip

      You don't need to call newton first in order to use continuation.

      optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)
       
       br_hopf = continuation(br, ind_hopf, (@lens _.β),
       	optcdim2, verbosity = 2,
      @@ -286,45 +286,45 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +

      Computation of the branch of periodic orbits (Finite differences)

      We now compute the bifurcated branches of periodic solutions from the Hopf points using Periodic orbits based on Trapezoidal rule. One has just to pass a PeriodicOrbitTrapProblem.

      We start by providing a linear solver and some options for the continuation to work

      # automatic branch switching from Hopf point
       opt_po = NewtonPar(tol = 1e-10, verbose = true, max_iterations = 15)
      @@ -365,580 +365,577 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Using the above call, it is very easy to find the first branches:

      We note that there are several branch points (blue points) on the above diagram. This means that there are additional branches in the neighborhood of these points. We now turn to automatic branch switching on these branches. This functionality, as we shall see, is only provided for PeriodicOrbitTrapProblem.

      Let's say we want to branch from the first branch point of the first curve pink branch. The syntax is very similar to the previous one:

      br_po2 = continuation(
       	# arguments for branch switching
      @@ -1092,4 +1089,4 @@ 

      and you should see:

      + normC = norminf)

      and you should see:

      diff --git a/dev/tutorials/tutorials3b/index.html b/dev/tutorials/tutorials3b/index.html index e78db36d..a17b10ec 100644 --- a/dev/tutorials/tutorials3b/index.html +++ b/dev/tutorials/tutorials3b/index.html @@ -87,235 +87,235 @@ 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 l ≈ +0.51200774 ∈ (+0.51199393, +0.51200774), |δp|=1e-05, [converged], δ = ( 2, 2), step = 19, eigenelements in eig[ 20], ind_ev = 2 -- # 2, hopf at l ≈ +1.02398602 ∈ (+1.02398516, +1.02398602), |δp|=9e-07, [converged], δ = ( 2, 2), step = 56, eigenelements in eig[ 57], ind_ev = 4 -- # 3, hopf at l ≈ +1.53596689 ∈ (+1.53596517, +1.53596689), |δp|=2e-06, [converged], δ = ( 2, 2), step = 93, eigenelements in eig[ 94], ind_ev = 6 -- # 4, endpoint at l ≈ +1.90000000, step = 119 +- # 1, hopf at l ≈ +0.51200774 ∈ (+0.51199393, +0.51200774), |δp|=1e-05, [converged], δ = ( 2, 2), step = 19, eigenelements in eig[ 20], ind_ev = 2 +- # 2, hopf at l ≈ +1.02398602 ∈ (+1.02398516, +1.02398602), |δp|=9e-07, [converged], δ = ( 2, 2), step = 56, eigenelements in eig[ 57], ind_ev = 4 +- # 3, hopf at l ≈ +1.53596689 ∈ (+1.53596517, +1.53596689), |δp|=2e-06, [converged], δ = ( 2, 2), step = 93, eigenelements in eig[ 94], ind_ev = 6 +- # 4, endpoint at l ≈ +1.90000000, step = 119

      We obtain the following bifurcation diagram with 3 Hopf bifurcation points

      scene = plot(br)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Normal form computation

      We can compute the normal form of the Hopf points as follows

      hopfpt = get_normal_form(br, 1)
      SuperCritical - Hopf bifurcation point at l ≈ 0.5120077382420837.
      -Frequency ω ≈ 2.139502108538091
      -Period of the periodic orbit ≈ 2.9367511637896206
      +Frequency ω ≈ 2.1395021085381014
      +Period of the periodic orbit ≈ 2.9367511637896064
       Normal form z⋅(iω + a⋅δp + b⋅|z|²):
      -┌─ a = 0.8788499222680364 + 0.5682401608688544im
      -└─ b = -0.0009377275090476322 + 0.0009393386916539157im
      +┌─ a = 0.8788518795432937 + 0.5682340619831843im
      +└─ b = -0.0009377275090476174 + 0.0009393386916539204im
       

      Continuation of Hopf points

      We use the bifurcation points guesses located in br.specialpoint to turn them into precise bifurcation points. For the second one, we have

      # index of the Hopf point in br.specialpoint
       ind_hopf = 2
       
       # newton iterations to compute the Hopf point
       hopfpoint = newton(br, ind_hopf; normN = norminf)
      -BK.converged(hopfpoint) && printstyled(color=:red, "--> We found a Hopf Point at l = ", hopfpoint.u.p[1], ", ω = ", hopfpoint.u.p[2], ", from l = ", br.specialpoint[ind_hopf].param, "\n")
      --> We found a Hopf Point at l = 1.0239851696528288, ω = -2.139509289533432, from l = 1.0239860208180194

      We now perform a Hopf continuation with respect to the parameters l, β

      Tip

      You don't need to call newton first in order to use continuation.

      optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)
      +BK.converged(hopfpoint) && printstyled(color=:red, "--> We found a Hopf Point at l = ", hopfpoint.u.p[1], ", ω = ", hopfpoint.u.p[2], ", from l = ", br.specialpoint[ind_hopf].param, "\n")
      --> We found a Hopf Point at l = 1.0239851696545312, ω = -2.1395092895331436, from l = 1.0239860208180194

      We now perform a Hopf continuation with respect to the parameters l, β

      Tip

      You don't need to call newton first in order to use continuation.

      optcdim2 = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds= 0.01, p_max = 6.5, p_min = 0.0, newton_options = opt_newton, detect_bifurcation = 0)
       br_hopf = continuation(br, ind_hopf, (@lens _.β), optcdim2, normC = norminf, jacobian_ma = :minaug)
       scene = plot(br_hopf)
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +

      Continuation of periodic orbits (Finite differences)

      Here, we perform continuation of periodic orbits branching from the Hopf bifurcation points.We need an educated guess for the periodic orbit which is given by guess_from_hopf:

      # number of time slices
       M = 51
      @@ -343,45 +343,45 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - + - +

      and obtain

      ┌─────────────────────────────────────────────────────┐
       │ Newton step         residual     linear iterations  │
      @@ -1607,108 +1607,108 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - +

      Deflation for periodic orbit problems

      Looking for periodic orbits branching of bifurcation points, it is very useful to use newton algorithm with deflation. We thus define a deflation operator (see previous example)

      deflationOp = DeflationOperator(2, (x,y) -> dot(x[1:end-1], y[1:end-1]), 1.0, [zero(orbitguess_f)])

      which allows to find periodic orbits different from orbitguess_f. Note that the dot product removes the last component, i.e. the period of the cycle is not considered during this particular deflation. We can now use

      outpo_f = @time newton(poTrap, orbitguess_f, deflationOp, opt_po; normN = norminf)

      Floquet coefficients

      A basic method for computing Floquet coefficients based on the eigenvalues of the monodromy operator is available (see FloquetQaD). It is precise enough to locate bifurcations. Their computation is triggered like in the case of a regular call to continuation:

      opt_po = @set opt_po.eigsolver = DefaultEig()
       opts_po_cont = ContinuationPar(dsmin = 0.001, dsmax = 0.04, ds= -0.01, p_max = 3.0, max_steps = 200, newton_options = opt_po, nev = 5, tol_stability = 1e-6, detect_bifurcation = 3)
      @@ -2477,4 +2477,4 @@ 

      +
      diff --git a/dev/tutorials/tutorialsCGL/index.html b/dev/tutorials/tutorialsCGL/index.html index d084864a..f84fa504 100644 --- a/dev/tutorials/tutorialsCGL/index.html +++ b/dev/tutorials/tutorialsCGL/index.html @@ -90,276 +90,276 @@ 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 r ≈ +1.14777610 ∈ (+1.14766562, +1.14777610), |δp|=1e-04, [converged], δ = ( 2, 2), step = 94, eigenelements in eig[ 95], ind_ev = 2 -- # 2, hopf at r ≈ +1.86107007 ∈ (+1.86018618, +1.86107007), |δp|=9e-04, [converged], δ = ( 2, 2), step = 195, eigenelements in eig[196], ind_ev = 4 -- # 3, endpoint at r ≈ +2.00000000, step = 215 +- # 1, hopf at r ≈ +1.14777610 ∈ (+1.14766562, +1.14777610), |δp|=1e-04, [converged], δ = ( 2, 2), step = 94, eigenelements in eig[ 95], ind_ev = 2 +- # 2, hopf at r ≈ +1.86107007 ∈ (+1.86018618, +1.86107007), |δp|=9e-04, [converged], δ = ( 2, 2), step = 195, eigenelements in eig[196], ind_ev = 4 +- # 3, endpoint at r ≈ +2.00000000, step = 215

      which gives

      scene = plot(br, ylims=(-0.1,0.1))
      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Normal form computation

      We compute the Hopf normal form of the first bifurcation point.

      hopfpt = get_normal_form(br, 1)
      SubCritical - Hopf bifurcation point at r ≈ 1.1477761028276166.
      -Frequency ω ≈ 0.9999999999999958
      -Period of the periodic orbit ≈ 6.283185307179613
      +Frequency ω ≈ 0.9999999999999991
      +Period of the periodic orbit ≈ 6.283185307179592
       Normal form z⋅(iω + a⋅δp + b⋅|z|²):
      -┌─ a = 0.9999993645066957 + 2.1722012059675938e-8im
      -└─ b = 0.004870129870129868 + 0.00048701298701298685im
      +┌─ a = 0.9999993504941648 - 6.405445633973413e-9im
      +└─ b = 0.004870129870129868 + 0.000487012987012987im
       

      So the Hopf branch is subcritical.

      Codim 2 Hopf continuation

      Having detected 2 hopf bifurcation points, we now continue them in the plane $(\gamma, r)$.

      Before we start the codim 2 continuation, we tell BifurcationKit.jl to use the spectral information start_with_eigen = true because the left eigenvector of the Jacobian is simply not the conjugate of the right one.

      # we perform Hopf continuation of the first Hopf point in br
       ind_hopf = 1
       br_hopf = @time continuation(
      @@ -375,68 +375,68 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      with detailed information

      br_hopf
       ┌─ Curve type: HopfCont
        ├─ Number of points: 46
        ├─ Type of vectors: BorderedArray{Vector{Float64}, Vector{Float64}}
      - ├─ Parameter γ starts at 0.0, ends at 1.0098353536481632
      + ├─ Parameter γ starts at 0.0, ends at 1.0098353536481615
        ├─ 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,       gh at γ ≈ +0.31388746 ∈ (+0.30785258, +0.31388746), |δp|=6e-03, [converged], δ = ( 0,  0), step =  14, eigenelements in eig[ 15], ind_ev =   0
      -- #  2,       bt at γ ≈ +1.00983535 ∈ (+0.98529855, +1.00983535), |δp|=2e-02, [converged], δ = ( 0,  0), step =  45, eigenelements in eig[ 46], ind_ev =   0
      -- #  3, endpoint at γ ≈ +1.00983535,                                                                     step =  45
      +- #  1,       gh at γ ≈ +0.31388746 ∈ (+0.30785258, +0.31388746), |δp|=6e-03, [converged], δ = ( 0,  0), step =  14, eigenelements in eig[ 15], ind_ev =   0
      +- #  2,       bt at γ ≈ +1.00983535 ∈ (+0.98529855, +1.00983535), |δp|=2e-02, [converged], δ = ( 0,  0), step =  45, eigenelements in eig[ 46], ind_ev =   0
      +- #  3, endpoint at γ ≈ +1.00983535,                                                                     step =  45
       

      We can now construct the curve of Fold points branching off the Bogdanov-Takens bifurcation we just detected.

      # find the index of the BT point
       indbt = findfirst(x -> x.type == :bt, br_hopf.specialpoint)
       # branch from the BT point
      @@ -451,65 +451,65 @@ 

      - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

      Periodic orbits continuation with stability

      Having found two Hopf bifurcation points, we aim at computing the periodic orbits branching from them. Like for the Brusselator example, we need to find some educated guess for the periodic orbits in order to have a successful Newton call.

      The following code is very close to the one explained in the tutorial 1d Brusselator (advanced user) so we won't give too much details here.

      We focus on the first Hopf bifurcation point. Note that, we do not improve the guess for the Hopf bifurcation point, e.g. by calling newtonHopf, as this is not really needed.

      # index of the Hopf point we want to branch from
       ind_hopf = 1
       
      @@ -828,4 +828,4 @@ 

      Preconditioner update

      For now, the preconditioner has been precomputed on the CPU which forbids its (efficient) update during continuation of a branch of periodic orbits. This could be improved using ilu0! and friends in CuArrays.

      + record_from_solution = (u, p) -> getAmplitude(poTrapMFGPU, u, par_cgl_gpu), normC = x->maximum(abs.(x)))

      Preconditioner update

      For now, the preconditioner has been precomputed on the CPU which forbids its (efficient) update during continuation of a branch of periodic orbits. This could be improved using ilu0! and friends in CuArrays.

      diff --git a/dev/tutorials/tutorialsCGLShoot/index.html b/dev/tutorials/tutorialsCGLShoot/index.html index ec2ff4cf..8aa8ad6f 100644 --- a/dev/tutorials/tutorialsCGLShoot/index.html +++ b/dev/tutorials/tutorialsCGLShoot/index.html @@ -151,4 +151,4 @@ verbosity = 3, plot = true, linear_algo = MatrixFreeBLS(@set ls.N = probSh.M*2n+2), plot_solution = (x, p; kwargs...) -> heatmap!(reshape(x[1:Nx*Ny], Nx, Ny); color=:viridis, kwargs...), - record_from_solution = (u, p) -> BK.getamplitude(probSh, u, (@set par_cgl.r = p.p); ratio = 2), normC = norminf)

      + record_from_solution = (u, p) -> BK.getamplitude(probSh, u, (@set par_cgl.r = p.p); ratio = 2), normC = norminf)

      diff --git a/dev/tutorials/tutorialsPD/index.html b/dev/tutorials/tutorialsPD/index.html index 3512ada8..9835ea26 100644 --- a/dev/tutorials/tutorialsPD/index.html +++ b/dev/tutorials/tutorialsPD/index.html @@ -117,4 +117,4 @@ verbosity = 2, plot = true, linear_algo = MatrixFreeBLS(@set ls.N = probSh.M*n+2), plot_solution = (x, p; kwargs...) -> (BK.plot_periodic_shooting!(x[1:end-1], 1; kwargs...); plot!(br_po_sh; subplot=1, legend=false)), - record_from_solution = (u, p; k...) -> BK.getmaximum(probSh, u, (@set par_br_pd.C = p.p); ratio = 2), normC = norminf)

      and plot it using plot(br_po_sh, br, br_po_sh_pd, label = ""):

      + record_from_solution = (u, p; k...) -> BK.getmaximum(probSh, u, (@set par_br_pd.C = p.p); ratio = 2), normC = norminf)

      and plot it using plot(br_po_sh, br, br_po_sh_pd, label = ""):

      diff --git a/dev/tutorials/tutorialsSH3d/index.html b/dev/tutorials/tutorialsSH3d/index.html index 86ea26fd..3de56715 100644 --- a/dev/tutorials/tutorialsSH3d/index.html +++ b/dev/tutorials/tutorialsSH3d/index.html @@ -160,4 +160,4 @@ contour3dMakie!(ax, br1[i].sol[2].x) ax.protrusions = (0, 0, 0, 10) end - display(fig)

      + display(fig)

      diff --git a/dev/waveEigen/index.html b/dev/waveEigen/index.html index 0ce3fbae..8b86acd9 100644 --- a/dev/waveEigen/index.html +++ b/dev/waveEigen/index.html @@ -1,2 +1,2 @@ -Eigen Solvers · Bifurcation Analysis in Julia

      Wave stability

      References

      • Beyn

        Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

      • Sandstede

        Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.

      +Eigen Solvers · Bifurcation Analysis in Julia

      Wave stability

      References

      • Beyn

        Beyn and Thümmler, Phase Conditions, Symmetries and PDE Continuation.

      • Sandstede

        Sandstede, Björn. “Stability of Travelling Waves.” In Handbook of Dynamical Systems, 2:983–1055. Elsevier, 2002. https://doi.org/10.1016/S1874-575X(02)80039-X.

      diff --git a/dev/zh/index.html b/dev/zh/index.html index 2c30589b..96e22222 100644 --- a/dev/zh/index.html +++ b/dev/zh/index.html @@ -2,4 +2,4 @@ Zero-Hopf · Bifurcation Analysis in Julia

      Normal form of the Zero-Hopf bifurcation

      We follow the paper[Kuznetsov],[Kuznetsov2] and consider a Cauchy problem

      \[\dot x=\mathbf F(x,p).\]

      We denote by $\mathbf L$ the jacobian of $\mathbf F$ at the bifurcation point $(x_0,p_0)$. We choose a basis such that:

      \[\mathbf L q_0=0, \quad \mathbf L q_1=i \omega_{0} q_1.\]

      Under some conditions, $x(t)\approx x_0+2\Re w_1(t)q_1+w_0(t)q_0$ where $w_i$ satisfy the normal form:

      \[\left\{\begin{aligned} \dot{w}_0= & \frac{1}{2} G_{200} w_0^2+G_{011}\left|w_1\right|^2+\frac{1}{6} G_{300} w_0^3 +G_{111} w_0\left|w_1\right|^2+O\left(\left\|\left(w_0, w_1, \bar{w}_1\right)\right\|^4\right) \\ \dot{w}_1= & i \omega_0 w_1+G_{110} w_0 w_1+\frac{1}{2} G_{210} w_0^2 w_1+\frac{1}{2} G_{021} w_1\left|w_1\right|^2 +O\left(\left\|\left(w_0, w_1, \bar{w}_1\right)\right\|^4\right) . -\end{aligned}\right.\tag{E}\]

      This normal form is usually computed in order to branch from a Zero-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the $G_{ijk}$ is returned.

      Normal form computation

      The normal form (E) can be automatically computed as follows

      get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

      br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type ZeroHopf.

      Note

      You should not need to call get_normal_form except if you need the full information about the branch point.

      References

      • Kuznetsov

        Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

      • Kuznetsov2

        Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.

      +\end{aligned}\right.\tag{E}\]

      This normal form is usually computed in order to branch from a Zero-Hopf bifurcation point to curves of Neimark-Sacker bifurcations of periodic orbits (see [Kuznetsov2]). Not all coefficients in (E) are required for this branching procedure, that is why only a subset of the $G_{ijk}$ is returned.

      Normal form computation

      The normal form (E) can be automatically computed as follows

      get_normal_form(br::ContResult, ind_bif::Int ; verbose = false, ζs = nothing, lens = getlens(br))

      br is a branch computed after a call to continuation with detection of bifurcation points enabled and ind_bif is the index of the bifurcation point on the branch br. The above call returns a point with information needed to compute the bifurcated branch. For more information about the optional parameters, we refer to get_normal_form. The result returns an object of type ZeroHopf.

      Note

      You should not need to call get_normal_form except if you need the full information about the branch point.

      References

      • Kuznetsov

        Kuznetsov, Yu. A. “Numerical Normalization Techniques for All Codim 2 Bifurcations of Equilibria in ODE’s.” SIAM Journal on Numerical Analysis 36, no. 4 (January 1, 1999): 1104–24. https://doi.org/10.1137/S0036142998335005.

      • Kuznetsov2

        Kuznetsov, Yu A., H. G. E. Meijer, W. Govaerts, and B. Sautois. “Switching to Nonhyperbolic Cycles from Codim 2 Bifurcations of Equilibria in ODEs.” Physica D: Nonlinear Phenomena 237, no. 23 (December 2008): 3061–68. https://doi.org/10.1016/j.physd.2008.06.006.