Library
- Library
Parameters
BifurcationKit.NewtonPar — Type
struct NewtonPar{T, L<:BifurcationKit.AbstractLinearSolver, E<:AbstractEigenSolver}Returns a variable containing parameters to affect the newton algorithm when solving F(x) = 0.
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 dampingalpha
For performance reasons, we decided to use an immutable structure to hold the parameters. One can use the package Accessors.jl to drastically simplify the mutation of different fields. See the tutorials for examples.
Internal fields
tol::Any: absolute tolerance forF(x). Default: 1.0e-12max_iterations::Int64: number of Newton iterations. Default: 25verbose::Bool: display Newton iterations? Default: falselinsolver::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)
BifurcationKit.ContinuationPar — Type
struct ContinuationPar{T, S<:BifurcationKit.AbstractLinearSolver, E<:AbstractEigenSolver}Returns a variable containing the parameters to affect the continuation algorithm used to solve F(x, p) = 0.
Arguments
dsmin, dsmaxare the minimum, maximum allowed arc-length value. It controls the density of points in the computed branch of solutions.ds = 0.01is the initial arc-length.p_min, p_maxallowed parameter range forpmax_steps = 100maximum number of continuation stepsnewton_options::NewtonPar: options for the Newton algorithmsave_to_file = false: save to file. A name is automatically generated or can be defined incontinuation. This requiresusing JLD2.save_sol_every_step::Int64 = 1at which continuation steps do we save the current solutionplot_every_step = 10at which continuation steps do we plot the current solution
Handling eigen-elements, their computation is triggered by the argument detect_bifurcation (see below)
nev = 3number of eigenvalues to be computed. It is automatically increased to have at leastnevunstable eigenvalues. To be set for proper bifurcation detection. See Detection of bifurcation points of Equilibria for more information.save_eig_every_step = 1record eigen vectors every specified steps. Important for memory limited resource, e.g. GPU.save_eigenvectors = trueImportant for memory limited resource, e.g. GPU.
Handling bifurcation detection
tol_stability = 1e-10lower bound on the real part of the eigenvalues to test for stability of equilibria and periodic orbitsdetect_fold = truedetect 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-16minimaldsfor the bisection algorithm for locating bifurcation pointsn_inversion = 2number of sign inversions in bisection algorithmmax_bisection_steps = 25maximum number of bisection stepstol_bisection_eigenvalue = 1e-16tolerance on real part of eigenvalue to detect bifurcation points in the bisection steps
Handling ds adaptation (see continuation for more information)
a = 0.5aggressiveness factor. It is used to adaptdsin order to have a number of newton iterations per continuation step roughly constant. The higherais, the larger the step sizedsis 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-16tolerance 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
BifurcationKit.cbMaxNorm — Type
cb = cbMaxNorm(maxres)Create a callback used to reject residuals larger than cb.maxres in the Newton iterations. See docs for newton.
BifurcationKit.cbMaxNormAndΔp — Type
cb = cbMaxNormAndΔp(maxres, δp)Create a callback used to reject residuals larger than cb.maxres or parameter step larger than δp in the Newton iterations. See docs for newton.
Results
BifurcationKit.NonLinearSolution — Type
Structure which holds the solution from application of Newton-Krylov algorithm to a nonlinear problem.
For example
sol = newton(prob, NewtonPar())methods
converged(sol)return whether the solution has converged.
Internal fields
u::Any: solution.prob::Any: nonlinear problem, typically aBifurcationProblem.residuals::Any: sequence of residuals.converged::Bool: has algorithm converged?itnewton::Int64: number of newton steps.itlineartot::Any: total number of linear iterations.
BifurcationKit.ContResult — Type
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).
Internal 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 stepi.itnewtonnumber of Newton iterations.itlineartotal number of linear iterations during newton (corrector).n_unstablenumber of eigenvalues with positive real part for each continuation step (to detect stationary bifurcation).n_imagnumber of eigenvalues with positive real part and non zero imaginary part at current continuation step (useful to detect Hopf bifurcation).stablestability of the computed solution for each continuation step. Hence,stableshould matcheig[step]which corresponds tobranch[k]for a givenk.stepcontinuation step (here equali).
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 argumentsave_sol_every_step::Int64(default 1) inContinuationPar.contparams::Any: The parameters used for the call tocontinuationwhich produced this branch. Must be aContinuationPar.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 functionalTrapeze,Shooting... will be saved here. Default: nothingspecialpoint::Vector: A vector holding the list of detected bifurcation points. SeeSpecialPointfor 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.propertynames(br)give the propertynames of a result.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 inbr.specialpoint.getlens(br)return the parameter axis used for the branch.get_lenses(br)return the parameter two axis used for the branch when 2 parameters continuation is used (Fold, Hopf, NS, PD).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 equationF(x, par) = 0.getparams(br, ind)Parameters passed to continuation and used in the equationF(x, par) = 0for the ind-th continuation step.setparam(br, p0)set the parameter valuep0according to::Lensfor the parameters of the problemgetprob(br).getlens(br)get the lens used for the computation of the branch.eigenvals(br, ind)give the eigenvalues at continuation stepind.eigenvalsfrombif(br, ind)give the eigenvalues at bifurcation point indexind.BifurcationKit._merge(br1, br2)merge twos branches into a singleContResult.type(br, ind)returns the type of the ind-th bifurcation point.br[k+1]gives information about the k-th step. A typical run yields the following.get_solution(br, ind)returns the ind-th solution.
julia> br[1]
(x = 0.0, param = 0.1, itnewton = 0, itlinear = 0, ds = -0.01, 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
0.08585786437626905
0.06464466094067263
0.03282485578727799
-1.2623798512809007e-5
-0.07160718539365075
-0.17899902778635765
-0.3204203840236672
-0.4618417402609767
-0.5continuation(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::AbstractBoundaryValueDiscretization)performs aBS from ind-th bifurcation point (which must be a Hopf bifurcation point) to branch of periodic orbits.
BifurcationKit.Branch — Type
struct Branch{Tkind, Tprob, T<:Union{ContResult, Vector{<:ContResult}}, Tbp} <: BifurcationKit.AbstractResult{Tkind, Tprob}A Branch is a structure which encapsulates the result of the computation of a branch bifurcating from a bifurcation point.
γ::Union{ContResult, Vector{<:ContResult}}: Set of branches branching off the bifurcation pointbp.bp::Any: Bifurcation point. It is thought as the root of the branches in γ.
BifurcationKit.SpecialPoint — Type
struct SpecialPoint{T, Tp, Tv, Tvτ} <: BifurcationKit.AbstractBifurcationPointStructure 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/).
Internal fields
type::Symbol: Description of the special points. In case ofEvents, this field records the user passed name to the event, or the default:userD,:userC. In case of bifurcation points, it can be one of the following names:- :bp Bifurcation point, simple eigenvalue crossing the imaginary axis - :fold Fold point - :hopf Hopf point - :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. - :cusp Cusp point - :gh Generalized Hopf point (also called Bautin point) - :bt Bogdanov-Takens point - :zh Zero-Hopf point - :hh Hopf-Hopf point - :ns Neimark-Sacker point - :pd Period-doubling point - :R1 Strong resonance 1:1 of periodic orbits - :R2 Strong resonance 1:2 of periodic orbits - :R3 Strong resonance 1:3 of periodic orbits - :R4 Strong resonance 1:4 of periodic orbits - :foldFlip Fold / Flip of periodic orbits - :foldNS Fold / Neimark-Sacker of periodic orbits - :pdNS Period-Doubling / Neimark-Sacker of periodic orbits - :gpd Generalized Period-Doubling of periodic orbits - :nsns Double Neimark-Sacker of periodic orbits - :ch Chenciner bifurcation of periodic orbits Default: :noneidx::Int64: Index inbr.branchorbr.eig(seeContResult) for which the bifurcation occurs. Default: 0param::Any: Parameter value at the special point (this is an estimate). Default: 0.0norm::Any: Norm of the equilibrium at the special point. Default: 0.0printsol::Any:printsol = record_from_solution(x, param)whererecord_from_solutionis one of the arguments tocontinuation. Default: 0.0x::Any: Solution at the special point. Default: Vector{T}(undef, 0)τ::BorderedArray{Tvτ, T} where {T, Tvτ}: Tangent along the branch at the special point. Default: BorderedArray(x, zero(T))ind_ev::Int64: Eigenvalue index responsible for detecting the special point (if applicable). Default: 0step::Int64: Continuation step at which the special occurs. Default: 0status::Symbol:status ∈ {:converged, :guess, :guessL}indicates whether the bisection algorithm was successful in detecting the special (bifurcation) point. Ifstatus == :guess, the bisection algorithm failed to meet the requirements given in::ContinuationPar. Same forstatus == :guessLbut the bisection algorithm stopped on the left of the bifurcation point. Default: :guessδ::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)precision::Any: Precision in the location of the special point Default: -1interval::Tuple{T, T} where T: Interval parameter containing the special point Default: (0, 0)
Associated methods
BifurcationKit.type(::SpecialPoint)returns the bifurcation type (::Symbol)
BifurcationKit.BifDiagNode — Type
Structure to hold a connected component of a bifurcation diagram which is encoded as a tree of BifDiagNode(s).
Internal fields
level::Int64: current recursion level in the tree.code::Int64: code for finding the current node in the tree, this is the index of the bifurcation point from which γ branches off.γ::Any: branch associated to the current node.child::Any: children of current node. These are the different branches off the bifurcation point in γ.
Methods
hasbranch(diagram)get_branch(diagram)return theAbstractBranchstored inside the current node.from(diagram)return the parent bifurcation point.diagram[code]For examplediagram[1,2,3]returnsdiagram.child[1].child[2].child[3]. This is essentially the Ulam-Harris-Neveu labeling.
Problems
BifurcationKit.BifFunction — Type
struct BifFunction{Tf, TFinp, Tdf, Tdfad, Tj, Tjad, TJinp, Td2f, Td2fc, Td3f, Td3fc, Tδ, Tjet} <: BifurcationKit.AbstractBifurcationFunctionStructure to hold the vector field and its derivatives. It should rarely be called directly. Also, in essence, it is very close to SciMLBase.ODEFunction.
Internal fields
F::Any: Vector field. Function of type out-of-placeresult = f(x, p)or inplacef(result, x, p). For type stability, the types ofxandresultshould matchF!::Any: Same as F but inplace with signature F!(result, x, p)dF::Any: Differential ofFwith respect tox, signaturedF(x,p,dx)dFad::Any: Adjoint of the Differential ofFwith respect tox, signaturedFad(x,p,dx)J::Any: Jacobian ofFat(x, p). It can assume three forms. 1. EitherJis a function andJ(x, p)returns a::AbstractMatrix. In this case, the default arguments ofcontparams::ContinuationParwill makecontinuationwork. 2. OrJis a function andJ(x, p)returns a function taking one argumentdxand returningdrof the same type asdx. In our notation,dr = J * dx. In this case, the default parameters ofcontparams::ContinuationParwill not work and you have to use a Matrix Free linear solver, for exampleGMRESIterativeSolvers, 3. OrJis a function andJ(x, p)returns a variablejwhich can assume any type. Then, you must implement a linear solverlsas a composite type, subtype ofAbstractLinearSolverwhich is called likels(j, rhs)and which returns the solution of the jacobian linear system. See for exampleexamples/SH2d-fronts-cuda.jl. This linear solver is passed toNewtonPar(linsolver = ls)which itself passed toContinuationPar. Similarly, you have to implement an eigensolvereigas a composite type, subtype ofAbstractEigenSolver.Jᵗ::Any: jacobian adjoint, it should be implemented in an efficient manner. For matrix-free methods,transposeis 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 passJᵗ = (x, p) -> transpose(dF(x, p)).J!::Any: Inplace jacobiand2F::Any: Second Differential ofFwith respect tox, signatured2F(x,p,dx1,dx2)d3F::Any: Third Differential ofFwith respect tox, signatured3F(x,p,dx1,dx2,dx3)d2Fc::Any: [internal] Second Differential ofFwith respect toxwhich accept complex vectors dxid3Fc::Any: [internal] Third Differential ofFwith respect toxwhich accept complex vectors dxiisSymmetric::Bool: 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. You can usein_bisection(state)to inquire whether the current state is in bisection mode.jet::Any: jet of the vector field.
Methods
residual(pb::BifFunction, x, p)callspb.F(x,p)residual!(pb::BifFunction, o, x, p)callspb.F(o, x, p)jacobian(pb::BifFunction, x, p)callspb.J(x, p)dF(pb::BifFunction, x, p, dx)callspb.dF(x, p, dx)R21(pb::BifFunction, x, p, dx1, dx2, dp1)callspb.jet.R21(x, p, dx1, dx2, dp1). Same for the other jet functions.- etc
BifurcationKit.BifurcationProblem — Type
struct BifurcationProblem{Tvf, Tu, Tp, Tl<:Union{typeof(identity), IndexLens, PropertyLens, ComposedFunction}, Tplot, Trec, Tgets, Tupdate} <: BifurcationKit.AbstractAllJetBifProblemStructure to hold a bifurcation problem. Generic case, the user has to set most options.
Methods
re_make(pb; kwargs...)modify a bifurcation problemgetu0(pb)callspb.u0getparams(pb)callspb.paramsgetlens(pb)callspb.lensgetparam(pb)callsget(pb.params, pb.lens)setparam(pb, p0)callsset(pb.params, pb.lens, p0)record_from_solution(pb)callspb.recordFromSolutionplot_solution(pb)callspb.plotSolutionis_symmetric(pb)callsis_symmetric(pb.VF)getdelta(prob)
Constructors
BifurcationProblem(F, u0, params, lens)all derivatives are computed using ForwardDiff.BifurcationProblem(F, u0, params, lens; J, Jᵗ, d2F, d3F, kwargs...)andkwargsare the fields above. You can pass your own jacobian withJ(seeBifFunctionfor description of the jacobian function) and jacobian adjoint withJᵗ. For example, this can be used to provide finite differences based jacobian usingBifurcationKit.finite_differences. You can also passrecord_from_solutionsee aboveplot_solutionsee aboveissymmetric[=false]whether the jacobian is symmetric, this remove the need of providing an adjointjvpjacobian-vector product, signaturejvp(x, p, dx)vjpvector-jacobian product (adjoint of jvp), signaturevjp(x, p,dx)d2Fsecond Differential ofFwith respect tox, signatured2F(x, p, dx1, dx2)d3Fthird Differential ofFwith respect tox, signatured3F(x, p, dx1, dx2, dx3)save_solutionspecify a particular way to record solution which are written inbr.sol. This can be useful in very particular situations and we recommend usingrecord_from_solutioninstead. For example, it is used internally to record the mesh in the collocation method because this mesh can be modified.
Internal fields
VF::Any: Vector field, typically aBifFunction.u0::Any: Initial guess.params::Any: Parameters.lens::Union{typeof(identity), IndexLens, PropertyLens, ComposedFunction}: Typically aAccessors.PropertyLens. It specifies which parameter axis amongparamsis used for continuation. For example, ifpar = (α = 1.0, β = 1.78), we can perform continuation w.r.t.αby usinglens = (@optic _.α). If you have an arraypar = [1.0, 2.0]and want to perform continuation w.r.t. the first variable, you can uselens = (@optic _[1])or pass directlylens = 1. For more information, we refer toAccessors.jl.plotSolution::Any: user function to plot solutions during continuation. Signature:plot_solution(x, p; kwargs...)forPlot.jlandplot_solution(ax, x, p; ax1 = nothing, kwargs...)for theMakie.jl.recordFromSolution::Any:record_from_solution = (x, p; k...) -> norm(x)function used to record a few indicators about the solution. It could benormor(x, p; k...) -> 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; k...) -> (x1 = x[1], x2 = x[2], nrm = norm(x))or simply(x, p; k...) -> (sum(x), 1)or(x, p; k...) -> [x[1], x[2]]. This will be stored incontres.branchwherecontres::AbstractBranchResultis the continuation curve of the bifurcation problem. Finally, the first component is used for plotting in the continuation curve.save_solution::Any: Function to save the full solution on the branch. Some problem are updated during computation (like periodic orbit functional with adaptive mesh) and this function allows to save the state of the problem along with the solution itself. Note that this should allocate the output (i.e. not as a view). Signature:save_solution(x, p). Defaults tosave_solution_default(x, p) = x. The saved solution can be retrieved back usingsaved_solutionwith signaturesaved_solution(x_saved). Finally, a functionrestore_problem!(prob, x_saved, pars)which defaults torestore_problem!(prob, x_saved, pars) = probshould be provided. It allows toupdatethe problem to the state it was atx_savedupdate!::Any: Function to update the problem after each continuation step. Defaults toupdate_default. It has signatureupdate!(prob, iter, state)whereprobis the current bifurcation problem,iter::ContIterablethe current iterable andstate::ContStatethe current state of the continuation. It should returntrueif the update was successful andfalseotherwise. The continuation will stop iffalseis returned. This type of function is useful for example to update the problem internals like meshes, preconditioners, etc. Note that you can extract the type of continuation fromiter(for exampleFoldCont) and thus modify the methodupdate!accordingly.
BifurcationKit.ODEBifProblem — Type
struct ODEBifProblem{Tvf, Tu, Tp, Tl<:Union{typeof(identity), IndexLens, PropertyLens, ComposedFunction}, Tplot, Trec, Tgets, Tupdate} <: BifurcationKit.AbstractAllJetBifProblemStructure to hold a bifurcation problem. Specific to Ordinary Differential Equations (ODE). The options are set accordingly. 🚧🚧 This is work in progress 🚧🚧.
Methods
re_make(pb; kwargs...)modify a bifurcation problemgetu0(pb)callspb.u0getparams(pb)callspb.paramsgetlens(pb)callspb.lensgetparam(pb)callsget(pb.params, pb.lens)setparam(pb, p0)callsset(pb.params, pb.lens, p0)record_from_solution(pb)callspb.recordFromSolutionplot_solution(pb)callspb.plotSolutionis_symmetric(pb)callsis_symmetric(pb.VF)getdelta(prob)
Constructors
ODEBifProblem(F, u0, params, lens)all derivatives are computed using ForwardDiff.ODEBifProblem(F, u0, params, lens; J, Jᵗ, d2F, d3F, kwargs...)andkwargsare the fields above. You can pass your own jacobian withJ(seeBifFunctionfor description of the jacobian function) and jacobian adjoint withJᵗ. For example, this can be used to provide finite differences based jacobian usingBifurcationKit.finite_differences. You can also passrecord_from_solutionsee aboveplot_solutionsee aboveissymmetric[=false]whether the jacobian is symmetric, this remove the need of providing an adjointjvpjacobian-vector product, signaturejvp(x, p, dx)vjpvector-jacobian product (adjoint of jvp), signaturevjp(x, p,dx)d2Fsecond Differential ofFwith respect tox, signatured2F(x, p, dx1, dx2)d3Fthird Differential ofFwith respect tox, signatured3F(x, p, dx1, dx2, dx3)save_solutionspecify a particular way to record solution which are written inbr.sol. This can be useful in very particular situations and we recommend usingrecord_from_solutioninstead. For example, it is used internally to record the mesh in the collocation method because this mesh can be modified.
Internal fields
VF::Any: Vector field, typically aBifFunction.u0::Any: Initial guess.params::Any: Parameters.lens::Union{typeof(identity), IndexLens, PropertyLens, ComposedFunction}: Typically aAccessors.PropertyLens. It specifies which parameter axis amongparamsis used for continuation. For example, ifpar = (α = 1.0, β = 1.78), we can perform continuation w.r.t.αby usinglens = (@optic _.α). If you have an arraypar = [1.0, 2.0]and want to perform continuation w.r.t. the first variable, you can uselens = (@optic _[1])or pass directlylens = 1. For more information, we refer toAccessors.jl.plotSolution::Any: user function to plot solutions during continuation. Signature:plot_solution(x, p; kwargs...)forPlot.jlandplot_solution(ax, x, p; ax1 = nothing, kwargs...)for theMakie.jl.recordFromSolution::Any:record_from_solution = (x, p; k...) -> norm(x)function used to record a few indicators about the solution. It could benormor(x, p; k...) -> 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; k...) -> (x1 = x[1], x2 = x[2], nrm = norm(x))or simply(x, p; k...) -> (sum(x), 1)or(x, p; k...) -> [x[1], x[2]]. This will be stored incontres.branchwherecontres::AbstractBranchResultis the continuation curve of the bifurcation problem. Finally, the first component is used for plotting in the continuation curve.save_solution::Any: Function to save the full solution on the branch. Some problem are updated during computation (like periodic orbit functional with adaptive mesh) and this function allows to save the state of the problem along with the solution itself. Note that this should allocate the output (i.e. not as a view). Signature:save_solution(x, p). Defaults tosave_solution_default(x, p) = x. The saved solution can be retrieved back usingsaved_solutionwith signaturesaved_solution(x_saved). Finally, a functionrestore_problem!(prob, x_saved, pars)which defaults torestore_problem!(prob, x_saved, pars) = probshould be provided. It allows toupdatethe problem to the state it was atx_savedupdate!::Any: Function to update the problem after each continuation step. Defaults toupdate_default. It has signatureupdate!(prob, iter, state)whereprobis the current bifurcation problem,iter::ContIterablethe current iterable andstate::ContStatethe current state of the continuation. It should returntrueif the update was successful andfalseotherwise. The continuation will stop iffalseis returned. This type of function is useful for example to update the problem internals like meshes, preconditioners, etc. Note that you can extract the type of continuation fromiter(for exampleFoldCont) and thus modify the methodupdate!accordingly.
Missing docstring for BifurcationKit.DAEMassBifProblem. Check Documenter's build log for details.
Missing docstring for BifurcationKit.IdentityOperator. Check Documenter's build log for details.
BifurcationKit.DeflationOperator — Type
struct DeflationOperator{Tp<:Real, Tdot, T<:Real, vectype, Tac} <: BifurcationKit.AbstractDeflationFactorThis 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) ⋅ Πᵢ(||u - rootᵢ||₂⁻²ᵖ + α) := F(u) ⋅ M(u)$
where $||u||₂² = dot(u, u)$. The fields of the struct DeflationOperator are as follows:
You can use a different accumulator than Πᵢ, for example mean. This is important because if you have many roots αⁿ can be smaller than machine precision. mean resolves this issue.
Internal fields
power::Real: powerp. You can use anIntfor example.dot::Any: function, this function has to be bilinear and symmetric for the linear solver to work well.α::Real: shift.roots::Vector: roots.accumulator::Any: accumulator ∈(Val(:Prod), Val(:Mean))tmp::Any: [internal] to reduce allocations during computation.autodiff::Bool: [internal] to reduce allocations during computation.δ::Real: [internal] for finite differences.
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(power::Real, α::T, roots::Vector{vectype}; autodiff = false, δ = convert(T, 1e-8), accumulator = Val(:Prod))DeflationOperator(power::Real, dot, α::Real, roots::Vector{vectype}; autodiff = false, δ = convert(VI.scalartype(roots[1]), 1e-8) , accumulator = Val(:Prod))DeflationOperator(power::Real, α::T, roots::Vector{vectype}, tmp::vectype; autodiff = false, accumulator = Val(:Prod))
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)`The option autodiff of the constructors above also applies when a custom distance is used.
Linear solvers / jacobians
When used with newton, you have access to the following linear solvers:
- custom solver
DeflatedProblemCustomLS()which requires solving two linear systemsJ⋅x = rhs. - if passed
Val(:autodiff), thenForwardDiff.jlis 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.
BifurcationKit.DeflatedProblem — Type
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.
Arguments
jactypeselects the jacobian for the newton solve. Can beVal(:autodiff),Val(:fullIterative),Val(:Custom)
Periodic orbits
BifurcationKit.Trapeze — Type
struct Trapeze{Tprob, vectype, Tls<:BifurcationKit.AbstractLinearSolver, T, Tmass, Tjac} <: BifurcationKit.AbstractFiniteDifferencesDiscretizationThis composite type implements a finite-difference discretization based on the Trapeze rule (aka Crank-Nicolson, order 2 in time) to locate periodic orbits / BVP. More details (maths, notations, linear systems) can be found here.
The scheme is as follows. We discretize the time on M slices $x_{1},\cdots,x_{M}$, each of dimension N, and one looks for the period T = x[end] such that the following Crank-Nicolson relations hold for $i = 1, \cdots, M-1$
$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,$
where we used the cyclic convention $x_{0} := x_{M-1}$ and where $h_i = s_i - s_{i-1}$ are the normalized steps of the mesh mesh ($s_0 = 0 < s_1 < \cdots < s_M = 1$). The orbit is finally closed by the periodicity condition $x_{M} - x_{1} = 0$. Here $M_a$ is a mass matrix (the identity by default, see field massmatrix) and $F$ stands for the residual of the vector field encoded in prob_vf.
The phase of the periodic orbit, which removes the indeterminacy due to the invariance of periodic orbits under time shifts, is constrained by using a section (but you could use your own)
$\sum_i\langle x_{i} - x_{\pi,i}, \phi_{i}\rangle=0.$
The pair $(\phi, x_{\pi})$ is stored in the fields ϕ and xπ: $x_\pi$ is a reference state on the orbit while $\phi$ are the (normalized) normal vectors of the section. It is updated automatically during continuation by updatesection! every update_section_every_step steps.
Internal fields
prob_vf::Any: Vector field (or bifurcation problem) whose residualFand jacobian are used to assemble the functionalG.nothingis allowed to build a bare discretization. Default: nothingϕ::Any: Normal vectorsϕof the phase constraint, of sizeN * M(see the section equation in the documentation ofTrapeze). Default: nothingxπ::Any: Reference pointxπof the phase constraint, of sizeN * M(see the section equation in the documentation ofTrapeze). Default: nothingM::Int64: Number of time slices. Default: 0mesh::BifurcationKit.TimeMesh: Mesh of (normalized) time steps, seeTimeMesh. Default: TimeMesh(M)N::Int64: Dimension of the problem in case of anAbstractVectorstate space. Default: 0linsolver::BifurcationKit.AbstractLinearSolver: Linear solver used to invert the jacobian of a single time slice, i.e. to solveJ⋅sol = rhs. Only needed in a matrix-free setting (e.g.BorderedMatrixFree()) or for the computation of the Floquet multipliers. Default: DefaultLS()ongpu::Bool: Whether the computation takes place on the gpu (Experimental). Whentrue, the functional returnsvcat(out[begin:end-1], phase_cond)which is compatible withCuArraysin the modeallowscalar(false). Default: falseisautonomous::Bool: Whether the vector field is autonomous, i.e. does not depend explicitly on time. Default: truemassmatrix::Any: Mass matrix $M_a$ of the time discretization. You can pass for example a sparse matrix. Default:nothing, i.e. the identity matrix. Default: nothingupdate_section_every_step::UInt64: Frequency at which the phase constraint is updated during continuation, seeupdatesection!. Default: 1jacobian::Any: Type of jacobian used in Newton iterations (see the# Jacobiansection in the documentation ofTrapeze). Default: Dense()
Methods
Here are some useful methods you can apply to pb::Trapeze:
length(pb)gives the numberM * Nof unknowns of the time-discretized state (without the periodT, which is stored asx[end]).get_mesh_size(pb)returns the numberMof time slices.get_state_dim(pb)returns the dimensionNof a time slice.get_times(pb)returns the normalized timessᵢat which the orbit is discretized, i.e. the cumulative sum of the mesh steps.get_time_slices(pb, x)returns the state part of the guessx(i.e.x[1:M*N], the period is dropped) reshaped as anN x Mmatrix.get_time_step(pb, i)returns thei-th normalized mesh stephᵢ.get_mass_matrix(pb)returns the mass matrix, defaulting to a sparse identity matrix if none was provided. PassingVal(true)as a second argument returns instead an identity matrix of the formI(N).hasmassmatrix(pb)returnstrueif a mass matrix was provided.getparams(pb),getlens(pb)andsetparam(pb, p)give access to the parameters of the underlying vector field.getperiod(pb, x)returns the periodT = x[end]of the guessx.getdelta(pb)returns the stepδused for finite differences.generate_solution(pb, orbit, period)generates a guess from a functiont -> orbit(t)fort ∈ [0, 2π]and a periodperiod.generate_ci_problem(pb, bifprob, sol, tspan)generates aTrapezeproblem together with a guess from anODEsolutionsol.get_periodic_orbit(pb, x, pars)computes the full periodic orbit, mainly for plotting purposes.
Constructors
The structure can be created by calling Trapeze(;kwargs...). For example, you can declare such a problem without vector field by doing
Trapeze(M = 100)A more realistic way to build the problem is to provide the bifurcation problem together with the number of time slices M (or a non-uniform mesh given by a vector of steps) and the dimension N of a time slice:
Trapeze(prob_vf, M::Int, N::Int)
Trapeze(prob_vf, ϕ, xπ, M::Int, N::Int, ls = DefaultLS(); kwargs...)In the second form, ϕ and xπ (see above) provide the initial section; they are stored into vectors of length N * M, the extra entries (if the provided vectors are shorter) being set to 0. The keyword massmatrix allows to specify a mass matrix. When the discretization is created with a vector field, the residual F of prob_vf and its jacobian are used to assemble the functional G.
Orbit guess
An orbit guess 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 generate_solution or from an ODEProblem solution using generate_ci_problem. You can evaluate the residual of the functional G on an orbit guess using po_residual(pb, orbitguess, p) and its jacobian with the methods listed in the # Functional section below.
Functional
A functional, hereby called G, encodes this problem. The following methods are available
po_residual(pb, orbitguess, p)evaluates the functionalGonorbitguesspo_residual!(pb, out, orbitguess, p)same aspo_residualbut writes the result intooutpo_jvp(pb, orbitguess, p, du)evaluates the jacobiandG(orbitguess)⋅dufunctional atorbitguessondupo_jacobian_sparse(pb, orbitguess, p)returns the sparse matrix of the jacobiandG(orbitguess)atorbitguess. It is called $A_γ$ in the docs.po_jacobian_sparse!(pb, J, orbitguess, p). Same aspo_jacobian_sparsebut overwritesJinplace. Note that the sparsity pattern must be the same independently of the values of the parameters or oforbitguess. In this case, this is significantly faster thanpo_jacobian_sparse.jacobian_cyclic_sparse(pb, orbitguess, p)returns the sparse cyclic matrix $J_c$ (see the docs) of the jacobiandG(orbitguess)atorbitguessjacobian_block_diag(pb, orbitguess, p)returns the block diagonal of the sparse matrix of the jacobiandG(orbitguess)atorbitguess, i.e. the matrices $I - (T\,h_i/2)\,J(x_i)$ associated to each slice (the last block being the identity). Its inverse is a natural block Jacobi preconditioner.
Jacobian
These methods only differ in the linear algebra used to invert the jacobian dG of the functional G (see Trapeze); the discretization is otherwise the same. The value of jacobian must belong to (BifurcationKit.Dense(), BifurcationKit.AutoDiffDense(), BifurcationKit.FullLU(), BifurcationKit.FullMatrixFree(), BifurcationKit.BorderedLU(), BifurcationKit.BorderedMatrixFree(), BifurcationKit.FullSparseInplace(), BifurcationKit.BorderedSparseInplace(), BifurcationKit.AutoDiffMF()).
- For
jacobian = FullLU(), we use the default linear solver based on a sparse matrix representation ofdG. This matrix is assembled at each Newton iteration. This is the right choice when the sparsity pattern can change. - For
jacobian = FullSparseInplace(), this is the same as forFullLU()but the sparse matrixdGis updated inplace. This method allocates much less and, in some cases, is significantly faster thanFullLU(). 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 matrixdGis dense, and it is also updated inplace. This option is useful to study ODEs of small dimension. - For
jacobian = AutoDiffDense(), the jacobian is evaluated using automatic differentiation (ForwardDiff). - For
jacobian = BorderedLU(), we take advantage of the bordered shape ofdGand invert it with a bordered linear solver based on a LU decomposition of the cyclic matrix. - For
jacobian = BorderedSparseInplace(), this is the same as forBorderedLU()but the cyclic matrixJcis updated inplace. This method allocates much less and, in some cases, is significantly faster thanBorderedLU(). 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 (given byoptions.linsolver) is used to invertdG: note that a preconditioner is very likely required here because of the cyclic shape ofdGwhich negatively affects the convergence properties of GMRES. - For
jacobian = BorderedMatrixFree(), a matrix-free linear solver is used as well but only forJc(see the docs):options.linsolveris then used to invertJc. These two matrix-free options thus expose different parts of the jacobiandGin order to apply specific preconditioners. For example, an ILU preconditioner onJccould remove the constraints indGand lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required. - For
jacobian = AutoDiffMF(), 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.
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.Collocation — Type
struct Collocation{Tprob<:Union{Nothing, BifurcationKit.AbstractBifurcationProblem}, Tjac<:BifurcationKit.AbstractJacobianType, 𝒯, vectype, ∂vectype, Tmass} <: BifurcationKit.AbstractDifferentialDiscretizationThis composite type implements an orthogonal collocation (at Gauss points) method of piecewise polynomials to locate periodic orbits / BVP. More details (maths, notations, linear systems) can be found online.
Internal fields
prob_vf::Union{Nothing, BifurcationKit.AbstractBifurcationProblem}: Bifurcation problem. Default: nothingϕ::Any: Used to set a section for the phase constraint equation. Default: nothingxπ::Any: Used in the section for the phase constraint equation. Default: nothing∂ϕ::Any: We store the derivative of ϕ, no need to recompute it each time. Default: nothingN::Int64: Dimension of the state space. Default: 0isautonomous::Bool: Whether the vector field is autonomous, i.e. does not depend explicitly on time. Default: truemassmatrix::Any: Mass matrix to handle differential-algebraic (DAE) problems. Defaults tonothingfor standard ODE problems. Default: nothingupdate_section_every_step::UInt64: Update the section everyupdate_section_every_stepstep during continuation. Default: 1jacobian::BifurcationKit.AbstractJacobianType: Describes the type of jacobian used in Newton/PALC/etc iterations. See below for more information. Default: DenseAnalytical()mesh_cache::BifurcationKit.MeshCollocationCache: Cache for collocation. See docs ofMeshCollocationCache. Default: nothingcache::BifurcationKit.POCollCache: Cache for allocation free computations. See docs ofPOCollCache. Default: nothingmeshadapt::Bool: Whether to use mesh adaptation. Default: falseverbose_mesh_adapt::Bool: Verbose mesh adaptation information. Default: falseK::Float64: Parameter for mesh adaptation, control new mesh step size. More precisely, we set max(hᵢ) / min(hᵢ) ≤ K if hᵢ denotes the time steps. Default: 100
Methods
Here are some useful methods you can apply to coll::Collocation:
length(coll)gives the total number of unknowns.size(coll)returns the triplet(N, m, Ntst).getmesh(coll)returns the mesh0 = τ₁ < ... < τₙₜₛₜ₊₁ = 1. This is useful because this mesh is bound to vary during automatic mesh adaptation.get_mesh_coll(coll)returns the (static) mesh-1 = σ₁ < ... < σₘ₊₁ = 1.get_times(coll)returns the vector of times (length1 + m * Ntst) at which the collocation is applied.generate_solution(coll, orbit, period)generates a guess from a functiont -> orbit(t)which approximates the periodic orbit.POInterpolation(coll, x)returns a function interpolating the solutionxusing a piecewise polynomial function.getperiod(coll, po, p)returns the period of the periodic orbitpo.
Orbit guess
An orbit guess 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.
Collocation is a discretization, not a functional. You can evaluate the residual G and its jacobian on an orbit guess using po_residual(coll, orbitguess, p), po_residual!(coll, out, orbitguess, p) and po_analytical_jacobian(coll, orbitguess, p).
Note that you can generate this guess from a function using generate_solution or generate_ci_problem.
Jacobian
Specify the choice of the jacobian (and linear algorithm), jacobian must belong to (BifurcationKit.AutoDiffDense(), BifurcationKit.DenseAnalytical(), BifurcationKit.FullSparse(), BifurcationKit.DenseAnalyticalInplace(), BifurcationKit.FullSparseInplace(), BifurcationKit.AutoDiffMF()).
This is used to select a way of inverting the jacobian dG of the functional G. See website for more information.
Mesh adaptation
Mesh adaptation is activated by setting meshadapt = true. It then modifies the mesh, i.e. the distribution of the Ntst intervals over [0, 1], so as to equilibrate an estimate of the discretization error along the orbit. More precisely, it is performed every update_section_every_step continuation steps after a successful Newton convergence (and not during bisection).
At each adaptation, the local error is estimated from the jump of the m-th derivative of the polynomial interpolating the orbit, which stands in for the (m + 1)-th derivative of the true solution. From this, a monitor function ϕ is built and a new mesh is computed by equipartition of ∫ϕ, i.e. the intervals are redistributed so that each of them carries the same amount of error.
The new mesh is enforced to satisfy max(hᵢ) / min(hᵢ) ≤ K, where hᵢ denotes the time steps; this bound is set through the parameter K. Set verbose_mesh_adapt = true to print information about the new mesh and the monitor function at each adaptation.
Note that mesh adaptation modifies getmesh(coll) in place. The mesh is stored in the solutions saved along the branch (see POSavedSolutionAndState), so that it can be restored, e.g. when starting a new branch from a bifurcation point.
Constructors
Collocation(Ntst::Int, m::Int; kwargs)creates an empty functional withNtstandm.
Functional
A functional, hereby called G, encodes this problem. Collocation is a discretization of G; it is wrapped into the functional PeriodicOrbit(coll). The following methods are available on this functional
residual(PeriodicOrbit(coll), orbitguess, p)evaluates the functional G onorbitguessresidual!(PeriodicOrbit(coll), out, orbitguess, p)evaluates the functional G onorbitguessjacobian(probPO, orbitguess, p)evaluates the jacobian dG of the functional G onorbitguess, whereprobPO = PeriodicOrbitFunctionalColl(coll)is the wrapped problem.
BifurcationKit.Shooting — Type
struct Shooting{Tf<:BifurcationKit.AbstractFlow, Tjac<:BifurcationKit.AbstractJacobianType, Ts, Tsection, Tpar, Tlens} <: BifurcationKit.AbstractShootingDiscretizationCreate a problem to implement the Simple / Parallel Multiple Standard Shooting method to locate periodic orbits / BVP. More details (maths, notations, linear systems) can be found here. The arguments are as described below.
A functional, hereby called G, encodes the shooting problem. For example, the following methods are available:
po_residual(pb, orbitguess, par)evaluates the functional G onorbitguesspo_jvp(pb, orbitguess, par, du)evaluates the jacobiandG(orbitguess)⋅dufunctional atorbitguessondu.po_jacobian(pb, orbitguess, par)computes the matrix of the jacobiandG(orbitguess)analytically, based on monodromy matrices. Useful mainly for ODEs.po_jacobian!(pb, J, orbitguess, par)same as above but overwritesJinplace.
You can then call po_residual(pb, orbitguess, par) to apply the functional to a guess. Note that you can generate this guess from a function solution using generate_solution or generate_ci_problem.
Allowed types
orbitguess::AbstractVectormust be of sizeM * N + 1where N is the number of unknowns of the state space andorbitguess[M * N + 1]is an estimate of the periodTof the limit cycle. This form of guess is convenient for the use of the linear solvers inIterativeSolvers.jl(for example) which only acceptAbstractVectors.orbitguess::BorderedArray(guess, T)whereguess[i]is the state of the orbit at theith time slice. This last form allows for non-vector state space which can be convenient for 2d problems for example, useGMRESKrylovKitfor the linear solver in this case.
Internal fields
M::Int64:ds: vector of time differences for each shooting. Its length is writtenM. IfM == 1, then the simple shooting is implemented and the multiple one otherwise. Default: 0flow::BifurcationKit.AbstractFlow:flow::Flow: implements the flow of the Cauchy problem though the structureFlow. Default: Flow()ds::Any:ds: vector of the time differences for each shooting, of lengthM. Defaults to a uniform partition of[0, 1]. Default: diff(LinRange(0, 1, M + 1))section::Any:section: implements a phase condition. The evaluationsection(x, T)must return a scalar number wherexis a guess for one point on the periodic orbit andTis the period of the guess. Also, the methodsection(x, T, dx, dT)must be available and must return the differential ofsection. The type ofxdepends on what is passed to the newton solver. SeeSectionSSfor a type of section defined as a hyperplane. Default: nothingparallel::Bool:parallelwhether the shooting is computed in parallel (threading). Available through the use of Flows defined byEnsembleProblem(this is automatically set up for you). Default: falsepar::Any:parparameters of the model Default: nothinglens::Any:lensparameter axis. Default: nothingupdate_section_every_step::UInt64: updates the section everyupdate_section_every_stepstep during continuation Default: 1jacobian::BifurcationKit.AbstractJacobianType: Describes the type of jacobian used in Newton iterations (see below). Default: AutoDiffDense()
Methods
Here are some useful methods you can apply to pb::Shooting:
get_mesh_size(pb)returns the numberMof time slices.get_time_slices(pb, x)returns the time slices, either as anN x Mmatrix or as aBorderedArray.getparams(pb),getlens(pb)andsetparam(pb, p)give access to the parameters of the model.isparallel(pb)returnstrueif the multiple trajectories are simulated in parallel (threading).generate_solution(pb, orbit, period)generates a guess from a functiont -> orbit(t).POInterpolation(pb, x)returns a function interpolating the periodic orbitx.get_periodic_orbit(pb, x, pars)computes the full periodic orbit, mainly for plotting purposes.
Jacobian
jacobian Specify the choice of the linear algorithm, which must belong to (BifurcationKit.AutoDiffMF(), BifurcationKit.MatrixFree(), BifurcationKit.AutoDiffDense(), BifurcationKit.AutoDiffDenseAnalytical(), BifurcationKit.FiniteDifferences(), BifurcationKit.FiniteDifferencesMF()). This is used to select a way of inverting the jacobian dG
1. 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
2. For `AutoDiffMF()`, we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of `x -> prob(x, p)` using a directional derivative, also called JVP product. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
3. 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.
4. 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.
5. For `AutoDiffDenseAnalytical()`. Same as for `AutoDiffDense` but the jacobian is formed using a mix of AD and analytical formula.
6. 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 = Shooting(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)- A convenient way to build the functional is to use:
pb = Shooting(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)::Numberfor the phase:
pb = Shooting(prob::Union{ODEProblem, EnsembleProblem}, alg, M::Int, section; parallel = false, kwargs...)or
pb = Shooting(prob::Union{ODEProblem, EnsembleProblem}, alg, ds, section; parallel = false, kwargs...)- The next way is an elaboration of the previous one
pb = Shooting(prob1::Union{ODEProblem, EnsembleProblem}, alg1, prob2::Union{ODEProblem, EnsembleProblem}, alg2, M::Int, section; parallel = false, kwargs...)or
pb = Shooting(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.PoincareShooting — Type
struct PoincareShooting{Tf, Tjac<:BifurcationKit.AbstractJacobianType, Tsection<:SectionPS, Tpar, Tlens} <: BifurcationKit.AbstractPoincareShootingDiscretizationThis composite type implements the Poincaré Shooting method to locate periodic orbits / BVP by relying on Poincaré return maps. More details (maths, notations, linear systems) can be found here. The arguments are as described below.
Internal fields
M::Int64:M: the number of Poincaré sections. IfM == 1, then the simple shooting is implemented and the multiple one otherwise. Default: 0flow::Any:flow::Flow: implements the flow of the Cauchy problem though the structureFlow. Default: Flow()section::SectionPS:sections: function or callable struct which implements a Poincaré section condition. The evaluationsections(x)must return a scalar number whenM == 1. Otherwise, one must implement a functionsection(out, x)which populatesoutwith theMsections. SeeSectionPSfor type of section defined as a hyperplane. Default: SectionPS(M)δ::Float64:δ = 1e-8used to compute the jacobian of the functional by finite differences. Default: 1.0e-8parallel::Bool:parallel = falsewhether the shooting are computed in parallel (threading). Only available through the use of Flows defined byEnsembleProblem. Default: falsepar::Any:parparameters of the model Default: nothinglens::Any:lensparameter axis Default: nothingupdate_section_every_step::UInt64:update_section_every_stepupdates the section everyupdate_section_every_stepstep during continuation Default: 1jacobian::BifurcationKit.AbstractJacobianType: Describes the type of jacobian used in Newton iterations (see below). Default: AutoDiffDenseAnalytical()
Jacobian
jacobian Specify the choice of the linear algorithm, which must belong to (BifurcationKit.AutoDiffMF(), BifurcationKit.MatrixFree(), BifurcationKit.AutoDiffDense(), BifurcationKit.AutoDiffDenseAnalytical(), BifurcationKit.FiniteDifferences(), BifurcationKit.FiniteDifferencesMF()). This is used to select a way of inverting the jacobian dG
1. 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
2. For `AutoDiffMF()`, we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of `x -> prob(x, p)` using a directional derivative, also called JVP product. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
3. 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.
4. 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.
5. For `AutoDiffDenseAnalytical()`. Same as for `AutoDiffDense` but the jacobian is formed using a mix of AD and analytical formula.
6. 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 = PoincareShooting(M::Int, prob::Union{ODEProblem, EnsembleProblem}, alg; kwargs...)
A convenient way is to create a functional is
pb = PoincareShooting(prob::ODEProblem, alg, section; kwargs...)
for simple shooting or
pb = PoincareShooting(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 = PoincareShooting(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 po_residual(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 in the state space and M is the number of Poincaré maps (the coordinates are the projections on the Poincaré sections, hence the - 1). 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.
po_residual(pb, orbitguess, par)evaluates the functional G onorbitguesspo_jvp(pb, orbitguess, par, du)evaluates the jacobiandG(orbitguess).dufunctional atorbitguessondupo_jacobian(pb, orbitguess, par)computes the matrix of the jacobiandG(orbitguess)analytically, based on monodromy matrices. Useful mainly for ODEs.po_jacobian!(pb, J, orbitguess, par)same as above but overwritesJinplace.
Waves
BifurcationKit.TWModel — Type
struct TWModel{Tprob, Tu0, TDu0, TD, Tj} <: BifurcationKit.AbstractTravelingWaveDiscretizationThis composite type implements a functional for freezing symmetries in order, for example, to compute traveling waves (TW). Note that you can freeze many symmetries, not just one, by passing many Lie generators. TWModel is a discretization: the residual of the frozen system is obtained by wrapping pb into a TravellingWave functional, residual(TravellingWave(pb), x, par), which computes:
┌ ┐
│ f(x, par) - s⋅∂⋅x │
│ <x - u₀, ∂⋅u₀> │
└ ┘Arguments
probbifurcation problem with continuous symmetries∂::Tupletuple of Lie generators. In effect, each of these is an (differential) operator which can be specified as a (sparse) matrix or as an operator implementingLinearAlgebra.mul!.u₀reference solution
Additional Constructor(s)
pb = TWModel(prob, ∂, u₀; kw...)This simplified call handles the case where a single symmetry needs to be frozen.
Useful function
updatesection!(pb::TWModel, u0)updates the reference solution of the problem usingu0.nb_constraints(::TWModel)number of constraints (or Lie generators)
Internal fields
prob_vf::Any: vector field, must beAbstractBifurcationProblem.∂::Any: Infinitesimal generator of symmetries, differential operator.u₀::Any: reference solution, we only need one!∂u₀::Any: Default: (∂ * u₀,)DAE::Int64: Default: 0nc::Int64: [Internal] number of constraints Default: 1jacobian::Any: Default: AutoDiff()
BifurcationKit.EigenWave — Type
Basic eigen solver to compute the stability of the wave based on the eigenvalues of `J + η * ∂`.BifurcationKit.GEigenWave — Type
Eigen solver to compute the stability of the wave based on the eigenvalues of the GEV, see [documentation](https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/intro_wave/#Wave-stability).BifurcationKit.continuation — Method
Specific continuation routine for wave problems.
Arguments
Linear solvers
BifurcationKit.DefaultLS — Type
struct DefaultLS <: BifurcationKit.AbstractDirectLinearSolverThis struct is used to provide the backslash operator `. Can be used to solveJ * x = rhs`.
J can be an AbstractMatrix, a linear operator or a ShiftedOperator (possibly wrapping a MassAndJacobian) to solve shifted systems.
Internal fields
useFactorization::Bool: Whether to catch a factorization for multiple solves. Some operators may not support LU (like ApproxFun.jl) or QR factorization so it is best to let the user decides. Some matrices do not havefactorizelikeStaticArrays.MMatrix. Default: true
BifurcationKit.DefaultPILS — Type
struct DefaultPILS <: BifurcationKit.AbstractIterativeLinearSolver[Mainly for debugging] This solver is used to test Moore-Penrose continuation. It is a direct solver based on the backslash operator, used to solve J * x = rhs.
J can be an AbstractMatrix, a linear operator or a ShiftedOperator (possibly wrapping a MassAndJacobian) to solve shifted systems.
Internal fields
useFactorization::Bool: Whether to catch a factorization for multiple solves. Some operators may not support LU (like ApproxFun.jl) or QR factorization so it is best to let the user decides. Some matrices do not havefactorizelikeStaticArrays.MMatrix. Default: true
BifurcationKit.GMRESIterativeSolvers — Type
mutable struct GMRESIterativeSolvers{T, Tl, Tr} <: BifurcationKit.AbstractIterativeLinearSolverLinear solver based on gmres from IterativeSolvers.jl. Can be used to solve J * x = rhs.
J can be an AbstractMatrix, a linear operator or a ShiftedOperator (possibly wrapping a MassAndJacobian) to solve shifted systems.
The struct is mutable so that you can modify the preconditioners.
Internal fields
abstol::Any: Absolute tolerance for solver Default: 0.0reltol::Any: Relative tolerance for solver Default: 1.0e-8restart::Int64: Number of restarts Default: 200maxiter::Int64: Maximum number of iterations Default: 100N::Int64: Dimension of the problem Default: 0verbose::Bool: Display information during iterations Default: falselog::Bool: Record information Default: trueinitially_zero::Bool: Start with zero guess Default: truePl::Any: Left preconditioner Default: IterativeSolvers.Identity()Pr::Any: Right preconditioner Default: IterativeSolvers.Identity()ismutating::Bool: Whether the linear operator is written inplace Default: false
BifurcationKit.GMRESKrylovKit — Type
mutable struct GMRESKrylovKit{𝒯, 𝒯l} <: BifurcationKit.AbstractIterativeLinearSolverCreate a linear solver based on linsolve from KrylovKit.jl. Can be used to solve J * x = rhs.
J can be an AbstractMatrix, a linear operator or a ShiftedOperator (possibly wrapping a MassAndJacobian) to solve shifted systems.
The struct is mutable so that you can modify the preconditioners.
By tuning the options, you can select CG, GMRES... see here
Internal fields
dim::Int64: Krylov Dimension Default: KrylovDefaults.krylovdim[]atol::Any: Absolute tolerance for solver Default: KrylovDefaults.tol[]rtol::Any: Relative tolerance for solver Default: KrylovDefaults.tol[]maxiter::Int64: Maximum number of iterations Default: KrylovDefaults.maxiter[]verbose::Int64: Verbosity ∈ {0,1,2} Default: 0issymmetric::Bool: If the linear map is symmetric, only meaningful if T<:Real Default: falseishermitian::Bool: If the linear map is hermitian Default: falseisposdef::Bool: If the linear map is positive definite Default: falsePl::Any: Left preconditioner Default: nothing
BifurcationKit.KrylovLS — Type
mutable struct KrylovLS{K, 𝒯l, 𝒯r} <: BifurcationKit.AbstractIterativeLinearSolverCreate a linear solver based on Krylov.jl. Can be used to solve J * x = rhs. You have access to cg, cr, gmres, symmlq, cg_lanczos, cg_lanczos_shift_seq...
J can be an AbstractMatrix, a linear operator or a ShiftedOperator (possibly wrapping a MassAndJacobian) to solve shifted systems.
The struct is mutable so that you can modify the preconditioners.
Example
You can create a Krylov solver with the following code:
KrylovLS(atol = 1e-11, rtol = 1e-8)
Other methods
Look at KrylovLSInplace for a method where the Krylov space is kept in memory
Internal fields
KrylovAlg::Symbol: Krylov methodkwargs::Any: Arguments passed to the linear solverPl::Any: Left preconditionerPr::Any: Right preconditioner
BifurcationKit.KrylovLSInplace — Type
mutable struct KrylovLSInplace{F, K, 𝒯l, 𝒯r} <: BifurcationKit.AbstractIterativeLinearSolverCreate an inplace linear solver based on Krylov.jl. Can be used to solve J * x = rhs.
J can be an AbstractMatrix, a linear operator or a ShiftedOperator (possibly wrapping a MassAndJacobian) to solve shifted systems.
The Krylov space is pre-allocated. This is really great for GPU but also for CPU.
The struct is mutable so that you can modify the preconditioners.
Internal fields
workspace::Any: Can be Krylov.GmresWorkspace for example.KrylovAlg::Symbol: Krylov method.kwargs::Any: Arguments passed to the linear solver.Pl::Any: Left preconditioner.Pr::Any: Right preconditioner.is_inplace::Bool: Is the linear mapping inplace.
Eigen solvers
BifurcationKit.DefaultEig — Type
struct DefaultEig{T} <: BifurcationKit.AbstractDirectEigenSolverThe struct DefaultEig is used to provide the eigen method to BifurcationKit.
Internal fields
which::Any: How do we sort the computed eigenvalues. Default: real
Constructors
Just pass the above fields like DefaultEig(; which = abs)
BifurcationKit.EigArpack — Type
struct EigArpack{T, Tby, Tw} <: BifurcationKit.AbstractIterativeEigenSolverCreate an eigen solver based on Arpack.jl.
Internal fields
sigma::Any: Shift for Shift-Invert method with `(J - sigma⋅I)which::Symbol: Which eigen-element to extract :LR, :LM, ...by::Any: Sorting function, default to realkwargs::Any: Keyword arguments passed to EigArpack
Constructor
EigArpack(sigma = nothing, which = :LR; kwargs...)
More information is available at Arpack.jl. You can pass the following parameters tol = 0.0, maxiter = 300, ritzvec = true, v0 = zeros((0,)).
BifurcationKit.EigKrylovKit — Type
struct EigKrylovKit{T, vectype} <: BifurcationKit.AbstractMFEigenSolverCreate an eigen solver based on KrylovKit.jl.
Internal fields
dim::Int64: Krylov Dimension Default: KrylovDefaults.krylovdim[]tol::Any: Tolerance Default: 0.0001restart::Int64: Number of restarts Default: 200maxiter::Int64: Maximum number of iterations Default: KrylovDefaults.maxiter[]verbose::Int64: Verbosity ∈ {0, 1, 2} Default: 0which::Symbol: Which eigenvalues are looked for :LR (largest real), :LM, ... Default: :LRissymmetric::Bool: If the linear map is symmetric, only meaningful if T<:Real Default: falseishermitian::Bool: If the linear map is hermitian Default: falsex₀::Any: Example of vector to usen for Krylov iterations Default: nothing
Constructors
Just pass the above fields like EigKrylovKit(;dim=2)
BifurcationKit.EigArnoldiMethod — Type
struct EigArnoldiMethod{T, Tby, Tw, Tkw, vectype} <: BifurcationKit.AbstractIterativeEigenSolverInternal fields
sigma::Any: Shift for Shift-Invert method.which::Any: Which eigen-element to extract LR(), LM(), ...by::Any: How do we sort the computed eigenvalues, defaults to real.kwargs::Any: Keyword arguments passed toArnoldiMethod.partialschur.x₀::Any: Example of vector used for Krylov iterations.
More information is available at ArnoldiMethod.jl. For example, you can pass the parameters tol, mindim, maxdim, restarts.
Constructor
EigArnoldiMethod(;sigma = nothing, which = ArnoldiMethod.LR(), x₀ = nothing, kwargs...)
BifurcationKit.ShiftInvert — Type
struct ShiftInvert{T, Tls<:BifurcationKit.AbstractLinearSolver, Teig<:AbstractEigenSolver} <: AbstractEigenSolverCreate an eigensolver based on Shift-Invert strategy. Basically, one computes the eigen-elements of (J - σ⋅I)⁻¹.
Internal fields
sigma::Any: Shift.ls::BifurcationKit.AbstractLinearSolver: Linear solver to compute (J - σ⋅I)⁻¹.eig::AbstractEigenSolver: Eigen-solver to compute the eigenvalues of (J - σ⋅I)⁻¹.
BifurcationKit.EigenMassMatrix — Type
struct EigenMassMatrix{Tb, Teig<:AbstractEigenSolver} <: AbstractEigenSolverCreate an eigensolver for DAE, Basically a GEV with mass matrix.
Internal fields
B::Any: Mass matrixeig::AbstractEigenSolver: Eigen-solver
Missing docstring for BifurcationKit.EigenDAE. Check Documenter's build log for details.
Generalized Eigen solvers
BifurcationKit.gev — Function
gev(l, A, B, nev; kwargs...)Solve the generalized eigenvalue problem $A x = \lambda B x$ using l.
Arguments
l::AbstractEigenSolver: the eigensolver configuration (controls sorting vial.which).A,B: the matrix (or operators) pair defining $A x = \lambda B x$.nev: number of requested eigenvalues.
BifurcationKit.DefaultGEig — Type
Generalized eigen solver based on LinearAlgebra.eigen.
BifurcationKit.GEigArpack — Type
struct GEigArpack{T, Tb} <: BifurcationKit.AbstractGEigenSolverInternal fields
eigensolver::Any: Arpack eigensolver.B::Any: Mass matrix
More information is available at Arpack.jl. You can pass the following parameters tol=0.0, maxiter=300, ritzvec=true, v0=zeros((0,)).
Constructor
GEigArpack(; kw...) where the keyword arguments are forwarded to the inner EigArpack.
BifurcationKit.GEigKrylovKit — Type
struct GEigKrylovKit{T, Tb} <: BifurcationKit.AbstractMFGEigenSolverCreate an generalised eigen solver based on KrylovKit.jl.
Internal fields
eigensolver::Any: KryloKit eigensolver.B::Any: Mass matrix / operator.
BifurcationKit.GEigArnoldiMethod — Type
struct GEigArnoldiMethod{T, Tb} <: BifurcationKit.AbstractMFGEigenSolverCreate an generalised eigen solver based on ArnoldiMethod.jl.
Internal fields
eigensolver::Any: Eigensolver.B::Any: Mass matrix / operator.
Floquet solvers
BifurcationKit.FloquetQaD — Type
struct FloquetQaD{E<:AbstractEigenSolver} <: BifurcationKit.AbstractFloquetSolverComputes Floquet multipliers (eigenvalues of the monodromy matrix) for periodic orbit problems using the Shooting method or Finite Differences (Trapeze method).
Method Description
The "Quick and Dirty" (QaD) method computes Floquet multipliers through sequential matrix products along the periodic orbit. This approach has numerical limitation:
- Precision issues: Accuracy degrades for large or small Floquet exponents when using many time sections, due to accumulated errors from repeated matrix multiplications.
Despite precision limitations, the method is sufficient for bifurcation detection in most cases.
Internal fields
eigsolver::AbstractEigenSolver: eigensolver used to compute the eigenvalues of the monodromy matrix.matrix_free::Bool: whether to use a matrix-free linear operator (automatic wheneigsolveris not a direct solver).
Implementation Details
- If
eigsolver == DefaultEig(), the full monodromy matrix is explicitly formed and its eigenvalues are computed - Otherwise, a matrix-free formulation is used, applying the monodromy operator via sequential time evolution
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 eigsolver needs to compute the eigenvalues with largest modulus (and not the ones 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 BifurcationKit, the proper option is properly set.
Collocation
BifurcationKit.FloquetGEV — Type
struct FloquetGEV{E<:AbstractEigenSolver, Tb} <: BifurcationKit.AbstractFloquetSolverComputes Floquet exponents for periodic orbits using a Generalized Eigenvalue Problem (GEV) formulation.
Method Description
This method reformulates the Floquet multiplier computation as a large-dimensional generalized eigenvalue problem. The approach is based on a simplified version of the algorithm described in [1].
Performance characteristics:
- Accuracy: More numerically precise than
FloquetQaD, especially for extreme Floquet exponents. - Speed: Slower due to the large dimension of the eigenvalue problem.
- Recommendation: Use
FloquetColl()when possible for better performance with similar accuracy.
Fields
eigsolver::AbstractEigenSolver: Eigensolver used to solve the generalized eigenvalue problem.B::Tb: Mass matrix for the generalized eigenvalue formulation.
Constructor
FloquetGEV(eigls::AbstractEigenSolver, ntot::Int, n::Int; array_zeros = zeros)Arguments:
eigls: Eigensolver to use.ntot: Total dimension of the generalized eigenvalue problem.n: State space dimension.array_zeros: Function to allocate zero arrays: defaults tozerosbutspzeroscan be passed for sparse matrices.
Example
# For a 2D system with 30 time sections and 4 collocation points:eigfloquet = FloquetGEV(DefaultEig(), (30 * 4 + 1) * 2, 2)References
[1] 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.
BifurcationKit.FloquetColl — Type
struct FloquetColl{E<:AbstractEigenSolver, C} <: BifurcationKit.AbstractFloquetSolverComputes Floquet exponents for periodic orbits discretized with the orthogonal collocation method.
Method Description
This method uses the condensation of parameters technique, originally described in [1] and implemented in AUTO07p, with improvements from [2,3]. The approach efficiently computes Floquet multipliers by exploiting the structure of the collocation discretization.
Performance characteristics:
- Accuracy: High precision, comparable to
FloquetGEV. - Speed: Faster than
FloquetGEVby exploiting collocation structure. - Recommendation: Preferred method for collocation-based periodic orbit problems.
Fields
eigsolver::AbstractEigenSolver: Which eigen solver. Defaults toDefaultEig.cache::Any: Cache, defaults tonothing. It should be set toCOPCACHE. When used withCOPBLS, it is automatically set up.small_n::Bool: Whether to use optimized COP to compute the Floquet exponents. Note that this does not work well for sparse matrices. Defaults totrue.
Constructor
FloquetColl(; eigls::AbstractEigenSolver = DefaultEig(), cache = nothing, small_n = true)Keyword Arguments:
eigls: Eigensolver to use (defaults toDefaultEig())cache: Optional cache for optimization (set toCOPCACHE; automatically configured when usingCOPBLS)small_n: Whether to use optimized algorithm for small state dimensions (defaults totrue)
References
[1] Doedel, Eusebius, Herbert B. Keller, et Jean Pierre Kernevez. «Numerical analysis and control of bifurcation problems (ii): bifurcation in infinite dimensions». International Journal of Bifurcation and Chaos 01, nᵒ 04 (décembre 1991): 745‑72. https://doi.org/10.1142/S0218127491000555.
[2] Lust, Kurt. «Improved Numerical Floquet Multipliers». International Journal of Bifurcation and Chaos 11, nᵒ 09 (septembre 2001): 2389‑2410. https://doi.org/10.1142/S0218127401003486.
[3] 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.
Bordered linear solvers
BifurcationKit.MatrixBLS — Type
struct MatrixBLS{S<:Union{Nothing, BifurcationKit.AbstractLinearSolver}} <: BifurcationKit.AbstractBorderedLinearSolverThis struct is used to provide the bordered linear solver based on inverting the full matrix.
Internal fields
solver::Union{Nothing, BifurcationKit.AbstractLinearSolver}: Linear solver used to invert the full matrix.
BifurcationKit.BorderingBLS — Type
struct BorderingBLS{S<:Union{Nothing, BifurcationKit.AbstractLinearSolver}, Ttol<:Real, Tdot, Tnorm} <: BifurcationKit.AbstractBorderedLinearSolverThis struct is used to provide the bordered linear solver based on the Bordering method. Using the options, you can trigger a sequence of Bordering reductions to meet a given precision.
Internal fields
solver::Union{Nothing, BifurcationKit.AbstractLinearSolver}: Linear solver for the Bordering method. Default: nothingtol::Real: Tolerance for checking precision. Default: 1.0e-12check_precision::Bool: Check precision of the linear solve? Default: truek::Int64: Number of recursions to achieve tolerance. Default: 1dot::Any: Inner product used by the solver. Default: VI.innernorm::Any: Norm used by the solver. Default: VI.norm
Constructors
- there is a simple constructor
BorderingBLS(ls)wherelsis a linear solver, for examplels = DefaultLS() - you can pass keyword arguments to create the solver, for example
BorderingBLS(solver = DefaultLS(), tol = 1e-4)
Reference(s)
This is the solver BEC + k in:
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.
BifurcationKit.MatrixFreeBLS — Type
struct MatrixFreeBLS{S<:Union{Nothing, BifurcationKit.AbstractLinearSolver}} <: BifurcationKit.AbstractBorderedLinearSolverThis struct is used to provide a bordered linear solver based on a matrix free operator for the full system in (x, p).
Constructor
MatrixFreeBLS(solver, ::Bool)Internal fields
solver::Union{Nothing, BifurcationKit.AbstractLinearSolver}: Linear solver for solving the extended linear system.use_bordered_array::Bool: Structure used to hold(x, p). Iftrue, this is achieved usingBorderedArray. Iffalse, aVectoris used which is analogous tovcat(x, p).
BifurcationKit.MatrixFreeBLSmap — Type
struct MatrixFreeBLSmap{Tj, Ta, Tb, Tc, Td}Composite type to save the bordered linear system with expression
┌ ┐ │ J a │ │ b' c │ └ ┘
It then solved using Matrix Free algorithm applied to the full operator and not just J as for MatrixFreeBLS
BifurcationKit.LSFromBLS — Type
struct LSFromBLS{Ts} <: BifurcationKit.AbstractLinearSolverThis structure is used to provide the following linear solver. To solve (1) J⋅x = rhs, one decomposes J using Matrix by blocks and then use a bordering strategy to solve (1).
It is interesting for solving the linear system associated with Collocation / Trapeze functionals, for example using
BorderingBLS(solver = BK.LSFromBLS(), tol = 1e-9, k = 2, check_precision = true)
Internal fields
solver::Any: Linear solver used to solve the smaller linear systems.
Nonlinear solver
BifurcationKit.solve — Function
solve(prob::AbstractBifurcationProblem, ::Newton, 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. 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 (the update then reads $x \leftarrow x - u$). 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 information.
Arguments
proba::AbstractBifurcationProblem, typically aBifurcationProblemwhich holds the vector field and its jacobian. We also refer toBifFunctionfor more details.options::NewtonParvariable holding the internal parameters used by thenewtonmethod
Optional Arguments
normN = normspecifies a norm for the convergence criteriacallbackfunction passed by the user which is called at the end of each iteration. The default one is the followingcb_default((x, fx, J, residual, step, itlinear, options, x0, residuals); k...) = true. Can be used to update a preconditioner for example. You can use for examplecbMaxNormto limit the residuals norms. If yo want to specify your own, the arguments passed to the callback are as followsxcurrent solutionfxcurrent residualJcurrent jacobianresidualcurrent norm of the residualstepcurrent newton stepitlinearnumber of iterations to solve the linear systemoptionsa copy of the argumentoptionspassed tonewtonresidualsthe history of residualskwargskwargs arguments, contain your initial guessx0
callback = (state;k...) -> state.residual<1for example.kwargsarguments passed to the callback. Useful whennewtonis called fromcontinuation
Output:
solution::NonLinearSolution, we refer toNonLinearSolutionfor more information.
solve(
prob::BifurcationKit.AbstractBifurcationProblem,
defOp::DeflationOperator{Tp, Tdot, T, vectype},
options::NewtonPar{T, L, E};
...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(DeflatedProblem{Tprob, _A, _B, _C, _D, Val{:Custom}} where {Tprob<:BifurcationKit.AbstractBifurcationProblem, _A, _B, _C, _D}), Tres<:(Vector)}
solve(
prob::BifurcationKit.AbstractBifurcationProblem,
defOp::DeflationOperator{Tp, Tdot, T, vectype},
options::NewtonPar{T, L, E},
_linsolver::BifurcationKit.DeflatedProblemCustomLS;
kwargs...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(DeflatedProblem{Tprob, _A, _B, _C, _D, Val{:Custom}} where {Tprob<:BifurcationKit.AbstractBifurcationProblem, _A, _B, _C, _D}), Tres<:(Vector)}
This is the deflated version of the Krylov-Newton Solver for F(x, p0) = 0.
We refer to the regular solve for more information. It penalises the roots saved in defOp.roots. The other arguments are as for solve. See DeflationOperator for more information on defOp.
Arguments
Compared to solve, the only different arguments are
defOp::DeflationOperatordeflation operatorlinsolverlinear solver used to invert the Jacobian of the deflated functional.- custom solver
DeflatedProblemCustomLS()which requires solving two linear systemsJ⋅x = rhs. - For other linear solvers
<: AbstractLinearSolver, a matrix free method is used for the deflated functional. - if passed
Val(:autodiff), thenForwardDiff.jlis 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.
- custom solver
BifurcationKit.newton — Function
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.
Arguments
Compared to newton, the only different arguments are
defOp::DeflationOperatordeflation operatorlinsolverlinear solver used to invert the Jacobian of the deflated functional.- custom solver
DeflatedProblemCustomLS()which requires solving two linear systemsJ⋅x = rhs. - For other linear solvers
<: AbstractLinearSolver, a matrix free method is used for the deflated functional. - if passed
Val(:autodiff), thenForwardDiff.jlis 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.
- custom solver
newton(
br::BifurcationKit.AbstractBranchResult,
ind_bif::Int64;
normN,
options,
start_with_eigen,
lens2,
kwargs...
) -> Any
This function turns an initial guess for a Fold / Hopf point into a solution to the Fold / Hopf problem based on a Minimally Augmented formulation.
Arguments
brresults returned after a call to continuationind_bifbifurcation index inbr
Optional arguments:
options::NewtonPar, default valuebr.contparams.newton_optionsnormN = normoptionsYou can pass newton parameters different from the ones stored inbrby using this argumentoptions.bdlinsolverbordered linear solver for the constraint equationstart_with_eigen = falsewhether to start the Minimally Augmented problem with information from eigen elements.kwargskeywords arguments to be passed to the regular Newton-Krylov solver
newton(
disc::BifurcationKit.AbstractShootingDiscretization,
orbitguess,
options::NewtonPar;
lens,
δ,
kwargs...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(BifurcationKit.PeriodicOrbitFunctionalSh{Tdisc, _A, _B, Nothing, Nothing} where {Tdisc<:BifurcationKit.AbstractShootingDiscretization, _A, _B}), Tres<:(Vector)}
This 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.
Arguments
Similar to newton except that prob is either a Shooting or a PoincareShooting. These two problems have specific options to be tuned, we refer to their link for more information and to the tutorials.
disca problem of type<: AbstractShootingDiscretizationencoding the shooting functional G.orbitguessa guess for the periodic orbit. SeeShootingand SeePoincareShootingfor information regarding the shape oforbitguess.optionssame as for the regularnewtonmethod.
Optional argument
jacobian Specify the choice of the linear algorithm, which must belong to (BifurcationKit.AutoDiffMF(), BifurcationKit.MatrixFree(), BifurcationKit.AutoDiffDense(), BifurcationKit.AutoDiffDenseAnalytical(), BifurcationKit.FiniteDifferences(), BifurcationKit.FiniteDifferencesMF()). This is used to select a way of inverting the jacobian dG
1. 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
2. For `AutoDiffMF()`, we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of `x -> prob(x, p)` using a directional derivative, also called JVP product. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
3. 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.
4. 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.
5. For `AutoDiffDenseAnalytical()`. Same as for `AutoDiffDense` but the jacobian is formed using a mix of AD and analytical formula.
6. 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.newton(
disc::BifurcationKit.AbstractShootingDiscretization,
orbitguess,
defOp::DeflationOperator{Tp, Tdot, T, vectype},
options::NewtonPar{T, S, E};
lens,
kwargs...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(DeflatedProblem{Tprob, _A, _B, _C, _D, Val{:Custom}} where {Tprob<:(BifurcationKit.PeriodicOrbitFunctionalSh{Tdisc, _A, _B, Nothing, Nothing} where {Tdisc<:BifurcationKit.AbstractShootingDiscretization, _A, _B}), _A, _B, _C, _D}), Tres<:(Vector)}
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 Shooting or a PoincareShooting.
Optional argument
jacobian Specify the choice of the linear algorithm, which must belong to (BifurcationKit.AutoDiffMF(), BifurcationKit.MatrixFree(), BifurcationKit.AutoDiffDense(), BifurcationKit.AutoDiffDenseAnalytical(), BifurcationKit.FiniteDifferences(), BifurcationKit.FiniteDifferencesMF()). This is used to select a way of inverting the jacobian dG
1. 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
2. For `AutoDiffMF()`, we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of `x -> prob(x, p)` using a directional derivative, also called JVP product. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
3. 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.
4. 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.
5. For `AutoDiffDenseAnalytical()`. Same as for `AutoDiffDense` but the jacobian is formed using a mix of AD and analytical formula.
6. 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:
- solution::NonLinearSolution, see
NonLinearSolution
newton(
trap::Trapeze,
orbitguess,
options::NewtonPar;
kwargs...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(BifurcationKit.PeriodicOrbitFunctionalTrap{Tdisc, _A, _B, Nothing, Nothing} where {Tdisc<:Trapeze, _A, _B}), Tres<:(Vector)}
Locate a periodic orbit with a Newton solver applied to the finite-difference functional G of the Trapeze discretization, i.e. solve $G(u) = 0$. The returned solution has u[end] = T equal to the period of the orbit.
Arguments:
trapa problem of typeTrapezeencoding the functionalG; itsjacobianfield selects the linear algebra used, see below.orbitguessa guess for the periodic orbit. SeeTrapezefor more details.optionssame as for the regularnewtonmethod.
These methods only differ in the linear algebra used to invert the jacobian dG of the functional G (see Trapeze); the discretization is otherwise the same. The value of jacobian must belong to (BifurcationKit.Dense(), BifurcationKit.AutoDiffDense(), BifurcationKit.FullLU(), BifurcationKit.FullMatrixFree(), BifurcationKit.BorderedLU(), BifurcationKit.BorderedMatrixFree(), BifurcationKit.FullSparseInplace(), BifurcationKit.BorderedSparseInplace(), BifurcationKit.AutoDiffMF()).
- For
jacobian = FullLU(), we use the default linear solver based on a sparse matrix representation ofdG. This matrix is assembled at each Newton iteration. This is the right choice when the sparsity pattern can change. - For
jacobian = FullSparseInplace(), this is the same as forFullLU()but the sparse matrixdGis updated inplace. This method allocates much less and, in some cases, is significantly faster thanFullLU(). 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 matrixdGis dense, and it is also updated inplace. This option is useful to study ODEs of small dimension. - For
jacobian = AutoDiffDense(), the jacobian is evaluated using automatic differentiation (ForwardDiff). - For
jacobian = BorderedLU(), we take advantage of the bordered shape ofdGand invert it with a bordered linear solver based on a LU decomposition of the cyclic matrix. - For
jacobian = BorderedSparseInplace(), this is the same as forBorderedLU()but the cyclic matrixJcis updated inplace. This method allocates much less and, in some cases, is significantly faster thanBorderedLU(). 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 (given byoptions.linsolver) is used to invertdG: note that a preconditioner is very likely required here because of the cyclic shape ofdGwhich negatively affects the convergence properties of GMRES. - For
jacobian = BorderedMatrixFree(), a matrix-free linear solver is used as well but only forJc(see the docs):options.linsolveris then used to invertJc. These two matrix-free options thus expose different parts of the jacobiandGin order to apply specific preconditioners. For example, an ILU preconditioner onJccould remove the constraints indGand lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required. - For
jacobian = AutoDiffMF(), 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(
trap::Trapeze,
orbitguess,
defOp::DeflationOperator{Tp, Tdot, T, vectype},
options::NewtonPar;
kwargs...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(DeflatedProblem{Tprob, Tp, _A, T, _B, Val{:Custom}} where {Tprob<:(BifurcationKit.PeriodicOrbitFunctionalTrap{Tdisc, _A, _B, Nothing, Nothing} where {Tdisc<:Trapeze, _A, _B}), Tp<:Real, _A, T<:Real, _B}), Tres<:(Vector)}
This function is similar to newton 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 algorithm from converging to the equilibrium point.
newton(
coll::Collocation,
orbitguess,
options::NewtonPar;
kwargs...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(BifurcationKit.PeriodicOrbitFunctionalColl{Tdisc, _A, _B, Nothing, Nothing} where {Tdisc<:Collocation, _A, _B}), Tres<:(Vector)}
This is the Newton solver for computing a periodic orbit using orthogonal collocation method. Note that the linear solver has to be appropriately set up in options.
Arguments
Similar to newton except that coll is a Collocation.
colla discretization of type<: Collocationencoding the collocation functional G.orbitguessa guess for the periodic orbit.optionssame as for the regularnewtonmethod.
Optional argument
jacobianSpecify the choice of the linear algorithm, which must belong to(BifurcationKit.AutoDiffDense(), BifurcationKit.DenseAnalytical(), BifurcationKit.FullSparse(), BifurcationKit.DenseAnalyticalInplace(), BifurcationKit.FullSparseInplace(), BifurcationKit.AutoDiffMF()). 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 usingoptions. The jacobian is formed inplace. - For
DenseAnalytical()Same as forAutoDiffDensebut the jacobian is formed using a mix of AD and analytical formula.
- For
newton(
coll::Collocation,
orbitguess,
defOp::DeflationOperator,
options::NewtonPar;
kwargs...
) -> NonLinearSolution{_A, Tprob, Tres} where {_A, Tprob<:(DeflatedProblem{Tprob, Tp, _A, T, _B, Val{:Custom}} where {Tprob<:(BifurcationKit.PeriodicOrbitFunctionalColl{Tdisc, _A, _B, Nothing, Nothing} where {Tdisc<:Collocation, _A, _B}), Tp<:Real, _A, T<:Real, _B}), Tres<:(Vector)}
This function is similar to newton(::Collocation, orbitguess, options; 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.DotTheta — Type
struct DotTheta{Tdot, Ta}Internal fields
dot::Any: dot product used in pseudo-arclength constraintapply!::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 examplex -> 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.
BifurcationKit.continuation — Function
continuation(
prob::BifurcationKit.AbstractBifurcationProblem,
alg::BifurcationKit.AbstractContinuationAlgorithm,
contparams::ContinuationPar;
linear_algo,
bothside,
kwargs...
) -> BifurcationKit.DCResult{Tprob, Tbr, Tit, Tsol, Talg} where {Tprob<:BifurcationKit.BVP.BVPBifProblem, Tbr<:(Vector), Tit<:(ContIterable{BifurcationKit.BoundaryValueProblemCont, Tprob, Talg, T, _A, _B, typeof(LinearAlgebra.norm), typeof(BifurcationKit.finalise_default), typeof(BifurcationKit.cb_default), Nothing} where {Tprob<:BifurcationKit.BVP.BVPBifProblem, Talg<:BifurcationKit.AbstractContinuationAlgorithm, T<:Real, _A, _B}), Tsol<:(Vector), Talg<:DefCont}
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::AbstractBifurcationProblema::AbstractBifurcationProblem, typically aBifurcationProblemwhich holds the vector field and its jacobian. We also refer toBifFunctionfor more details.algcontinuation algorithm, for exampleNatural(), PALC(), Multiple(),.... See algoscontparams::ContinuationParparameters for continuation. SeeContinuationPar
Optional Arguments:
plot = falsewhether to plot the solution/branch/spectrum while computing the branchbothside = falsecompute the branches on the two sides of the initial parameter valuep0, merge them and return it.normC = normnorm used in the nonlinear solvesfilenameto save the computed branch during continuation. The identifier .jld2 will be appended to this filename. This requiresusing JLD2.callback_newtoncallback for newton iterations. See docs ofsolve. For example, it can be used to change the preconditioners. It can also be used to limit residuals and parameter steps, seecbMaxNormandcbMaxNormAndΔpfinalise_solution = (z, tau, step, contResult; kwargs...) -> trueFunction called at the end of each continuation step. Can be used to alter the continuation procedure (stop it by returningfalse), save personal data, plot... The notations arez = BorderedArray(x, p)wherex(resp.p) is the current solution (resp. parameter value),tau::BorderedArrayis the tangent atz,step::Intis the index of the current continuation step andcontResultis the current branch but before saving the currentstateto it! For advanced use:- the state
state::ContStateof the continuation iterator is passed inkwargs. This can be used for testing whether this is called from bisection for locating bifurcation points / events:in_bisection(state)for example. This allows to escape some personal code in this case.
- the iterator
iter::ContIterableof the continuation is passed inkwargs.
- the state
verbosity::Int = 0controls the amount of information printed during the continuation process. Must belong to{0,1,2,3}. In casecontparams.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
linear_algoset the linear solver for the continuation algorithmalg.For example,PALCneeds a linear solver for an enlarged problem (sizen+1instead ofn) and one thus needs to tune the one passed incontparams.newton_options.linsolver. This is a convenient argument to thus change thealglinear solver and is used mostly internally. The proper way is to pass directly toalgthe correct linear solver.kind::AbstractContinuationKind[Internal] flag to describe continuation kind (equilibrium, codim 2, ...). Default =EquilibriumCont()
Output:
contres::ContResultcomposite type which contains the computed branch. SeeContResultfor more information.
continuation(
prob::BifurcationKit.AbstractBifurcationProblem,
algdc::DefCont,
contParams::ContinuationPar;
verbosity,
plot,
linear_algo,
dot_palc,
callback_newton,
filename,
normC,
kwcont...
) -> BifurcationKit.DCResult{Tprob, Tbr, Tit, Tsol, Talg} where {Tprob<:BifurcationKit.BVP.BVPBifProblem, Tbr<:(Vector), Tit<:(ContIterable{BifurcationKit.BoundaryValueProblemCont, Tprob, Talg, T, _A, _B, typeof(LinearAlgebra.norm), typeof(BifurcationKit.finalise_default), typeof(BifurcationKit.cb_default), Nothing} where {Tprob<:BifurcationKit.BVP.BVPBifProblem, Talg<:BifurcationKit.AbstractContinuationAlgorithm, T<:Real, _A, _B}), Tsol<:(Vector), Talg<:DefCont}
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::AbstractBifurcationProblembifurcation problemalg::DefCont, deflated continuation algorithm, seeDefContcontParamsparameters for continuation. SeeContinuationParfor more information about the options
Optional Arguments:
plot = falsewhether to plot the solution while computing,callback_newtoncallback for newton iterations. see docs fornewton. 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 argumentfromDeflatedNewton = trueto tell the user can it is not in the continuation part (regular newton) of the algorithm,verbosity::Intcontrols the amount of information printed during the continuation process. Must belong to{0,⋯,5},normC = normnorm 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 factor1/length(x)for example in problems where the dimension of the state space changes (mesh adaptation, ...),
Outputs:
contres::DCResultcomposite type which contains the computed branches. SeeContResultfor more information,
continuation(
br::BifurcationKit.AbstractBranchResult,
ind_bif,
lens2::Union{typeof(identity), IndexLens, PropertyLens, ComposedFunction};
...
) -> Any
continuation(
br::BifurcationKit.AbstractBranchResult,
ind_bif,
lens2::Union{typeof(identity), IndexLens, PropertyLens, ComposedFunction},
options_cont::ContinuationPar;
prob,
start_with_eigen,
detect_codim2_bifurcation,
update_minaug_every_step,
kwargs...
) -> Any
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
brresults returned after a call to continuationind_bifbifurcation index inbrlens2second parameter used for the continuation, the first one is the one used to computebr, e.g.getlens(br)options_cont = br.contparamsarguments to be passed to the regular continuation
Optional arguments:
linsolve_adjointsolver for (J+iω)˟ ⋅sol = rhs or Jᵗ ⋅sol = rhsbdlinsolverbordered linear solver for the constraint equationbdlinsolver_adjointbordered linear solver for the constraint equation with top-left block (J-iω)˟ or Jᵗ. Required in the linear solver for the Minimally Augmented Fold/Hopf functional. This option can be used to pass a dedicated linear solver for example with specific preconditioner.update_minaug_every_stepupdate vectorsa, bin Minimally Formulation everyupdate_minaug_every_stepstepsdetect_codim2_bifurcation ∈ {0,1,2}whether to detect Bogdanov-Takens, Bautin and Cusp. If equals1non precise detection is used. If equals2, a bisection method is used to locate the bifurcations. Default value = 2.start_with_eigen = falsewhether to start the Minimally Augmented problem with information from eigen elements. Ifstart_with_eigen = false, then:a::Nothingestimate of null vector of J (resp. J-iω) for Fold (resp. Hopf). If nothing is passed, a random vector is used. In case you do not rely onAbstractArray, you should probably pass this.b::Nothingestimate of null vector of Jᵗ (resp. (J-iω)˟) for Fold (resp. Hopf). If nothing is passed, a random vector is used. In case you do not rely onAbstractArray, you should probably pass this.
kwargskeywords 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.
continuation(
prob::BifurcationKit.AbstractBifurcationProblem,
x0,
par0,
x1,
p1::Real,
alg,
lens::Union{typeof(identity), IndexLens, PropertyLens, ComposedFunction},
contParams::ContinuationPar;
bothside,
kwargs...
) -> ContResult
[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 pseudo arc length s=0) with parameter par0 and x1 is the second point with parameter set(par0, lens, p1).
continuation(
br::BifurcationKit.AbstractResult{Tkind<:Union{BifurcationKit.BoundaryValueProblemCont, BifurcationKit.EquilibriumCont}, Tprob},
ind_bif::Int64;
...
) -> Any
continuation(
br::BifurcationKit.AbstractResult{Tkind<:Union{BifurcationKit.BoundaryValueProblemCont, BifurcationKit.EquilibriumCont}, Tprob},
ind_bif::Int64,
options_cont::ContinuationPar;
...
) -> Branch
continuation(
br::BifurcationKit.AbstractResult{Tkind<:Union{BifurcationKit.BoundaryValueProblemCont, BifurcationKit.EquilibriumCont}, Tprob},
ind_bif::Int64,
options_cont::ContinuationPar,
Teigvec::Type{𝒯eigvec};
alg,
δp,
ampfactor,
use_normal_form,
bls,
bls_block,
nev,
scaleζ,
autodiff,
start_with_eigen,
usedeflation,
verbosedeflation,
max_iter_deflation,
perturb,
plot_solution,
tol_fold,
kwargs_deflated_newton,
kwargs...
) -> Any
Automatic 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.
Arguments
br: branch result from a call tocontinuationcontaining the bifurcation pointind_bif: index of the bifurcation point inbrfrom which to branchoptions_cont: continuation parameters for the new branch
Optional arguments
alg = getalg(br)continuation algorithm to be used, default value:getalg(br)δpused to specify a specific value for the parameter on the bifurcated branch which is otherwise determined byoptions_cont.ds. This allows to use a step larger thanoptions_cont.dsmax.ampfactor = 1factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep. Can also be used to select the upper/lower branch in Pitchfork bifurcations. See alsouse_normal_formbelow.use_normal_form = true. Ifuse_normal_form = true, the normal form is computed as well as its predictor and a guess is automatically formed. Ifuse_normal_form = false, the parameter valuep = p₀ + δpand the guessx = x₀ + ampfactor .* e(whereeis a vector of the kernel) are used as initial guess. This is useful in case automatic branch switching does not work.nevnumber of eigenvalues to be computed to get the right eigenvectorscaleζ = normpass a norm to normalize vectors during normal form computationplot_solutionchange plot solution method in the problemgetprob(br)usedeflation = falsewhether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcatedverbosedeflationprint deflated newton iterationsmax_iter_deflationnumber of newton steps in deflated newtonperturb = identitywhich perturbation function to use during deflated newtonTeigvec = _getvectortype(br)type of the eigenvector. Useful whenbrwas loaded from a file and this information was lostkwargsoptional arguments to be passed tocontinuation, the regularcontinuationone and toget_normal_form.
In the case of a very large model and use of special hardware (GPU, cluster), we suggest to decouple 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.
continuation(
discPO::BifurcationKit.AbstractShootingDiscretization,
orbitguess,
alg::BifurcationKit.AbstractContinuationAlgorithm,
contParams::ContinuationPar,
linear_algo::BifurcationKit.AbstractBorderedLinearSolver;
δ,
eigsolver,
record_from_solution,
plot_solution,
kwargs...
) -> Any
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 Shooting or a PoincareShooting. By default, it prints the period of the periodic orbit.
Optional arguments
eigsolverspecify an eigen solver for the computation of the Floquet exponents, defaults toFloquetQaD
jacobian Specify the choice of the linear algorithm, which must belong to (BifurcationKit.AutoDiffMF(), BifurcationKit.MatrixFree(), BifurcationKit.AutoDiffDense(), BifurcationKit.AutoDiffDenseAnalytical(), BifurcationKit.FiniteDifferences(), BifurcationKit.FiniteDifferencesMF()). This is used to select a way of inverting the jacobian dG
1. 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
2. For `AutoDiffMF()`, we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of `x -> prob(x, p)` using a directional derivative, also called JVP product. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
3. 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.
4. 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.
5. For `AutoDiffDenseAnalytical()`. Same as for `AutoDiffDense` but the jacobian is formed using a mix of AD and analytical formula.
6. 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.continuation(
disc::BifurcationKit.AbstractBoundaryValueDiscretization,
orbitguess,
alg::BifurcationKit.AbstractContinuationAlgorithm,
_contParams::ContinuationPar;
linear_algo,
kwargs...
) -> Any
This is the continuation routine for computing a periodic orbit.
Arguments
Similar to continuation except that prob::AbstractBoundaryValueDiscretization.
Optional argument
linear_algo::AbstractBorderedLinearSolver
jacobian Specify the choice of the linear algorithm, which must belong to (BifurcationKit.AutoDiffMF(), BifurcationKit.MatrixFree(), BifurcationKit.AutoDiffDense(), BifurcationKit.AutoDiffDenseAnalytical(), BifurcationKit.FiniteDifferences(), BifurcationKit.FiniteDifferencesMF()). This is used to select a way of inverting the jacobian dG
1. 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
2. For `AutoDiffMF()`, we use Automatic Differentiation (AD) to compute the (matrix-free) derivative of `x -> prob(x, p)` using a directional derivative, also called JVP product. This is to be used with an iterative solver (e.g. GMRES) to solve the linear system
3. 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.
4. 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.
5. For `AutoDiffDenseAnalytical()`. Same as for `AutoDiffDense` but the jacobian is formed using a mix of AD and analytical formula.
6. 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.continuation(
br::BifurcationKit.AbstractBranchResult,
ind_bif::Int64,
_contParams::ContinuationPar,
disc::BifurcationKit.AbstractBoundaryValueDiscretization;
bif_prob,
detailed,
start_with_eigen,
use_normal_form,
nev,
kwargs...
) -> Branch
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
brbranch result from a call tocontinuationind_hopfindex of the bifurcation point inbrcontParamsparameters for the call tocontinuationdiscdiscretization used to specify the way toc compute the periodic orbit. It can beTrapeze,Collocation,ShootingorPoincareShooting.
Optional arguments
alg = getalg(br)continuation algorithm used for the bifurcated branch. It is inherited from the branchbr.δpused to specify the guess for the parameter on the bifurcated branch which otherwise defaults tocontParams.ds. This allows to use an initial step larger thancontParams.dsmax.ampfactor = 1multiplicative factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.use_normal_form = truewhether to use the normal form in order to compute the predictor. Whenfalse,ampfactorandδpare used to make a predictor based on the bifurcating eigenvector. Settinguse_normal_form = falsecan be useful when computing the normal form is not possible for example when higher order derivatives are not available.usedeflation = falsewhether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branchnevnumber of eigenvalues to be computed to get the right eigenvector- all
kwargsfromcontinuation
A modified version of prob is passed to plot_solution and finalise_solution.
continuation(
br::BifurcationKit.AbstractResult{BifurcationKit.PeriodicOrbitCont, Tprob<:BifurcationKit.AbstractWrapperPeriodicOrbitProblem},
ind_bif::Int64,
_contParams::ContinuationPar;
alg,
δp,
ampfactor,
usedeflation,
linear_algo,
detailed,
prm,
use_normal_form,
autodiff_nf,
kwargs...
) -> Branch
Branch switching at a bifurcation point of periodic orbits (PO) specified by a br::AbstractBranchResult. The functional for computing the PO is getprob(br). A deflated Newton-Krylov solver can be used to improve the branch switching capabilities.
Arguments
brbranch of periodic orbitsind_bifindex of the branch point_contParamscontinuation parameters, seecontinuation
Optional arguments
δp = _contParams.dsused to specify a particular guess for the parameter in the branch which is otherwise determined bycontParams.ds. This allows to use a step larger thancontParams.dsmax.ampfactor = 1factor which alters the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.usedeflation = falsewhether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcated branchuse_normal_form = trueiffalse, the predictor is based on the coupleδp, ampfactor.
For normal form
detailed = truewhether to fully compute the normal form or a very simplified version.autodiff_nf = truewhether to useautodiffinget_normal_form. This can be used in case automatic differentiation is not working as intented.
For continuation
linear_algo = nothing, same as forcontinuation; whennothing, aBorderingBLSis built from_contParams.newton_options.linsolver.kwargskeywords arguments used for a call to the regularcontinuationand the ones specific to periodic orbits (POs).
continuation(
trap::Trapeze,
orbitguess,
alg::BifurcationKit.AbstractContinuationAlgorithm,
_contParams::ContinuationPar;
1002,
record_from_solution,
linear_algo,
kwargs...
) -> Any
Convenience wrapper around continuation_po to continue a branch of periodic orbits computed with the Trapeze finite-difference functional.
Arguments
trapa problem of typeTrapezeencoding the functionalG.orbitguessa guess for a first periodic orbit. SeeTrapezefor more details.algcontinuation algorithm.contParamssame as for the regularcontinuationmethod.
Keyword arguments
linear_algosame as incontinuation; it defaults to a bordered linear solver based oncontParams.newton_options.linsolver.record_from_solutionfunction used to record the solution on the branch; it defaults to(u, p; k...) -> (period = u[end],)so that the period is printed along the branch.
These methods only differ in the linear algebra used to invert the jacobian dG of the functional G (see Trapeze); the discretization is otherwise the same. The value of jacobian must belong to (BifurcationKit.Dense(), BifurcationKit.AutoDiffDense(), BifurcationKit.FullLU(), BifurcationKit.FullMatrixFree(), BifurcationKit.BorderedLU(), BifurcationKit.BorderedMatrixFree(), BifurcationKit.FullSparseInplace(), BifurcationKit.BorderedSparseInplace(), BifurcationKit.AutoDiffMF()).
- For
jacobian = FullLU(), we use the default linear solver based on a sparse matrix representation ofdG. This matrix is assembled at each Newton iteration. This is the right choice when the sparsity pattern can change. - For
jacobian = FullSparseInplace(), this is the same as forFullLU()but the sparse matrixdGis updated inplace. This method allocates much less and, in some cases, is significantly faster thanFullLU(). 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 matrixdGis dense, and it is also updated inplace. This option is useful to study ODEs of small dimension. - For
jacobian = AutoDiffDense(), the jacobian is evaluated using automatic differentiation (ForwardDiff). - For
jacobian = BorderedLU(), we take advantage of the bordered shape ofdGand invert it with a bordered linear solver based on a LU decomposition of the cyclic matrix. - For
jacobian = BorderedSparseInplace(), this is the same as forBorderedLU()but the cyclic matrixJcis updated inplace. This method allocates much less and, in some cases, is significantly faster thanBorderedLU(). 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 (given byoptions.linsolver) is used to invertdG: note that a preconditioner is very likely required here because of the cyclic shape ofdGwhich negatively affects the convergence properties of GMRES. - For
jacobian = BorderedMatrixFree(), a matrix-free linear solver is used as well but only forJc(see the docs):options.linsolveris then used to invertJc. These two matrix-free options thus expose different parts of the jacobiandGin order to apply specific preconditioners. For example, an ILU preconditioner onJccould remove the constraints indGand lead to poor convergence. Of course, for these last two methods, a preconditioner is likely to be required. - For
jacobian = AutoDiffMF(), 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.
continuation(
coll::Collocation,
orbitguess,
alg::BifurcationKit.AbstractContinuationAlgorithm,
_contParams::ContinuationPar,
linear_algo::BifurcationKit.AbstractBorderedLinearSolver;
δ,
eigsolver,
record_from_solution,
plot_solution,
kwargs...
) -> Any
This is the continuation method for computing a periodic orbit using an orthogonal collocation method.
Arguments
Similar to continuation except that prob is a Collocation. By default, it prints the period of the periodic orbit.
Keywords arguments
eigsolverspecify an eigen solver for the computation of the Floquet exponents, defaults toFloquetColl
Specific continuation routine for wave problems.
Arguments
Iterator
BifurcationKit.ContIterable — Type
struct ContIterable{Tkind<:BifurcationKit.AbstractContinuationKind, Tprob, Talg, T, S, E, TnormC, Tfinalisesolution, TcallbackN, Tevent} <: BifurcationKit.AbstractContinuationIterable{Tkind<:BifurcationKit.AbstractContinuationKind}Iterator over the steps of a continuation procedure. Calling continuation is equivalent to iterating over a ContIterable while saving the states in a ContResult. Constructing the iterator manually allows a finer control of the continuation procedure:
iter = ContIterable(prob, alg, contparams; kwargs...)
for state in iter
println("Continuation step = ", state.step)
endThe first iteration computes the initial point on the branch, its tangent and its stability. Each subsequent iteration performs one continuation step: Newton correction of the predicted point, step size adaptation and computation of the next predictor. Iteration stops when the number of steps reaches contparams.max_steps, when the parameter exits [p_min, p_max], when the corrector fails or when the user requests it (for example via finalise_solution, see continuation).
Fields
kind::BifurcationKit.AbstractContinuationKind: type of solution computed during continuation, e.g.EquilibriumContorPeriodicOrbitContprob::Any: bifurcation problem to be continued, seeBifurcationProblemalg::Any: continuation algorithm, e.g.PALCorMoorePenrosecontparams::ContinuationPar{T, S, E} where {T, S, E}: continuation parameters, seeContinuationParplot::Bool: whether to plot the branch during continuationevent::Any: structure for event detectionnormC::Any: norm used in the nonlinear solver to measure the size of the correctionsfinalise_solution::Any: function called at the end of each continuation step, seecontinuationcallback_newton::Any: callback called after each newton iteration, seecontinuationverbosity::UInt8: level of verbosity, must belong to {0,1,2,3}filename::String: name of the file where the branch is saved ifsave_to_file = trueinContinuationPar
Useful functions
getprob(iter)returns the bifurcation problemgetalg(iter)returns the continuation algorithmgetcontparams(iter)returns the continuation parameterssetparam(iter, p::Real)set parameter with lensiter.prob.lenstopis_event_active(iter)whether the event detection is activecompute_eigenelements(iter)whether to compute eigen elementssave_eigenvectors(iter)whether to save eigen vectorsisindomain(iter, p)whetherpis in the domain [pmin, pmax]is_on_boundary(iter, p)whetherpis on the boundary {pmin, pmax}length(iter)the maximum number of continuation steps
More information is available on the website
BifurcationKit.ContState — Type
mutable struct ContState{Tv, T, Teigvals, Teigvec, Tcb} <: BifurcationKit.AbstractContinuationState{Tv}Mutable structure holding the current state of the continuation procedure: the current solution z, its tangent τ, the predictor z_pred and the current step size ds. It is created internally by the iterator ContIterable and updated at each continuation step (Newton correction, eigen-solver, step size control, predictor). It is also passed as a keyword argument to user callbacks like finalise_solution (see continuation).
If you mutate these (internal) fields yourself, you can break the continuation procedure. Use the methods below to access the fields, knowing that they do not yield copies.
Internal fields
z_pred::Any: predictor, i.e. the initial guess for the next Newton correction.τ::Any: tangent to the curve at the current solution.z::Any: current solution.z_old::Any: previous solution on the branch.converged::Bool: whether the newton correction converged at the current continuation step.itnewton::Int64: Number of newton iteration (in corrector).itlinear::Int64: number of linear iteration (in newton corrector).step::Int64: current continuation step.ds::Any: current step size.stopcontinuation::Bool: boolean to stop continuation.stepsizecontrol::Bool: perform step size adaptation.n_unstable::Tuple{Int64, Int64}: number of unstable eigenvalues (current, previous).n_imag::Tuple{Int64, Int64}: number of unstable complex eigenvalues (current, previous).convergedEig::Bool: boolean for eigen solver computation.eigvals::Any: current eigenvalues.eigvecs::Any: current eigenvectors.eventValue::Any: current and previous values of the event function.in_bisection::Bool: whether the state is in bisection for locating special points.
Useful functions
copy(state)returns a copy ofstate.copyto!(dest, state)copystateintodest.getsolution(state)returns the current solution(x, p).gettangent(state)return the tangent at the current solution.getpredictor(state)return the predictor at the current solution.getx(state)returns the x component of the current solution.getp(state)returns the p component of the current solution.get_previous_solution(state)returns the previous solution(x, p).getpreviousx(state)returns the x component of the previous solution.getpreviousp(state)returns the p component of the previous solution.is_stable(state)whether the current state is stable.in_bisection(state)whether the state is in bisection for locating special points.getparams(iter, state)return the current parameter set.
Continuation algorithms
Tangents / predictors
BifurcationKit.Natural — Type
Natural continuation algorithm. The predictor is the constant predictor and the parameter is incremented by ContinuationPar().ds at each continuation step. The corrector is the regular newton algorithm.
Constructor(s)
Natural()
BifurcationKit.Secant — Type
Secant Tangent predictorBifurcationKit.Bordered — Type
Bordered Tangent predictorBifurcationKit.Polynomial — Type
Polynomial Tangent predictorInternal fields
n::Int64: Order of the polynomialk::Int64: Length of the last solutions vector used for the polynomial fitA::Matrix{T} where T<:Real: Matrix for the interpolationtangent::BifurcationKit.AbstractTangentComputation: Algo for tangent when polynomial predictor is not possiblesolutions::DataStructures.CircularBuffer: Vector of solutionsparameters::DataStructures.CircularBuffer{T} where T<:Real: Vector of parametersarclengths::DataStructures.CircularBuffer{T} where T<:Real: Vector of arclengthscoeffsSol::Vector: Coefficients for the polynomials for the solutioncoeffsPar::Vector{T} where T<:Real: Coefficients for the polynomials for the parameterupdate::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)norder of the polynomialklength of the last solutions vector used for the polynomial fitv0example of solution to be stored. It is only used to get theeltypeof the tangent.
Can be used like
PALC(tangent = Polynomial(Bordered(), 2, 6, rand(1)))BifurcationKit.Multiple — Type
Multiple Tangent continuation algorithm.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 called pmcont in pde2path.
Internal fields
alg::PALC: Tangent predictor used. Default: PALC()τ::Any: Save the current tangent.α::Real: Damping in Newton iterations, 0 < α < 1.nb::Int64: Number of predictorscurrentind::Int64: Index of the largest converged predictor. Default: 0pmimax::Int64: Index for lookup in residual history. Default: 1imax::Int64: Maximum index for lookup in residual history. Default: 4dsfact::Real: Factor to increase ds upon successful step. Default: 1.5
Constructor(s)
Multiple(alg, x0, α, nb)
Multiple(x0, α, nb)Algorithms
BifurcationKit.PALC — Type
struct PALC{Ttang<:BifurcationKit.AbstractTangentComputation, Tbls<:BifurcationKit.AbstractLinearSolver, T, Tdot} <: BifurcationKit.AbstractContinuationAlgorithmPseudo-arclength continuation algorithm.
Additional information is available on the website.
Internal fields
tangent::BifurcationKit.AbstractTangentComputation: Tangent (predictor), must be a subtype ofAbstractTangentComputation. For exampleSecant()orBordered(), etc. 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], not yet used. Default: falsebls::BifurcationKit.AbstractLinearSolver: Bordered linear solver used to invert the jacobian of the bordered problem during newton iterations. It is also used to compute the tangent for the predictorBordered(). Default: MatrixBLS()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 factor1/length(x)for example in problems where the dimension of the state space changes (mesh adaptation, ...) or when a specific (FEM) dot product is provided. Default: DotTheta()
BifurcationKit.AutoSwitch — Type
struct AutoSwitch{Talg, T} <: BifurcationKit.AbstractContinuationAlgorithmContinuation algorithm which switches automatically between Natural continuation and PALC (or other if specified) depending on the stiffness of the branch being continued. The formula for switching from PALC to NATURAL is:
(1 - θ) * abs(τ.p) > tol_param
Internal fields
alg::Any: Continuation algorithm to switch to whenNaturalis discarded. TypicallyPALC()tol_param::Any: tolerance for switching to PALC(), default value = 1//2
Constructor(s)
AutoSwitch(;alg = PALC(tangent = Bordered()), tol_param = 1//2)
BifurcationKit.MoorePenrose — Type
struct MoorePenrose{T, Tls<:BifurcationKit.AbstractLinearSolver} <: BifurcationKit.AbstractContinuationAlgorithmMoore-Penrose continuation algorithm. The tangent used by the predictor is computed by predictor (default PALC()). The corrector solves the extended system (F(x,p)=0, τ⋅(x-x₀,p-p₀)=0) using a Moore-Penrose inverse.
Available linear solvers for method:
BifurcationKit.direct(default): solves[J dFdp] ⋅ Δ = rhsdirectly via\.BifurcationKit.pInv: solves usingLinearAlgebra.pinv.BifurcationKit.iterative: uses a bordered linear solverls(e.g.,MatrixBLS()) for the extended system.
Constructors
MoorePenrose(;predictor = PALC(), method = direct, ls = nothing)
Internal fields
predictor::Any: Tangent predictor, for examplePALC(),Natural(), etc.method::MoorePenroseLS: Moore Penrose linear solver. Can beBifurcationKit.direct,BifurcationKit.pInvorBifurcationKit.iterative.ls::BifurcationKit.AbstractLinearSolver: (Bordered) linear solver used to invert the jacobian of the (bordered) problem during moore-penrose iterations. It is also used to compute the tangent for the predictorBordered().
Missing docstring for AsymptoticNumericalMethod.ANM. Check Documenter's build log for details.
BifurcationKit.DefCont — Type
struct DefCont{Tdo, Talg, Tps, Tas, Tud, Tk} <: BifurcationKit.AbstractContinuationAlgorithmStructure which holds the parameters specific to Deflated continuation.
Internal fields
deflation_operator::Any: Deflation operator,::DeflationOperatorDefault: nothingalg::Any: Used as a predictor,::AbstractContinuationAlgorithm. For examplePALC(),Natural(),... Default: PALC()max_branches::Int64: maximum number of (active) branches to be computed Default: 100seek_every_step::Int64: whether to seek new (deflated) solution at every step Default: 1max_iter_defop::Int64: maximum number of deflated Newton iterations Default: 5perturb_solution::Any: perturb function Default: _perturbSolutionaccept_solution::Any: accept (solution) function Default: _acceptSolutionupdate_deflation_op::Any: function to update the deflation operator, ie pushing new solutions Default: _updateDeflationOpjacobian::Any: jacobian for deflated newton. Can beDeflatedProblemCustomLS(), orVal(:autodiff),Val(:fullIterative)Default: DeflatedProblemCustomLS()
Events
BifurcationKit.DiscreteEvent — Type
struct DiscreteEvent{Tcb, Tl, Tf, Td} <: BifurcationKit.AbstractDiscreteEventStructure to pass a DiscreteEvent function to the continuation algorithm. A discrete call back returns a discrete value and we seek when it changes.
Internal fields
nb::Int64: number of events, ie the length of the result returned by the callback functioncondition::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 elementslabels::Any: Labels used to display information. For examplelabels[1]is used to qualify an event occurring in the first component. You can uselabels = ("hopf",)orlabels = ("hopf", "fold"). You must havelabels::Union{Nothing, NTuple{N, String}}.finaliser::Any: Finaliser functiondata::Any: Place to store some personal data
BifurcationKit.ContinuousEvent — Type
struct ContinuousEvent{Tcb, Tl, T, Tf, Td} <: BifurcationKit.AbstractContinuousEventStructure to pass a ContinuousEvent function to the continuation algorithm. A continuous call back returns a tuple/scalar value and we seek its zeros.
Internal fields
nb::Int64: Number of events, i.e. 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 at 1.0 and at -2.0, you can pass(iter, state) -> (getp(state)+2, getx(state)[1]-1)),. Note that the typeTshould match the one of the parameter specified by the::Lensincontinuation.computeEigenElements::Bool: whether the event requires to compute eigen elements.labels::Any: Labels used to display information. For examplelabels[1]is used to qualify an event of the type(0, 1.3213, 3.434). You can uselabels = ("hopf",)orlabels = ("hopf", "fold"). You must havelabels::Union{Nothing, NTuple{N, String}}.tol::Any: Tolerance on event value to declare it as true event.finaliser::Any: Finaliser function.data::Any: Place to store some personal data.
BifurcationKit.SetOfEvents — Type
struct SetOfEvents{Tc<:Tuple, Td<:Tuple} <: BifurcationKit.AbstractEventMultiple 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.FoldDetectEvent, BK.BifDetectEvent)You can pass as many events as you like.
Internal fields
eventC::Tuple: Continuous eventeventD::Tuple: Discrete event
BifurcationKit.PairOfEvents — Type
struct PairOfEvents{Tc<:BifurcationKit.AbstractContinuousEvent, Td<:BifurcationKit.AbstractDiscreteEvent} <: BifurcationKit.AbstractEventStructure 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)Internal fields
eventC::BifurcationKit.AbstractContinuousEvent: Continuous eventeventD::BifurcationKit.AbstractDiscreteEvent: Discrete event
BifurcationKit.SaveAtEvent — Function
SaveAtEvent(
positions::Tuple{Vararg{T, N}} where {N, T};
use_newton
) -> ContinuousEvent{Tcb, Tl, Int64} where {Tcb, Tl}
This 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.
For example, you can use it like continuation(args...; event = SaveAtEvent((1., 2., -3.)))
The keyword use_newton controls how the saved state is finalised:
use_newton = false(default): the event point is simply the last continuation state recorded when the parameter crossed the requested valuep; it is saved without further refinement, so its accuracy is that of the continuation step / event location;use_newton = true: once the event has been located around a target valuep, the event point is refined by running a Newton solve ofF(x, p) = 0at the exact parameterp, starting from the event stateevent_point.xand using thenewton_optionsof the continuation. If it converges, the stateevent_point.xand parameterevent_point.paramare updated to the refined solution andevent_point.precisionis set to the Newton tolerance. Use this when you need an accurate equilibrium located exactly at the requested parameter values.
BifurcationKit.FoldDetectEvent — Constant
`FoldDetectEvent`This 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.
BifurcationKit.BifDetectEvent — Constant
`BifDetectEvent`This 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 on the website at Detection of bifurcation points of Equilibria.
Branch switching (branch point)
BifurcationKit.continuation — Method
continuation(
br::BifurcationKit.AbstractResult{Tkind<:Union{BifurcationKit.BoundaryValueProblemCont, BifurcationKit.EquilibriumCont}, Tprob},
ind_bif::Int64;
...
) -> Any
continuation(
br::BifurcationKit.AbstractResult{Tkind<:Union{BifurcationKit.BoundaryValueProblemCont, BifurcationKit.EquilibriumCont}, Tprob},
ind_bif::Int64,
options_cont::ContinuationPar;
...
) -> Branch
continuation(
br::BifurcationKit.AbstractResult{Tkind<:Union{BifurcationKit.BoundaryValueProblemCont, BifurcationKit.EquilibriumCont}, Tprob},
ind_bif::Int64,
options_cont::ContinuationPar,
Teigvec::Type{𝒯eigvec};
alg,
δp,
ampfactor,
use_normal_form,
bls,
bls_block,
nev,
scaleζ,
autodiff,
start_with_eigen,
usedeflation,
verbosedeflation,
max_iter_deflation,
perturb,
plot_solution,
tol_fold,
kwargs_deflated_newton,
kwargs...
) -> Any
Automatic 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.
Arguments
br: branch result from a call tocontinuationcontaining the bifurcation pointind_bif: index of the bifurcation point inbrfrom which to branchoptions_cont: continuation parameters for the new branch
Optional arguments
alg = getalg(br)continuation algorithm to be used, default value:getalg(br)δpused to specify a specific value for the parameter on the bifurcated branch which is otherwise determined byoptions_cont.ds. This allows to use a step larger thanoptions_cont.dsmax.ampfactor = 1factor to alter the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep. Can also be used to select the upper/lower branch in Pitchfork bifurcations. See alsouse_normal_formbelow.use_normal_form = true. Ifuse_normal_form = true, the normal form is computed as well as its predictor and a guess is automatically formed. Ifuse_normal_form = false, the parameter valuep = p₀ + δpand the guessx = x₀ + ampfactor .* e(whereeis a vector of the kernel) are used as initial guess. This is useful in case automatic branch switching does not work.nevnumber of eigenvalues to be computed to get the right eigenvectorscaleζ = normpass a norm to normalize vectors during normal form computationplot_solutionchange plot solution method in the problemgetprob(br)usedeflation = falsewhether to use nonlinear deflation (see Deflated problems) to help finding the guess on the bifurcatedverbosedeflationprint deflated newton iterationsmax_iter_deflationnumber of newton steps in deflated newtonperturb = identitywhich perturbation function to use during deflated newtonTeigvec = _getvectortype(br)type of the eigenvector. Useful whenbrwas loaded from a file and this information was lostkwargsoptional arguments to be passed tocontinuation, the regularcontinuationone and toget_normal_form.
In the case of a very large model and use of special hardware (GPU, cluster), we suggest to decouple 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.
BifurcationKit.multicontinuation — Function
multicontinuation(
br::BifurcationKit.AbstractBranchResult,
ind_bif::Int64;
...
) -> Union{Nothing, Vector}
multicontinuation(
br::BifurcationKit.AbstractBranchResult,
ind_bif::Int64,
options_cont::ContinuationPar;
...
) -> Union{Nothing, Vector}
multicontinuation(
br::BifurcationKit.AbstractBranchResult,
ind_bif::Int64,
options_cont::ContinuationPar,
Teigvec::Type{𝒯eigvec};
δp,
ampfactor,
nev,
ζs,
scaleζ,
autodiff,
bls_block,
start_with_eigen,
verbosedeflation,
plot_solution,
kwargs...
) -> Union{Nothing, Vector}
Automatic 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.
Arguments
brbranch result from a call tocontinuationind_bifindex of the bifurcation point inbrfrom which you want to branch fromoptions_contoptions for the call tocontinuation
Optional arguments
alg = getalg(br)continuation algorithm to be used, default value:getalg(br)δpused to specify a particular guess for the parameter on the bifurcated branch which is otherwise determined byoptions_cont.ds. This allows to use a step larger thanoptions_cont.dsmax.ampfactor = 1factor which alters the amplitude of the bifurcated solution. Useful to magnify the bifurcated solution when the bifurcated branch is very steep.nevnumber of eigenvalues to be computed to get the right eigenvectorverbosedeflation = falsewhether to display the nonlinear deflation iterations (see Deflated problems) to help finding the guess on the bifurcated branchscaleζnorm used to normalize eigenbasis when computing the reduced equationTeigvectype of the eigenvector. Useful whenbrwas loaded from a file and this information was lostζsbasis of the kernelperturb_guess = identityperturb the guess from the predictor just before the deflated-newton correctionkwargsoptional arguments to be passed tocontinuation, the regularcontinuationone.
In 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.
multicontinuation(
br::BifurcationKit.AbstractBranchResult,
bpnf::BifurcationKit.NdBranchPoint,
defOpm::DeflationOperator,
defOpp::DeflationOperator;
...
) -> Vector
multicontinuation(
br::BifurcationKit.AbstractBranchResult,
bpnf::BifurcationKit.NdBranchPoint,
defOpm::DeflationOperator,
defOpp::DeflationOperator,
options_cont::ContinuationPar;
alg,
δp,
verbosedeflation,
max_iter_deflation,
plot_solution,
Teigvec,
kwargs...
) -> Vector
Automatic 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.
Arguments
brbranch result from a call tocontinuationbpnfnormal formdefOpm::DeflationOperator, defOpp::DeflationOperatorto specify converged points on non-trivial branches before/after the bifurcation points. The points are located indefOpm.rootsanddefOpp.roots. Note that we only continue from the second points in the roots vectors, the first one is meant to be the trivial branch.
The rest is as the regular multicontinuation function.
Branch switching (Hopf point)
Missing docstring for continuation(br::BifurcationKit.AbstractBranchResult, ind_bif::Int, _contParams::ContinuationPar, prob::BifurcationKit.AbstractPeriodicOrbitProblem ; kwargs...). Check Documenter's build log for details.
Bifurcation diagram
BifurcationKit.bifurcationdiagram — Function
bifurcationdiagram(
prob::BifurcationKit.AbstractBifurcationProblem,
alg::BifurcationKit.AbstractContinuationAlgorithm,
level::Int64,
options;
linear_algo,
kwargs...
) -> BifDiagNode{Tγ, Vector{BifDiagNode}} where Tγ<:BifurcationKit.AbstractBranchResult
Compute the bifurcation diagram associated with the problem F(x, p) = 0 recursively.
Arguments
prob::AbstractBifurcationProblembifurcation problemalgcontinuation algorithmlevelmaximum branching (or recursion) level for computing the bifurcation diagramoptions = (x, p, level) -> contparamsthis function allows to change thecontinuationoptions depending on the branchinglevel. The argumentx, pdenotes the current solution toF(x, p) = 0.kwargsoptional arguments. Look atbifurcationdiagram!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::BifurcationKit.AbstractBifurcationProblem,
node::BifDiagNode,
maxlevel::Int64,
options;
code,
halfbranch,
verbosediagram,
kwargs...
) -> BifDiagNode
Similar 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.
Arguments
node::BifDiagNodea node in the bifurcation diagrammaxlevelrequired maximal level of recursion.options = (x, p, level; k...) -> contparamsthis function allows to change thecontinuationoptions depending on the branchinglevel. The argumentx, pdenotes the current solution toF(x, p)=0.
Optional arguments
code = "0"code used to display iterationsusedeflation = falsehalfbranch = falsefor Pitchfork / Transcritical bifurcations, compute only half of the branch. Can be useful when there are symmetries.verbosediagramverbose specific to bifurcation diagram. Print information about the branches as they are being computed.kwargsoptional arguments as forcontinuationbut also for the different versions listed in Continuation.
BifurcationKit.get_branch — Function
get_branch(diagram::BifDiagNode, code) -> BifDiagNode
Return the part of the diagram (bifurcation diagram) by recursively descending down the diagram using the Int valued tuple code. For example get_branch(diagram, (1,2,3,)) returns diagram.child[1].child[2].child[3].
BifurcationKit.get_branches_from_BP — Function
get_branches_from_BP(
diagram::BifDiagNode,
indbif::Int64
) -> Vector{BifDiagNode}
Return the part of the diagram corresponding to the indbif-th bifurcation point on the root branch.
Utils for periodic orbits
BifurcationKit.getperiod — Function
getperiod(
::BifurcationKit.AbstractBoundaryValueDiscretization,
x
) -> Any
getperiod(
::BifurcationKit.AbstractBoundaryValueDiscretization,
x,
par
) -> Any
Compute the period of the periodic orbit associated to x.
getperiod(prob::Trapeze, x, p) -> Any
Compute the period of the periodic orbit associated to x.
getperiod(psh::PoincareShooting, x_bar, par) -> Any
Compute the period of the periodic orbit associated to x_bar.
BifurcationKit.SectionSS — Type
struct SectionSS{Tn} <: BifurcationKit.AbstractSectionThis composite type (named for Section Standard Shooting) encodes a type of section implemented by a single hyperplane. It can be used in conjunction with Shooting. The hyperplane is defined by a point center and a normal and is defined by
\[0 = < normal, x - center >\]
Internal fields
normal::Any: Normal to define hyperplane.center::Any: Representative point on hyperplane.
Constructor(s)
SectionSS(normals, centers) which only applies to the first normal (resp. center) in the list of normals (resp. centers).BifurcationKit.SectionPS — Type
struct SectionPS{Tn, Tc, Tnb, Tcb, Tr} <: BifurcationKit.AbstractSectionThis composite type (named for SectionPoincaréShooting) encodes a type of Poincaré sections implemented by hyperplanes. It can be used in conjunction with PoincareShooting. Each hyperplane is defined par a point (one example in centers) and a normal (one example in normals). See [1] for more details.
Internal fields
M::Int64: number of hyperplanesnormals::Any: normals to define hyperplanescenters::Any: representative point on each hyperplaneindices::Vector{Int64}: indices to be removed in the operator Eknormals_bar::Any: Projected normalscenters_bar::Any: Projected centersradius::Any
Constructor(s)
SectionPS(normals, centers)Ref(s)
[1] J., M. Net, B. Garcı́a-Archilla, and C. Simó. “Newton–Krylov Continuation of Periodic Orbits for Navier–Stokes Flows.” Journal of Computational Physics 201, no. 1 (November 20, 2004): 13–33. https://doi.org/10.1016/j.jcp.2004.04.018.
Misc.
BifurcationKit.PrecPartialSchurKrylovKit — Function
PrecPartialSchurKrylovKit(J, x0, nev, which = :LM; krylovdim = max(2nev, 20), verbosity = 0)Builds 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().
BifurcationKit.PrecPartialSchurArnoldiMethod — Function
PrecPartialSchurArnoldiMethod(J, N, nev, which = LM(); tol = 1e-9, kwargs...)Builds 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.
BifurcationKit.Flow — Type
struct Flow{TF, Tf, Tts, Tff, Td, Tad, Tse, TR01, TR11, TR20, TR30, Tfs, Tcb, Tδ} <: BifurcationKit.AbstractFlowStructure to encode the flow associated to a Cauchy problem dx/dt = F(x, p).
Internal fields
F::Any: The vector field(x, p) -> F(x, p)associated to a Cauchy problem. Used for the differential of the shooting problem. Default: nothingflow::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: nothingflowTimeSol::Any: Flow which returns the tuple (t, u(t)). Optional, mainly used for plotting on the user side. Default: nothingflowFull::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 usenothingas default. Default: nothingjvp::Any: The differentialdflowof the flow w.r.t.x,(x, p, dx, t) -> dflow(x, p, dx, t). One important thing is that we requiredflow(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: nothingvjp::Any: The adjoint differentialvjpflowof the flow w.r.t.x,(x, p, dx, t) -> vjpflow(x, p, dx, t). One important thing is that we requirevjpflow(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: nothingjvpSerial::Any: [Optional] Serial version of dflow. Used internally by parallel multiple shooting. Please usenothingas default. Default: nothingR01::Any: [Optional] Derivatives of the flow with respect to the parameterlens.R01(x, pars, t, lens, p)returns∂ₚφ(x, p, t), the derivative of the flow map with respect to the parameterlensevaluated atp, as a vector of the size ofx. It is used by the Poincaré return map and the normal forms. Default: nothingR11::Any: [Optional] Derivatives of the flow with respect to the parameterlens.R11(x, pars, dx, t, lens, p)returns∂ₚ[dφ(x, p, t)⋅dx], the mixed derivative of the JVP with respect to the parameter, as a vector of the size ofx. It is used by the Poincaré return map and the normal forms. Default: nothingR20::Any: [Optional] Higher-order differentials of the flow with respect tox.R20(x, pars, h1, h2, t)returnsd²φ(x, p, t)(h1, h2), the second differential of the flow map applied toh1,h2. Used by the normal forms. Default: nothingR30::Any: [Optional] Higher-order differentials of the flow with respect tox.R30(x, pars, h1, h2, h3, t)returnsd³φ(x, p, t)(h1, h2, h3), the third differential of the flow map applied toh1,h2,h3. Used by the normal forms. Default: nothingflowSerial::Any: [Internal] Serial version of the flow Default: nothingcallback::Any: [Internal] Store possible callback Default: nothingdelta::Any: [Internal] Default: 1.0e-8
Simplified constructor(s)
We provide a simple constructor where you only pass the vector field F, the flow ϕ and its differential dϕ:
fl = Flow(F, ϕ, dϕ)Simplified constructors for DifferentialEquations.jl
These 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
fl = Flow(prob, Tsit5(); kwargs...)where kwargs is passed to SciMLBase::solve. If your vector field depends on parameters p, you can define a Flow using
fl = Flow(prob, Tsit5(); kwargs...)Finally, you can pass two ODEProblem where the second one is used to compute the variational equation:
fl = Flow(prob1::ODEProblem, alg1, prob2::ODEProblem, alg2; kwargs...)BifurcationKit.get_normal_form — Function
get_normal_form(
prob::BifurcationKit.AbstractBifurcationProblem,
br::BifurcationKit.AbstractBranchResult,
id_bif::Int64;
...
) -> Any
get_normal_form(
prob::BifurcationKit.AbstractBifurcationProblem,
br::BifurcationKit.AbstractBranchResult,
id_bif::Int64,
Teigvec::Type{𝒯eigvec};
nev,
verbose,
lens,
detailed,
autodiff,
scaleζ,
ζs,
ζs_ad,
bls,
bls_adjoint,
bls_block,
bls_block_adjoint,
start_with_eigen
) -> Any
Compute the reduced equation / normal form of the bifurcation point located at br.specialpoint[ind_bif].
Arguments
prob::AbstractBifurcationProblembrresult from a call tocontinuationind_bifindex of the bifurcation point inbr.specialpoint
Optional arguments
nevnumber of eigenvalues used to compute the spectral projection. This number has to be adjusted when used with iterative methods.verbosewhether to display informationζslist of vectors spanning the kernel of the jacobian at the bifurcation point. Useful for enforcing the kernel basis used for the normal form.lens::Lensspecify which parameter to take the partial derivative ∂pFscaleζfunction to normalize the kernel basis. Indeed, the kernel vectors are normalized usingnorm, the normal form coefficients can be super small and can imped its analysis. Usingscaleζ = norminfcan help sometimes.autodiff = truewhether to use ForwardDiff for the differentiations. Only used for the codim 2 normal forms (e.g. Bogdanov-Takens (BT), Zero-Hopf (ZH), Hopf-Hopf (HH) points).detailed = Val(true)whether to compute only a simplified normal form when only basic information is required. This can be useful is cases the computation is "long", for example for a Bogdanov-Takens point.bls = MatrixBLS()specify bordered linear solver. Needed to compute the reduced equation Taylor expansion of Branch/BT points. Indeed, it is required to solveL⋅u = rhswhereLis the jacobian at the bifurcation point,Lis thus singular and we rely on a bordered linear solver to solve this system.bls_block = blsspecify bordered linear solver when the border has dimension > 1 (1 forbls). (seeblsoption above).start_with_eigen = Val(true)whether to compute the basis of the kernel (the eigenvectors) using the eigensolver (Val(true)) or using a bordered linear system (Val(false)). The latter can be more robust for large scale problems where the eigensolver fails. It requiresbls,bls_adjointand possiblybls_blockto be provided.
Available method(s)
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.
References
[1] Golubitsky, Martin, and David G Schaeffer. Singularities and Groups in Bifurcation Theory. Springer-Verlag, 1985. http://books.google.com/books?id=rrg-AQAAIAAJ.
[2] Kielhöfer, Hansjörg. Bifurcation Theory: An Introduction with Applications to PDEs. Applied Mathematical Sciences 156. Springer, 2003. https://doi.org/10.1007/978-1-4614-0502-3.
get_normal_form(
wrap::BifurcationKit.AbstractWrapperPeriodicOrbitProblem,
br::BifurcationKit.AbstractResult{<:BifurcationKit.PeriodicOrbitCont},
id_bif::Int64;
...
) -> Any
get_normal_form(
wrap::BifurcationKit.AbstractWrapperPeriodicOrbitProblem,
br::BifurcationKit.AbstractResult{<:BifurcationKit.PeriodicOrbitCont},
id_bif::Int64,
Teigvec::Type{𝒯eigvec};
nev,
verbose,
ζs,
lens,
scaleζ,
autodiff,
δ,
k...
) -> Any
Compute the normal form (NF) of bifurcations of periodic orbits. We detail the additional keyword arguments specific to periodic orbits.
Optional arguments
prm = falsecompute the normal form using Poincaré return map (PRM). If false, use the Iooss normal form.nev = length(eigenvalsfrombif(br, id_bif)),verbose = false,lens = getlens(br),Teigvec = _getvectortype(br)type of the eigenvectors (can be useful for GPU)scaleζ = norm, scale the eigenvectorautodiff = falseuse autodiff or finite differences in some part of the normal form computationdetailed = truewhether to compute only a simplified normal form when only basic information is required. This can be useful is cases the computation is long.δ = getdelta(wrap)delta used for derivatives based on finite differences.
Notes
For collocation, the default method to compute the NF of Period-doubling and Neimark-Sacker bifurcations is Iooss' one [1].
References
[1] Iooss, "Global Characterization of the Normal Form for a Vector Field near a Closed Orbit.", 1988