Skip to content

Biharmonic

The biharmonic problem is a typical example of a higher-order PDE problem. It can appear in, for example, elasticity and fluid flow problems. In this example, we will briefly review what the biharmonic problem looks like, and we will implement it using Mantis.

Formulation

The 1D case.

In 1D the biharmonic problem is defined as:

4ϕ(x)x4=f(x)for x[0,L],ϕ(0)=ϕ(L)=0,2ϕx2(0)=2ϕx2(L)=0,

where we are looking for a function ϕ(x) whose fourth derivative equals negative f(x), the forcing function. We have chosen the domain to be [0,L] with L some length. Note that there are now two boundary conditions, since this is a higher order equation. In this example, we'll use homogeneous boundary conditions on the value and second derivatives. The weak formulation is then as follows.

Given fL2([0,L]), find ψHh,02([0,L]) such that0L2ψx22ϕx2dx=Ωψfdx ψHh,02([0,L]).

For this problem, the homogeneous dirichlet boundary condition is an essential boundary condition, while the homogeneous boundary condition on the laplacian is a natural boundary condition which is already included in the above weak formulation.

The differential form case in nD.

Since Mantis is designed to deal with differential forms, we prefer to work with the differential form formulation of the biharmonic problem. The 1D example above is the 1D version of the 0-form biharmonic problem with homogeneous boundary conditions on the value and laplacian. The 0-form biharmonic problem in n-dimensions on domain ΩRn with boundary Ω is

Δ2ϕ0=f0on Ω,tr(ϕ0)=0on Ω,tr(Δϕ0)=0on Ω.

The weak formulation is then as follows.

Given f0L2Λ0(Ω), find ϕ0H2Λh0(Ω) such thatΩΔψ0Δϕ0=Ωψ0f0 ψ0H2Λh,00(Ω).

What is actually computed?

In many finite element codes, and this is also true for Mantis, the integrals in the above weak formulations are not directly computed on the given domain. Instead, they are pulled-back (mapped) to a reference domain.

For higher-order operators, such as the biharmonic operator, this usually causes derivatives of the (inverse) metric to appear. The Laplacian in 1D, for example, becomes (assuming we have a smooth enough mapping Φ:ξx)

Δϕ0=1det(g)(ξ(1det(g))2ϕξ2+1det(g)2ϕξ2),

while in 2D, it becomes (assuming we have a smooth enough mapping Φ:(ξ,η)(x,y)

Δϕ0=2ϕ0ξ2g1,1+ϕ0ξg1,1ξ+2ϕ0ξηg1,2+ϕ0ηg1,2ξ+2ϕ0ηξg2,1+ϕ0ξg2,1η+2ϕ0η2g2,2+ϕ0ηg2,2η+1det(g)((ϕ0ξg1,1+ϕ0ηg1,2)ξ(det(g))+(ϕ0ξg2,1+ϕ0ηg2,2)η(det(g))).

These expressions are for the Laplacian applied to 0-forms, in which case

Δ=δd=dd,

with δ the codifferential.

These expressions tend to become rather complex. Fortunately, the user does not have to implement such transformations. Mantis can handle this automatically.

Implementation

The 1D case

Let's first look at the 1D version. We will start by creating a geometry (just a line in 1D) from 0.0 to 1.0 with 2 elements. On this geometry, we create a B-spline space of maximally smooth quadratics (so, degree 2 and regularity 1). Note that since the biharmonic problem requires the computation of the Laplacian, the regularity k must be at least 1.

julia
using Mantis
using GLMakie # Used for plotting later on. It also allows the use of L"".

starting_point = (0.0,)
box_size = (1.0,)
num_elements = (2,)
p = (3,)
k = (2,)

geometry = Geometry.create_cartesian_box(starting_point, box_size, num_elements)
B = FunctionSpaces.create_bspline_space(starting_point, box_size, num_elements, p, k)
Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), 3, [4, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5 0.25],), ([0.25 0.5 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,))], 2, 5), [[[1], [2, 3, 4], [5]]])

Mantis works with forms, so we need to define the form space. In this case, we are working with 0-forms, so we define the form space as follows.

julia
Λ⁰ = Forms.FormSpace(0, B, L"\phi_h")
Mantis.Forms.FormSpace{1, 0, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), 3, [4, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5 0.25],), ([0.25 0.5 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,))], 2, 5), [[[1], [2, 3, 4], [5]]]), L"$\phi_h$")

We define the weak form inputs. The weak form inputs contain the trial and test spaces, the forcing function, and the quadrature rule. We define the forcing function as a function of the coordinates. In this case, we define the forcing function as f0=16π4sin(2πx).

julia
function forcing_function(x::Matrix{Float64})
    return [@. 16.0 * pi^4 * sin(2.0 * pi * x[:, 1])]
end
f⁰ = Forms.AnalyticalFormField(0, forcing_function, geometry, L"f^0")
Mantis.Forms.AnalyticalFormField{1, 0, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, typeof(Main.forcing_function), LaTeXStrings.LaTeXString}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), Main.forcing_function, L"$f^0$")

The quadrature rule is defined as a tensor product rule of the degree of the B-spline space plus one. In this case, we define the quadrature rule as a Gauss-Legendre rule.

julia
canonical_qrule = Quadrature.tensor_product_rule(p .+ 1, Quadrature.gauss_legendre)
= Quadrature.StandardQuadrature(canonical_qrule, Geometry.get_num_elements(geometry))
Mantis.Quadrature.StandardQuadrature{1, Mantis.Quadrature.CanonicalQuadratureRule{1, Mantis.Points.CartesianPoints{1, Vector{Float64}, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}, LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}}(Mantis.Quadrature.CanonicalQuadratureRule{1, Mantis.Points.CartesianPoints{1, Vector{Float64}, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}, LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(Mantis.Points.CartesianPoints{1, Vector{Float64}, CartesianIndices{1, Tuple{Base.OneTo{Int64}}}, LinearIndices{1, Tuple{Base.OneTo{Int64}}}}(([0.06943184420297371, 0.33000947820757187, 0.6699905217924281, 0.9305681557970262],), CartesianIndices((4,)), LinearIndices((Base.OneTo(4),))), [0.17392742256872692, 0.3260725774312731, 0.3260725774312731, 0.17392742256872692], "Gauss-Legendre"), 2)

We define the weak form for the biharmonic problem. The weak form is defined as a function that takes the weak form inputs and the quadrature rule as arguments. Note that this function is dimension-agnostic. The laplacian is written as δd.

julia
function zero_form_biharmonic(
    inputs::Assemblers.AbstractInputs, dΩ::Quadrature.AbstractGlobalQuadratureRule
)
    ψ⁰ = Assemblers.get_test_form(inputs)
    ϕ⁰ = Assemblers.get_trial_form(inputs)
    f⁰ = Assemblers.get_forcing(inputs)

    A =(δ(d(ψ⁰)) (δ(d(ϕ⁰))), dΩ)
    lhs_expression = ((A,),)

    b =(ψ⁰ (f⁰), dΩ)
    rhs_expression = ((b,),)

    return lhs_expression, rhs_expression
end
zero_form_biharmonic (generic function with 1 method)

We define the weak form inputs as a WeakFormInputs object. The weak form inputs contain the trial and test spaces, and the forcing function. The trial and test spaces are the same in this case, which is the default.

julia
wfi = Assemblers.WeakFormInputs(Λ⁰, f⁰)
Mantis.Assemblers.WeakFormInputs{1, Tuple{Mantis.Forms.FormSpace{1, 0, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}}, Tuple{Mantis.Forms.FormSpace{1, 0, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}}, Tuple{Mantis.Forms.AnalyticalFormField{1, 0, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, typeof(Main.forcing_function), LaTeXStrings.LaTeXString}}}((Mantis.Forms.FormSpace{1, 0, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), 3, [4, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5 0.25],), ([0.25 0.5 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,))], 2, 5), [[[1], [2, 3, 4], [5]]]), L"$\phi_h$"),), (Mantis.Forms.FormSpace{1, 0, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), 3, [4, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5 0.25],), ([0.25 0.5 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,))], 2, 5), [[[1], [2, 3, 4], [5]]]), L"$\phi_h$"),), (Mantis.Forms.AnalyticalFormField{1, 0, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, typeof(Main.forcing_function), LaTeXStrings.LaTeXString}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), Main.forcing_function, L"$f^0$"),))

We can now assemble the linear system and solve it to obtain the solution. We define the Dirichlet boundary conditions using the appropriate helper function.

julia
bc = Forms.set_dirichlet_boundary_conditions(Λ⁰, 0.0)
Dict{Int64, Float64} with 2 entries:
  5 => 0.0
  1 => 0.0

We assemble the linear system and solve it to obtain the solution. Note that we do not need to redefine the weak form itself; it was already written in a dimension-independent way.

julia
lhs_expressions, rhs_expressions = zero_form_biharmonic(wfi, dΩ)
weak_form = Assemblers.WeakForm(lhs_expressions, rhs_expressions, wfi)
A, b = Assemblers.assemble(weak_form, bc)
sol = vec(A \ b)
ϕ⁰ = Forms.build_form_field(Λ⁰, sol)
Mantis.Forms.FormField{1, 0, Mantis.Forms.FormSpace{1, 0, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}, LaTeXStrings.LaTeXString}(Mantis.Forms.FormSpace{1, 0, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 3),),), (CartesianIndices((2,)),), (LinearIndices((Base.OneTo(2),)),)), 3, [4, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5 0.25],), ([0.25 0.5 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,))], 2, 5), [[[1], [2, 3, 4], [5]]]), L"$\phi_h$"), [0.0, 1.0469646794854808, 6.21724893790088e-15, -1.0469646794854761, 0.0], L"$\phi_h$")

We want to plot the computed solution next to the exact solution, so we also create a FormField for the exact solution.

julia
function exact_solution(x::Matrix{Float64})
    return [@. sin(2.0 * pi * x[:, 1])]
end
ϕ_exact = Forms.AnalyticalFormField(0, exact_solution, geometry, L"\phi_{exact}")

fig = Mantis.Plot.plot_solution((ϕ⁰, ϕ_exact); title="Solution", ylabel=" ")

The above solution does not look very good. We only used two elements with a low polynomial degree for our basis functions. If we use 16 elements instead, we should get a much better approximation. So let's try that:

julia
num_elements = (16,)
(16,)

The code below is the same as before. We don't need to redefine any of the functions that we created, those are still valid. We just rerun the rest.

julia
geometry = Geometry.create_cartesian_box(starting_point, box_size, num_elements)
B = FunctionSpaces.create_bspline_space(starting_point, box_size, num_elements, p, k)

Λ⁰ = Forms.FormSpace(0, B, L"\phi_h")

f⁰ = Forms.AnalyticalFormField(0, forcing_function, geometry, L"f^0")

canonical_qrule = Quadrature.tensor_product_rule(p .+ 1, Quadrature.gauss_legendre)
= Quadrature.StandardQuadrature(canonical_qrule, Geometry.get_num_elements(geometry))

wfi = Assemblers.WeakFormInputs(Λ⁰, f⁰)

bc = Forms.set_dirichlet_boundary_conditions(Λ⁰, 0.0)

lhs_expressions, rhs_expressions = zero_form_biharmonic(wfi, dΩ)
weak_form = Assemblers.WeakForm(lhs_expressions, rhs_expressions, wfi)
A, b = Assemblers.assemble(weak_form, bc)
sol = vec(A \ b)
ϕ⁰ = Forms.build_form_field(Λ⁰, sol)

ϕ_exact = Forms.AnalyticalFormField(0, exact_solution, geometry, L"\phi_{exact}")

fig = Mantis.Plot.plot_solution((ϕ⁰, ϕ_exact); title="Solution", ylabel=" ")

The above solution is indeed much closer (in the 'eyeball-norm') than before. We can make this more precise by computing the error in the L2-norm and plotting how this error decreases as we choose increasingly fine meshes. This is called a convergence study.

Convergence studies for the 1D case.

One way to obtain some confirmation that these results are what we expect, we can compute the error on finer and finer meshes. To start, we create a function that will create all objects based on the geometry that we provide, and that will compute the error using the given geometry.

julia
canonical_qrule_analysis = Quadrature.tensor_product_rule(
    3 .* p .+ 1, Quadrature.gauss_legendre
)

function compute_error_biharmonic(geometry, function_space)
    Λ⁰ = Forms.FormSpace(0, function_space, L"\phi_h")

    f⁰ = Forms.AnalyticalFormField(0, forcing_function, geometry, L"f^0")

= Quadrature.StandardQuadrature(canonical_qrule, Geometry.get_num_elements(geometry))

    wfi = Assemblers.WeakFormInputs(Λ⁰, f⁰)

    bc = Forms.set_dirichlet_boundary_conditions(Λ⁰, 0.0)

    lhs_expressions, rhs_expressions = zero_form_biharmonic(wfi, dΩ)
    weak_form = Assemblers.WeakForm(lhs_expressions, rhs_expressions, wfi)
    A, b = Assemblers.assemble(weak_form, bc)
    sol = vec(A \ b)
    ϕ⁰ = Forms.build_form_field(Λ⁰, sol)

    ϕ⁰_exact = Forms.AnalyticalFormField(0, exact_solution, geometry, L"\phi_{exact}")

    dΩ_analysis = Quadrature.StandardQuadrature(
        canonical_qrule_analysis, Geometry.get_num_elements(geometry)
    )

    return Analysis.L2_norm(ϕ⁰ - ϕ⁰_exact, dΩ_analysis)
end
compute_error_biharmonic (generic function with 1 method)

To study the effect of introducing a different spacing of the elements in the grid, we can introduce a mapping. Here, we pick the mapping from the One-dimensional mapped geometry example. Do note that this will lead to a nearly singular system.

julia
const exponent = 3
mapping(ξ̂) = ξ̂^exponent
d_map(ξ̂) = exponent * ξ̂^(exponent - 1)
d2_map(ξ̂) = exponent * (exponent - 1) * ξ̂^(exponent - 2)
full_map = Geometry.Mapping(
    (1, 1), ξ̂ -> mapping.(ξ̂[:, 1]), ξ̂ -> d_map.(ξ̂[:, 1]), ξ̂ -> d2_map.(ξ̂[:, 1])
)
Mantis.Geometry.Mapping{1, 1, Main.var"#4#5", Main.var"#6#7", Main.var"#8#9"}(Main.var"#4#5"(), Main.var"#6#7"(), Main.var"#8#9"())

Then, we create a loop to build geometries with increasingly many elements and to compute the biharmonic equation with them.

julia
num_elements_study = [(4,), (8,), (16,), (32,), (64,)]
h = Vector{Float64}(undef, length(num_elements_study))
errors_cartesian = Vector{Float64}(undef, length(num_elements_study))
errors_mapped = Vector{Float64}(undef, length(num_elements_study))
for i in eachindex(num_elements_study)
    geo_cartesian = Geometry.create_cartesian_box(
        starting_point, box_size, num_elements_study[i]
    )
    geo_mapped = Geometry.MappedGeometry(geo_cartesian, full_map)

    space_cartesian = FunctionSpaces.create_bspline_space(
        starting_point, box_size, num_elements_study[i], p, k
    )
    space_curvilinear = FunctionSpaces.BSplineSpace(geo_cartesian, full_map, p[1], k[1])

    h[i] = box_size[1] / num_elements_study[i][1]
    errors_cartesian[i] = compute_error_biharmonic(geo_cartesian, space_cartesian)
    errors_mapped[i] = compute_error_biharmonic(geo_mapped, space_curvilinear)
end

We can then plot the results using GLMakie

julia
fig2 = Figure()
ax2 = Axis(
    fig2[1, 1]; xlabel=L"h", ylabel=L"||ϕ_h - ϕ_{exact}||_{L^2}", xscale=log10, yscale=log10
)

scatterlines!(
    ax2, h, errors_mapped; label="Mapped", color=:blue, marker=:rect, markersize=10
)
C = errors_mapped[3] / (h[3]^4)
lines!(ax2, h, C .* (h .^ 4); label=L"O(h^4)", linestyle=:dot, color=:black)

scatterlines!(
    ax2, h, errors_cartesian; label="Cartesian", color=:red, marker=:circle, markersize=10
)
C2 = errors_cartesian[3] / (h[3]^4)
lines!(ax2, h, C2 .* (h .^ 4); label=L"O(h^4)", linestyle=:dash, color=:black)

fig2[1, 2] = Legend(fig2, ax2)

For this setup, we expect the error to decrease with a rate of p+1, so 4. This is indeed confirmed by looking at the plot.

The 2D case

The 2D case works in essentially the same way. All we have to do is ensure that our inputs are now the 2D versions.

julia
starting_point_2D = (0.0, 0.0)
box_size_2D = (1.0, 1.0)
num_elements_2D = (8, 8)
p_2D = (3, 3)
k_2D = (2, 2)

geometry_2D = Geometry.create_cartesian_box(starting_point_2D, box_size_2D, num_elements_2D)
B_2D = FunctionSpaces.create_bspline_space(
    starting_point_2D, box_size_2D, num_elements_2D, p_2D, k_2D
)
Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}((Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]]), Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]])), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), CartesianIndices((11, 11)), LinearIndices((Base.OneTo(11), Base.OneTo(11))), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11], [12, 23, 34, 45, 56, 67, 78, 89, 100], [13, 14, 15, 16, 17, 18, 19, 20, 21, 24  …  98, 101, 102, 103, 104, 105, 106, 107, 108, 109], [22, 33, 44, 55, 66, 77, 88, 99, 110], [111], [112, 113, 114, 115, 116, 117, 118, 119, 120], [121]]])

Mantis works with forms, so we need to define the form space. In this case, we are working with 0-forms, so we define the form space as follows.

julia
Λ⁰_2D = Forms.FormSpace(0, B_2D, L"\phi_h")
Mantis.Forms.FormSpace{2, 0, Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}((Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]]), Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]])), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), CartesianIndices((11, 11)), LinearIndices((Base.OneTo(11), Base.OneTo(11))), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11], [12, 23, 34, 45, 56, 67, 78, 89, 100], [13, 14, 15, 16, 17, 18, 19, 20, 21, 24  …  98, 101, 102, 103, 104, 105, 106, 107, 108, 109], [22, 33, 44, 55, 66, 77, 88, 99, 110], [111], [112, 113, 114, 115, 116, 117, 118, 119, 120], [121]]]), L"$\phi_h$")

We define the weak form inputs. The weak form inputs contain the trial and test spaces, the forcing function, and the quadrature rule. We define the forcing function as a function of the coordinates. In this case, we define the forcing function as f0=64π4sin(2πx)sin(2πy).

julia
function forcing_function_2D(x::Matrix{Float64})
    return [@. 64.0 * pi^4 * sin(2.0 * pi * x[:, 1]) * sin(2.0 * pi * x[:, 2])]
end
f⁰_2D = Forms.AnalyticalFormField(0, forcing_function_2D, geometry_2D, L"f^0")
Mantis.Forms.AnalyticalFormField{2, 0, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, typeof(Main.forcing_function_2D), LaTeXStrings.LaTeXString}(Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), Main.forcing_function_2D, L"$f^0$")

The quadrature rule is defined as a tensor product rule of the degree of the B-spline space plus one. In this case, we define the quadrature rule as a Gauss-Legendre rule.

julia
canonical_qrule_2D = Quadrature.tensor_product_rule(p_2D .+ 1, Quadrature.gauss_legendre)
dΩ_2D = Quadrature.StandardQuadrature(
    canonical_qrule_2D, Geometry.get_num_elements(geometry_2D)
)
Mantis.Quadrature.StandardQuadrature{2, Mantis.Quadrature.CanonicalQuadratureRule{2, Mantis.Points.CartesianPoints{2, Vector{Float64}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}}(Mantis.Quadrature.CanonicalQuadratureRule{2, Mantis.Points.CartesianPoints{2, Vector{Float64}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(Mantis.Points.CartesianPoints{2, Vector{Float64}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}(([0.06943184420297371, 0.33000947820757187, 0.6699905217924281, 0.9305681557970262], [0.06943184420297371, 0.33000947820757187, 0.6699905217924281, 0.9305681557970262]), CartesianIndices((4, 4)), LinearIndices((Base.OneTo(4), Base.OneTo(4)))), [0.0302507483214005, 0.056712962962962965, 0.056712962962962965, 0.0302507483214005, 0.056712962962962965, 0.10632332575267359, 0.10632332575267359, 0.056712962962962965, 0.056712962962962965, 0.10632332575267359, 0.10632332575267359, 0.056712962962962965, 0.0302507483214005, 0.056712962962962965, 0.056712962962962965, 0.0302507483214005], "Tensor-product of (Gauss-Legendre, Gauss-Legendre) rules"), 64)

We define the weak form inputs as a WeakFormInputs object. The weak form inputs contain the trial and test spaces, and the forcing function. The trial and test spaces are the same in this case, which is the default.

julia
wfi_2D = Assemblers.WeakFormInputs(Λ⁰_2D, f⁰_2D)
Mantis.Assemblers.WeakFormInputs{2, Tuple{Mantis.Forms.FormSpace{2, 0, Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}}, Tuple{Mantis.Forms.FormSpace{2, 0, Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}}, Tuple{Mantis.Forms.AnalyticalFormField{2, 0, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, typeof(Main.forcing_function_2D), LaTeXStrings.LaTeXString}}}((Mantis.Forms.FormSpace{2, 0, Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}((Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]]), Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]])), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), CartesianIndices((11, 11)), LinearIndices((Base.OneTo(11), Base.OneTo(11))), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11], [12, 23, 34, 45, 56, 67, 78, 89, 100], [13, 14, 15, 16, 17, 18, 19, 20, 21, 24  …  98, 101, 102, 103, 104, 105, 106, 107, 108, 109], [22, 33, 44, 55, 66, 77, 88, 99, 110], [111], [112, 113, 114, 115, 116, 117, 118, 119, 120], [121]]]), L"$\phi_h$"),), (Mantis.Forms.FormSpace{2, 0, Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}((Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]]), Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]])), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), CartesianIndices((11, 11)), LinearIndices((Base.OneTo(11), Base.OneTo(11))), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11], [12, 23, 34, 45, 56, 67, 78, 89, 100], [13, 14, 15, 16, 17, 18, 19, 20, 21, 24  …  98, 101, 102, 103, 104, 105, 106, 107, 108, 109], [22, 33, 44, 55, 66, 77, 88, 99, 110], [111], [112, 113, 114, 115, 116, 117, 118, 119, 120], [121]]]), L"$\phi_h$"),), (Mantis.Forms.AnalyticalFormField{2, 0, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, typeof(Main.forcing_function_2D), LaTeXStrings.LaTeXString}(Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), Main.forcing_function_2D, L"$f^0$"),))

We can now assemble the linear system and solve it to obtain the solution. We define the Dirichlet boundary conditions using the appropriate helper function.

julia
bc_2D = Forms.set_dirichlet_boundary_conditions(Λ⁰_2D, 0.0)
Dict{Int64, Float64} with 40 entries:
  5   => 0.0
  56  => 0.0
  78  => 0.0
  55  => 0.0
  110 => 0.0
  114 => 0.0
  12  => 0.0
  8   => 0.0
  1   => 0.0
  23  => 0.0
  22  => 0.0
  111 => 0.0
  6   => 0.0
  67  => 0.0
  11  => 0.0
  45  => 0.0
  44  => 0.0
  9   => 0.0
  99  => 0.0
  ⋮   => ⋮

We assemble the linear system and solve it to obtain the solution. Note that we do not need to redefine the weak form itself; it was already written in a dimensio-independent way.

julia
lhs_expressions_2D, rhs_expressions_2D = zero_form_biharmonic(wfi_2D, dΩ_2D)
weak_form_2D = Assemblers.WeakForm(lhs_expressions_2D, rhs_expressions_2D, wfi_2D)
A_2D, b_2D = Assemblers.assemble(weak_form_2D, bc_2D)
sol_2D = vec(A_2D \ b_2D)
ϕ⁰_2D = Forms.build_form_field(Λ⁰_2D, sol_2D)
Mantis.Forms.FormField{2, 0, Mantis.Forms.FormSpace{2, 0, Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}, LaTeXStrings.LaTeXString}(Mantis.Forms.FormSpace{2, 0, Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}, LaTeXStrings.LaTeXString}(Mantis.FunctionSpaces.TensorProductSpace{2, 1, 1, 2, Tuple{Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}, Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}, CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}, Vector{Vector{Vector{Int64}}}}((Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]]), Mantis.FunctionSpaces.BSplineSpace{Mantis.FunctionSpaces.Bernstein, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Vector{Vector{Int64}}}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), Mantis.FunctionSpaces.KnotVector{Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}, Vector{Int64}}(Mantis.Geometry.CartesianGeometry{1, 1, 1, Tuple{Tuple{LinRange{Float64, Int64}}}, Tuple{CartesianIndices{1, Tuple{Base.OneTo{Int64}}}}, Tuple{LinearIndices{1, Tuple{Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9),),), (CartesianIndices((8,)),), (LinearIndices((Base.OneTo(8),)),)), 3, [4, 1, 1, 1, 1, 1, 1, 1, 4]), Mantis.FunctionSpaces.Bernstein(3), Mantis.FunctionSpaces.ExtractionOperator{1, Matrix{Float64}, UnitRange{Int64}, UnitRange{Int64}}([([1.0 0.0 0.0 0.0; 0.0 1.0 0.0 0.0; 0.0 0.5 0.5 0.0; 0.0 0.25 0.5833333333333334 0.16666666666666666],), ([0.25 0.5833333333333334 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.6666666666666667 0.16666666666666666],), ([0.16666666666666669 0.6666666666666667 0.16666666666666666 0.0; 0.0 0.6666666666666667 0.3333333333333333 0.0; 0.0 0.33333333333333337 0.6666666666666666 0.0; 0.0 0.16666666666666669 0.5833333333333333 0.25],), ([0.16666666666666669 0.5833333333333333 0.25 0.0; 0.0 0.5 0.5 0.0; 0.0 0.0 1.0 0.0; 0.0 0.0 0.0 1.0],)], Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}[Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(1:4, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(2:5, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(3:6, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(4:7, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(5:8, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(6:9, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(7:10, (1:4,)), Mantis.FunctionSpaces.Indices{1, UnitRange{Int64}, UnitRange{Int64}}(8:11, (1:4,))], 8, 11), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11]]])), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), Mantis.Geometry.CartesianGeometry{2, 2, 1, Tuple{Tuple{LinRange{Float64, Int64}, LinRange{Float64, Int64}}}, Tuple{CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}, Tuple{LinearIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}}}(((LinRange{Float64}(0.0, 1.0, 9), LinRange{Float64}(0.0, 1.0, 9)),), (CartesianIndices((8, 8)),), (LinearIndices((Base.OneTo(8), Base.OneTo(8))),)), CartesianIndices((11, 11)), LinearIndices((Base.OneTo(11), Base.OneTo(11))), [[[1], [2, 3, 4, 5, 6, 7, 8, 9, 10], [11], [12, 23, 34, 45, 56, 67, 78, 89, 100], [13, 14, 15, 16, 17, 18, 19, 20, 21, 24  …  98, 101, 102, 103, 104, 105, 106, 107, 108, 109], [22, 33, 44, 55, 66, 77, 88, 99, 110], [111], [112, 113, 114, 115, 116, 117, 118, 119, 120], [121]]]), L"$\phi_h$"), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], L"$\phi_h$")

Knowing the exact solutions, we can compute the L2-error.

julia
function exact_solution_2D(x::Matrix{Float64})
    return [@. sin(2.0 * pi * x[:, 1]) * sin(2.0 * pi * x[:, 2])]
end
ϕ⁰_exact_2D = Forms.AnalyticalFormField(0, exact_solution_2D, geometry_2D, L"\phi_{exact}")

canonical_qrule_2D_analysis = Quadrature.tensor_product_rule(
    3 .* p_2D .+ 1, Quadrature.gauss_legendre
)
dΩ_2D_analysis = Quadrature.StandardQuadrature(
    canonical_qrule_2D_analysis, Geometry.get_num_elements(geometry_2D)
)

println("L2 error: ", Analysis.L2_norm(ϕ⁰_2D - ϕ⁰_exact_2D, dΩ_2D_analysis))
L2 error: 0.0003543752765070691

We can also write the output to a VTK file that can be visualized using a VTK viewer, such as Paraview. Note that we export both the computed and exact solutions.

julia
output_filename_2D = "Biharmonic-0form-Homogeneous-Cartesian-$(length(p_2D))D"
Mantis.Plot.export_form_fields_to_vtk(
    (ϕ⁰_2D, ϕ⁰_exact_2D),
    output_filename_2D;
    output_directory_tree=["examples", "data", "output", "Biharmonic"],
)
Writing form 'phi_h' to file ...
Writing form 'phi_{exact}' to file ...

The 2D case on a more complicated geometry.

If we want to use a different geometry instead, we create a space on the new geometry and reuse all other code.

julia
mapping_2D_curv = Geometry.create_curvilinear_mapping(starting_point_2D, box_size_2D)
geometry_2D_curv = Geometry.MappedGeometry(geometry_2D, mapping_2D_curv)
B_2D_curv = FunctionSpaces.TensorProductSpace(
    FunctionSpaces.get_constituent_spaces(B_2D), Geometry.CartesianGeometry, mapping_2D_curv
)

Λ⁰_2D_curv = Forms.FormSpace(0, B_2D_curv, L"\phi_h")

f⁰_2D_curv = Forms.AnalyticalFormField(0, forcing_function_2D, geometry_2D_curv, L"f^0")

dΩ_2D_curv = Quadrature.StandardQuadrature(
    canonical_qrule_2D, Geometry.get_num_elements(geometry_2D_curv)
)

wfi_2D_curv = Assemblers.WeakFormInputs(Λ⁰_2D_curv, f⁰_2D_curv)

bc_2D_curv = Forms.set_dirichlet_boundary_conditions(Λ⁰_2D_curv, 0.0)

lhs_expressions_2D_curv, rhs_expressions_2D_curv = zero_form_biharmonic(
    wfi_2D_curv, dΩ_2D_curv
)
weak_form_2D_curv = Assemblers.WeakForm(
    lhs_expressions_2D_curv, rhs_expressions_2D_curv, wfi_2D_curv
)
A_2D_curv, b_2D_curv = Assemblers.assemble(weak_form_2D_curv, bc_2D_curv)
sol_2D_curv = vec(A_2D_curv \ b_2D_curv)
ϕ⁰_2D_curv = Forms.build_form_field(Λ⁰_2D_curv, sol_2D_curv)

ϕ⁰_exact_2D_curv = Forms.AnalyticalFormField(
    0, exact_solution_2D, geometry_2D_curv, L"\phi_{exact, curv}"
)

dΩ_2D_analysis_curv = Quadrature.StandardQuadrature(
    canonical_qrule_2D_analysis, Geometry.get_num_elements(geometry_2D_curv)
)

println("L2 error: ", Analysis.L2_norm(ϕ⁰_2D_curv - ϕ⁰_exact_2D_curv, dΩ_2D_analysis_curv))

output_filename_2D_curv = "Biharmonic-0form-Homogeneous-Curvilinear-$(length(p_2D))D"
Mantis.Plot.export_form_fields_to_vtk(
    (ϕ⁰_2D_curv, ϕ⁰_exact_2D_curv),
    output_filename_2D_curv;
    output_directory_tree=["examples", "data", "output", "Biharmonic"],
)
L2 error: 0.00421557327021206
Writing form 'phi_h' to file ...
Writing form 'phi_{exact, curv}' to file ...

Convergence studies for the 2D case.

One way to obtain some confirmation that these results are what we expect, we can compute the error on finer and finer meshes. To start, we create a function that will create all objects based on the geometry that we provide, and that will compute the error using the given geometry.

julia
function compute_error_biharmonic_2D(geometry, function_space)
    Λ⁰_2D = Forms.FormSpace(0, function_space, "ϕ")

    f⁰_2D = Forms.AnalyticalFormField(0, forcing_function_2D, geometry, "f⁰")

    dΩ_2D = Quadrature.StandardQuadrature(
        canonical_qrule_2D, Geometry.get_num_elements(geometry)
    )

    wfi_2D = Assemblers.WeakFormInputs(Λ⁰_2D, f⁰_2D)

    bc_2D = Forms.set_dirichlet_boundary_conditions(Λ⁰_2D, 0.0)

    lhs_expressions_2D, rhs_expressions_2D = zero_form_biharmonic(wfi_2D, dΩ_2D)
    weak_form_2D = Assemblers.WeakForm(lhs_expressions_2D, rhs_expressions_2D, wfi_2D)
    A_2D, b_2D = Assemblers.assemble(weak_form_2D, bc_2D)
    sol_2D = vec(A_2D \ b_2D)
    ϕ⁰_2D = Forms.build_form_field(Λ⁰_2D, sol_2D)

    ϕ⁰_exact_2D = Forms.AnalyticalFormField(0, exact_solution_2D, geometry, "ϕ_exact")

    dΩ_2D_analysis = Quadrature.StandardQuadrature(
        canonical_qrule_2D_analysis, Geometry.get_num_elements(geometry)
    )

    return Analysis.L2_norm(ϕ⁰_2D - ϕ⁰_exact_2D, dΩ_2D_analysis)
end
compute_error_biharmonic_2D (generic function with 1 method)

Then, we create a loop to build geometries with increasingly many elements and to compute the biharmonic equation with them.

julia
num_elements_study_2D = [(4, 4), (8, 8), (16, 16), (32, 32), (64, 64)]
h_2D = Vector{Float64}(undef, length(num_elements_study_2D))
errors_cartesian_2D = Vector{Float64}(undef, length(num_elements_study_2D))
errors_curvilinear_2D = Vector{Float64}(undef, length(num_elements_study_2D))
for i in eachindex(num_elements_study_2D)
    geo_cartesian = Geometry.create_cartesian_box(
        starting_point_2D, box_size_2D, num_elements_study_2D[i]
    )
    curved_mapping = Geometry.create_curvilinear_mapping(starting_point_2D, box_size_2D)
    geo_curvilinear = Geometry.MappedGeometry(geo_cartesian, curved_mapping)

    space_cartesian = FunctionSpaces.create_bspline_space(
        starting_point_2D, box_size_2D, num_elements_study_2D[i], p_2D, k_2D
    )
    space_curvilinear = FunctionSpaces.TensorProductSpace(
        FunctionSpaces.get_constituent_spaces(space_cartesian),
        Geometry.CartesianGeometry,
        curved_mapping,
    )

    h_2D[i] = box_size_2D[1] / num_elements_study_2D[i][1]
    errors_cartesian_2D[i] = compute_error_biharmonic_2D(geo_cartesian, space_cartesian)
    errors_curvilinear_2D[i] = compute_error_biharmonic_2D(
        geo_curvilinear, space_curvilinear
    )
end

We can then plot the results using GLMakie again.

julia
fig3 = Figure()
ax3 = Axis(
    fig3[1, 1]; xlabel=L"h", ylabel=L"||ϕ_h - ϕ_{exact}||_{L^2}", xscale=log10, yscale=log10
)

scatterlines!(
    ax3,
    h_2D,
    errors_curvilinear_2D;
    label="Curvilinear",
    color=:blue,
    marker=:rect,
    markersize=10,
)
C = errors_curvilinear_2D[3] / (h[3]^4)
lines!(ax3, h_2D, C .* (h_2D .^ 4); label=L"O(h^4)", linestyle=:dot, color=:black)

scatterlines!(
    ax3,
    h_2D,
    errors_cartesian_2D;
    label="Cartesian",
    color=:red,
    marker=:circle,
    markersize=10,
)
C2 = errors_cartesian_2D[3] / (h[3]^4)
lines!(ax3, h_2D, C2 .* (h_2D .^ 4); label=L"O(h^4)", linestyle=:dash, color=:black)

fig3[1, 2] = Legend(fig3, ax3)

For this setup, we expect the error to decrease with a rate of p+1, so 4. This is indeed confirmed by looking at the plot.


This page was generated using Literate.jl.