Bifurcation Problem
We refer to the docs of BifurcationKit.jl for an in-depth description of the bifurcation problems. Here, we only focus on the ones related to Gridap.
The main structure is GridapBifProblem which encodes a system of PDEs discretized with Gridap.jl. The weak form is written with the usual Gridap API, for example
res((u, v), p, (V1, V2)) = ∫( -p.D1 * ∇(u)⋅∇(V1) + NL1∘(u, v) ⋅ V1 + -p.D2 * ∇(v)⋅∇(V2) + NL2∘(u, v) ⋅ V2 ) * dΩand the problem is instantiated with
prob = GridapBifProblem(res, u0, par, V, U, dΩ, (@optic _.D1); jac = jac, mass = m0)See the tutorials for complete examples.
Mass matrix
Many evolution PDEs write, after semi-discretization in space,
\[M\frac{\mathrm{d}z}{\mathrm{d}t} = F(z, p)\]
where $M$ is a mass matrix which can be singular. A typical example is the incompressible Navier–Stokes equations: the velocity has a time derivative but the pressure does not, so that the mass matrix has a zero block on the pressure dofs.
The stability of a stationary solution is obtained from the generalized eigenvalue problem
\[J\,\phi = \lambda\, M\,\phi\]
and not from the spectrum of $J$ alone (which contains spurious modes coming from the saddle-point structure). For this reason, GridapBifProblem is a subtype of BifurcationKit.AbstractDAEBifProblem and the mass matrix is used automatically by the DAE eigensolvers, see Eigen Solvers.
The mass matrix is assembled with
Missing docstring for GridapBifurcationKit.get_mass_matrix. Check Documenter's build log for details.
By default the L² mass $\int u\cdot v$ is used. For incompressible flows, one passes the velocity only mass, which produces the required zero block on the pressure:
m0((u, p), (v, q)) = ∫( v ⊙ u ) * dΩprob = GridapBifProblem(res, u0, par, V, U, dΩ, lens; jac = jac, mass = m0)The following BifurcationKit functions are specialized so that the mass matrix is correctly taken into account:
BifurcationKit.is_mass_matrix_constant(prob)returnstrue;BifurcationKit.getmassmatrix(prob, x, p)returnsget_mass_matrix(prob).