Skip to content

Forms

As explained on the differential form theory page, differential forms provide an elegant and general framework to deal with the discretisation of PDEs. One of the most distinguishing features of Mantis is its ability to work with these differential forms. The Forms module provides all the required tools to use differential forms in Mantis.

What is a differential form in Mantis?

The top-level type within the Forms module is the AbstractForm{manifold_dim, form_rank, expression_rank} type. Every expression involving forms (see Creating Forms) and operations on forms (see Operations on Forms) will be an AbstractForm. There are two exceptions to this rule. The first exception is an operation that returns a real value, such as an integral, see Operators returning a real value. The second exception is an operation that returns a vector, such as the sharp, see Operators returning a vector

Mantis.Forms.AbstractForm Type
julia
AbstractForm{manifold_dim, form_rank, expression_rank}

Supertype for all form expressions representing differential forms.

Type parameters

  • manifold_dim: Dimension of the manifold on which the form lives. This will always be inherited from the underlying function space or geometry.

  • form_rank: The rank of the form, i.e. 0-form, 1-form, 2-form, etc.

  • expression_rank: The number of bases present in an expression. Is 0 if no bases are present, 1 for a single basis, and 2 for two bases. Expression ranks larger than 2 are not allowed.

Non-zero expression rank does not mean that the full expression has a basis.

If expression_rank is larger than 0, this means that the expression acts on at least one basis, but not necessarily that there is a basis for the total expression. For example, applying the exterior derivative to a FormSpace will result in a form with expression rank 1. However, while the FormSpace has a basis, this does not generate a basis for the exterior derivative (only a spanning set).

source

There are two aliases for AbstractForm, which are AbstractFormField and AbstractFormSpace.

Mantis.Forms.AbstractFormField Type
julia
AbstractFormField{manifold_dim, form_rank}

Alias for an AbstractForm with expression rank 0, that is, a form expression without a basis. See AbstractForm for more details.

source
Mantis.Forms.AbstractFormSpace Type
julia
AbstractFormSpace{manifold_dim, form_rank}

Alias for an AbstractForm with expression rank 1, that is, a form expression involving one basis. See AbstractForm for more details.

source

Every AbstractForm has three type parameters which say something about the form. You can always call the following three methods on any AbstractForm to get these type parameters.

Mantis.Forms.get_manifold_dim Function
julia
get_manifold_dim(::AbstractForm{manifold_dim}) where {manifold_dim}

Returns the manifold_dim of the given form.

source
Mantis.Forms.get_form_rank Function
julia
get_form_rank(
    ::AbstractForm{manifold_dim, form_rank}
) where {manifold_dim, form_rank}

Returns the form_rank of the given form.

source
Mantis.Forms.get_expression_rank Function
julia
get_expression_rank(
    ::AbstractForm{manifold_dim, form_rank, expression_rank}
) where {manifold_dim, form_rank, expression_rank}

Returns the expression_rank of the given form.

source

The above abstract types are used in function signatures, but cannot be instantiated. The concrete types that can be instantiated are discussed next.

Creating Forms

You can create two main types of Forms: FormSpaces and FormFields.

FormSpaces

A FormSpace allows you to distinguish between functions and forms. A FormSpace is build on top of a FunctionSpaces.AbstractFESpace, which acts as its basis. However, it is the FormSpace that dictates the behaviour of the form.

Mantis.Forms.FormSpace Type
julia
FormSpace{manifold_dim, form_rank, F, L} <: AbstractFormSpace{manifold_dim, form_rank}

Differential forms with a basis.

A FormSpace relies on a FunctionSpaces.AbstractFESpace to represent a differential form with the function space as basis. While the function space provides a basis, the form_rank of the FormSpace will dictate the behaviour of the form (i.e. is it a 0-form, 1-form, etc.) and thus its properties.

Constructors

  • FormSpace(form_rank::Int, fem_space::F, label::AbstractString): General constructor.

Example

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (4, 4), (3, 3), (2,2));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form");  # 0-form with B as basis.

julia> Λ²ₕ = Forms.FormSpace(2, B, "2-form");  # 2-form with B as basis.

Fields

  • fem_space::F: The finite element space FunctionSpaces.AbstractFESpace used as basis for this form. From this space, the manifold_dim and geometry are inherited. Additionally, the num_components of the function space must be consistent with the provided form_rank and the manifold_dim, i.e., a real-valued 0-form has 1 component (in any dimension), a 1-form in 3D has 3 components, etc.

  • label::AbstractString: Label for the form space. This will be used in export and plotting functions to easily identify the form.

Type parameters

source

As explained on the differential form theory page, differential forms are more expressive than functions. By using a FormSpace, this expressiveness becomes available within your code. For example, if we start by creating a simple 2D FunctionSpaces.BSplineSpace using the helper FunctionSpaces.create_bspline_space (on a unit square with 4×4 elements, degree 3 and regularity 2),

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (4, 4), (3, 3), (2, 2))
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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 3, [4, 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.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,))], 4, 7), [[[1], [2, 3, 4, 5, 6], [7]]]), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 3, [4, 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.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,))], 4, 7), [[[1], [2, 3, 4, 5, 6], [7]]])), 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, 5), LinRange{Float64}(0.0, 1.0, 5)),), (CartesianIndices((4, 4)),), (LinearIndices((Base.OneTo(4), Base.OneTo(4))),)), 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, 5), LinRange{Float64}(0.0, 1.0, 5)),), (CartesianIndices((4, 4)),), (LinearIndices((Base.OneTo(4), Base.OneTo(4))),)), CartesianIndices((7, 7)), LinearIndices((Base.OneTo(7), Base.OneTo(7))), [[[1], [2, 3, 4, 5, 6], [7], [8, 15, 22, 29, 36], [9, 10, 11, 12, 13, 16, 17, 18, 19, 20  30, 31, 32, 33, 34, 37, 38, 39, 40, 41], [14, 21, 28, 35, 42], [43], [44, 45, 46, 47, 48], [49]]])

we can use this function space to create two different spaces: one for a 0-form Λh0 and one for a 2-form Λh2 (a top form in 2D).

julia
julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form")
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}}}}, String}(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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 3, [4, 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.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,))], 4, 7), [[[1], [2, 3, 4, 5, 6], [7]]]), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 3, [4, 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.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,))], 4, 7), [[[1], [2, 3, 4, 5, 6], [7]]])), 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, 5), LinRange{Float64}(0.0, 1.0, 5)),), (CartesianIndices((4, 4)),), (LinearIndices((Base.OneTo(4), Base.OneTo(4))),)), 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, 5), LinRange{Float64}(0.0, 1.0, 5)),), (CartesianIndices((4, 4)),), (LinearIndices((Base.OneTo(4), Base.OneTo(4))),)), CartesianIndices((7, 7)), LinearIndices((Base.OneTo(7), Base.OneTo(7))), [[[1], [2, 3, 4, 5, 6], [7], [8, 15, 22, 29, 36], [9, 10, 11, 12, 13, 16, 17, 18, 19, 20  30, 31, 32, 33, 34, 37, 38, 39, 40, 41], [14, 21, 28, 35, 42], [43], [44, 45, 46, 47, 48], [49]]]), "0-form")

julia> Λ²ₕ = Forms.FormSpace(2, B, "2-form")
FormSpace{2, 2, 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}}}}, String}(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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 3, [4, 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.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,))], 4, 7), [[[1], [2, 3, 4, 5, 6], [7]]]), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 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, 5),),), (CartesianIndices((4,)),), (LinearIndices((Base.OneTo(4),)),)), 3, [4, 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.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,))], 4, 7), [[[1], [2, 3, 4, 5, 6], [7]]])), 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, 5), LinRange{Float64}(0.0, 1.0, 5)),), (CartesianIndices((4, 4)),), (LinearIndices((Base.OneTo(4), Base.OneTo(4))),)), 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, 5), LinRange{Float64}(0.0, 1.0, 5)),), (CartesianIndices((4, 4)),), (LinearIndices((Base.OneTo(4), Base.OneTo(4))),)), CartesianIndices((7, 7)), LinearIndices((Base.OneTo(7), Base.OneTo(7))), [[[1], [2, 3, 4, 5, 6], [7], [8, 15, 22, 29, 36], [9, 10, 11, 12, 13, 16, 17, 18, 19, 20  30, 31, 32, 33, 34, 37, 38, 39, 40, 41], [14, 21, 28, 35, 42], [43], [44, 45, 46, 47, 48], [49]]]), "2-form")

These two forms have the same basis B, but have different transformation properties. This will result in the use of different pullbacks (see How FormSpaces are evaluated on how that is reflected in the implementation), and on the operations that you can apply to these forms (see Operations on Forms).

ConstantFormSpaces

Next to the conventional FormSpace, Mantis also provides a ConstantFormSpace. A ConstantFormSpace can be instantiated as a 0- or manifold_dim-form (so a top form), and will always evaluate to 1. This is often useful as Lagrange multiplier, where a ConstantFormSpace can act as the form basis for the real numbers R. Note that, compared to the FormSpaces, the ConstantFormSpace does not require a function space but only the geometry.

Mantis.Forms.ConstantFormSpace Type
julia
ConstantFormSpace{manifold_dim, form_rank, G, L} <:
AbstractFormSpace{manifold_dim, form_rank}

Constant scalar differential form.

This can, for instance, be used as a Lagrange multiplier enforcing a zero-average constraint on another differential form.

Constructors

  • ConstantFormSpace(form_rank::Int, geometry::G, label::L): Generic constructor.

Example

julia
julia> using Mantis

julia> geometry = Geometry.create_cartesian_box((0.0, 0.0), (1.0, 1.0), (4, 4));

julia> Λ⁰ₕ = Forms.ConstantFormSpace(0, geometry, "0-form");  # 0-form constant on geometry.

julia> Λ²ₕ = Forms.ConstantFormSpace(2, geometry, "2-form");  # 2-form constant on geometry.

Fields

  • geometry::G: The geometry Geometry.AbstractGeometry on which the ConstantFormSpace should be created. The manifold_dim will be inherited from this geometry.

  • label::L: Label for the constant form space. This will be used in export and plotting functions to easily identify the form.

Type parameters

  • manifold_dim: Dimension of the manifold.

  • form_rank: Rank of the differential form.

  • G: Type of the geometry (a Geometry.AbstractGeometry).

  • L: Type of the label (an AbstractString).

source

FormFields

A FormField can be used to represent a differential form field (a combination of a basis with coefficients) or forms without an underlying basis. The former is, for example, useful to represent solution fields or right hand sides, while the latter can be used with analytical expressions to, for example, represent exact solutions or forcings.

Mantis.Forms.FormField Type
julia
FormField{manifold_dim, form_rank, FS, L} <: AbstractFormField{manifold_dim, form_rank}

Represents a differential form field, i.e., a differential form with coefficients and form_space. Note that this is considered a field, and thus to not have a basis.

Constructors

  • FormField( form_space::FS, coefficients::Vector{Float64}=zeros(get_num_basis(form_space)), label::AbstractString=get_label(form_space), ): General constructor for form fields. Note that the coefficients default to zero if not given, and that the label also has a default.

Example

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (4, 4), (3, 3), (2,2));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form");  # 0-form space with B as basis.

julia> coefficients = ones(Forms.get_num_basis(Λ⁰ₕ)); # Create some coefficients

julia> α⁰ₕ = Forms.FormField(Λ⁰ₕ, coefficients, "0-form-field");  # 0-form field with Λ⁰ₕ as basis and all ones as coefficients.

julia> β⁰ₕ = Forms.FormField(Λ⁰ₕ);  # 0-form field with Λ⁰ₕ as basis and all zero coefficients.

Fields

  • form_space::FS: The form space associated with this field.

  • coefficients::Vector{Float64}: Coefficients of the form field.

  • label::AbstractString: Label for the form field.

Type parameters

  • manifold_dim: Dimension of the manifold.

  • form_rank: Rank of the differential form.

  • FS: Type of the form space.

  • L: Type of the label (an AbstractString).

source
Mantis.Forms.AnalyticalFormField Type
julia
AnalyticalFormField{manifold_dim, form_rank, G, E, L} <:
AbstractFormField{manifold_dim, form_rank}

Represents an analytical differential form field.

The analytical expression should be a Julia function defining the form in the physical domain. See the documentation on the Geometry module for the difference between the domains used in Mantis.

Constructors

  • AnalyticalFormField(form_rank::Int, expression::E, geometry::G, label::AbstractString): General constructor for analytical form fields.

Example

julia
julia> using Mantis

julia> function my_form_expression(input)
           x = input[:, 1]
           y = input[:, 2]
           return [@. sin(x) * sin(y)]
       end;

julia> geometry = Geometry.create_cartesian_box((0.0, 0.0), (1.0, 1.0), (4, 4));

julia> α⁰ₕ = Forms.AnalyticalFormField(0, my_form_expression, geometry, "Analytical 0-form");

julia> α²ₕ = Forms.AnalyticalFormField(2, my_form_expression, geometry, "Analytical 2-form");

Fields

  • geometry::G: The geometry associated with this field.

  • expression::E: The expression defining the form field.

  • label::AbstractString: Label for the form field.

Type parameters

  • manifold_dim, form_rank, expression_rank: See AbstractForm for the details.

  • G: Type of the geometry.

  • E: Type of the expression.

  • L: Type of the label (an AbstractString).

source

Since a FormField has coefficients and an AnalyticalFormField has an analytical expression, you can inspect them using the following functions.

Mantis.Forms.get_coefficients Function
julia
get_coefficients(form_field::FormField)

Returns the coefficients of the form field.

Arguments

  • form_field::FormField: The form field.

Returns

  • Vector{Float64}: The coefficients of the form field.
source
Mantis.Forms.get_num_coefficients Function
julia
get_num_coefficients(form_field::FormField)

Returns the number of coefficients of the form field.

Arguments

  • form_field::FormField: The form field.

Returns

  • Int: The number of coefficients (dofs) of the form field.
source
Mantis.Forms.get_expression Function
julia
get_expression(form_field::AnalyticalFormField)

Returns the expression of the analytical form field. Remember that the expression is defined in the physical domain. See AnalyticalFormField for the details.

Arguments

  • form_field::AnalyticalFormField: The analytical form field.

Returns

  • <:Function: The expression of the analytical form field.
source

Evaluating Forms

As with any object in Mantis, evaluating a form is a matter of calling the evaluate-function:

Mantis.Forms.evaluate Method
julia
evaluate(
    form::AbstractForm{manifold_dim},
    element_id::Int,
    xi::Points.AbstractPoints{manifold_dim},
) where {manifold_dim}

Evaluate any form (expression) on the given element_id at the given points xi.

Evaluation in the canonical domain.

The evaluation of a form (expression) is always done in the canonical domain, not the physical domain. See the documentation on the Geometry module for more details on these domains.

Arguments

  • form::AbstractForm{manifold_dim}: The differential form space.

  • element_id::Int: The global element id. See Geometry for the details.

  • xi::Points.AbstractPoints{manifold_dim}: The points in the canonical domain at which to evaluate the form. See Geometry and Points for more details on the canonical domain and point structure.

Returns

  • Vector{Array{Float64, expression_rank+1}}: Vector of length equal to the number of components of the form, where each entry is a Array{Float64, expression_rank+1} (so, a Vector for AbstractFormFields and a Matrix for AbstractFormSpaces) of size (num_evaluation_points,), (num_evaluation_points, num_basis_functions_on_element), respectively. For expressions involving two forms (such as the wedge), the entries will be of type Array{Float64, 1 + expression_rank_1 + expression_rank_2}

  • form_basis_indices::Vector{Vector{Int}}: The indices of the underlying function space that have been evaluated (the inner vector), per basis (the outer vector). For AbstractFormFields (things without a basis), this will always be [[1]].

Examples

Evaluating a 0-form:

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form");  # 0-form with B as basis.

julia> xi = Points.CartesianPoints((LinRange(0.0, 1.0, 2), LinRange(0.0, 1.0, 3)));

julia> Forms.evaluate(Λ⁰ₕ, 1, xi)
([[1.0 0.0 0.0 0.0; 0.0 0.5 0.0 0.0;  ; 0.0 0.0 0.0 0.0; 0.0 0.0 0.25 0.25]], [[1, 2, 3, 5, 6, 7, 9, 10, 11]])

Evaluating a 2-form in 2D (a top form). Note how the result is scaled by the pullback to the canonical domain.

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ²ₕ = Forms.FormSpace(2, B, "2-form");  # 2-form with B as basis.

julia> xi = Points.CartesianPoints((LinRange(0.0, 1.0, 2), LinRange(0.0, 1.0, 3)));

julia> Forms.evaluate(Λ²ₕ, 1, xi)
([[0.25 0.0 0.0 0.0; 0.0 0.125 0.0 0.0;  ; 0.0 0.0 0.0 0.0; 0.0 0.0 0.0625 0.0625]], [[1, 2, 3, 5, 6, 7, 9, 10, 11]])
source

Internals: How a FormSpace is evaluated

Internal behaviour

We explain how a FormSpace is evaluated. However, this is considered an implementational detail.

The evaluation of a FormSpace happens in the canonical domain and is done in two steps. Firstly, the underlying function space is evaluated. This evaluation gives us the function values and the basis indices. Secondly, the function space evaluation is pulled-back to the canonical domain. What this pullback looks like is dictated by the form_rank. The evaluation then returns the pulled-back values and the basis indices (the indices for the form are the same as for the function space). This behaviour is encoded using the following two internal functions.

Mantis.Forms._evaluate_form_in_canonical_coordinates Function
julia
_evaluate_form_in_canonical_coordinates(
    form_space::FormSpace{manifold_dim, form_rank},
    element_idx::Int,
    xi::Points.AbstractPoints{manifold_dim},
    nderivatives::Int,
) where {manifold_dim, form_rank}

Evaluate the form basis functions and their arbitrary derivatives in canonical coordinates.

Arguments

  • form_space::FormSpace{manifold_dim, form_rank}: The form space.

  • element_idx::Int: Index of the element where the evaluation is performed.

  • xi::Points.AbstractPoints{manifold_dim}: Canonical points for evaluation.

Returns

  • local_form_basis::Vector{Vector{Vector{Matrix{Float64}}}}: The basis functions evaluated at the canonical coordinates of the element.

  • ::Vector{Vector{Int}}: The basis functions evaluated at the canonical coordinates of the element.

source
Mantis.Forms._pullback_to_canonical_coordinates Function
julia
_pullback_to_canonical_coordinates(
    geometry::Geometry.AbstractGeometry{manifold_dim},
    form_evaluations::Vector{Vector{Vector{Matrix{Float64}}}},
    element_idx::Int,
    form_rank::Int,
) where {manifold_dim}

Pullback the basis functions to the canonical coordinates of the element.

Arguments

  • geometry::Geometry.AbstractGeometry{manifold_dim}: The geometry of the form space.

  • form_evaluations::Vector{Vector{Vector{Matrix{Float64}}}}: The basis functions evaluated at the parametric coordinates.

  • element_idx::Int: Index of the element to evaluate.

  • form_rank::Int: Rank of the form.

Returns

  • form_evaluations::Vector{Vector{Vector{Matrix{Float64}}}}: The form evaluations pulled-back to canonical coordinates.
source

Internals: How an AnalyticalFormField is evaluated

Internal behaviour

We explain how an AnalyticalFormField is evaluated. However, this is considered an implementational detail.

A user has to define the expression used in the AnalyticalFormField in the physical domain. However, in Mantis, forms are always evaluated in the canonical domain. This means that any AnalyticalFormField must always be pulled-back before the result can be used in other computations. These pull-backs are determined by the form_rank of the AnalyticalFormField.

Mantis.Forms._evaluate Method
julia
_evaluate(
    form_field::AnalyticalFormField{manifold_dim, form_rank},
    element_idx::Int,
    xi::Points.AbstractPoints{manifold_dim},
) where {manifold_dim}

Internal function to evaluate an analytical form field, by first pulling back the form to the canonical domain. The used pull-back is dictated by the form_rank.

Arguments

Returns

source

Operations on Forms

Now that we know how to create forms, we can look into the operators that we can use on these form objects. We first look at operators that map forms to forms.

Exterior Derivative

The exterior derivative is a generalised derivative, which maps k-forms to k+1 forms, and is known by its alias d. The exterior derivative is a metric-independent operation. In R3, the exterior derivative embodies the well-known gradient (when applied to 0-forms), curl (when applied to 1-forms), and divergence (when applied to 2-forms).

Mantis.Forms.ExteriorDerivative Type
julia
ExteriorDerivative{manifold_dim, form_rank, expression_rank, F} <:
AbstractForm{manifold_dim, form_rank, expression_rank}

Represents the exterior derivative of an AbstractForm.

The manifold_dim and expression_rank are inherited from the form to which the exterior derivative is applied. The form_rank of the exterior derivative is the form rank of the input form plus one.

Formally, applying the exterior derivative to a volume form (the rank of the form equals the dimension of the manifold) returns zero. However, in Mantis, the constructor throws an error instead.

Constructors

  • ExteriorDerivative(form::F): General constructor for any AbstractForm.

Examples

Creating the exterior derivative of a 0-form:

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form");  # 0-form space with B as basis.

julia> dΛ⁰ₕ = d(Λ⁰ₕ);  # Note that dΛ⁰ₕ is a 1-form.

julia> isa(dΛ⁰ₕ, Forms.ExteriorDerivative{2, 1, 1})
true

Fields

  • form::F: The form to which the exterior derivative is applied. Note that the form rank of this form is one lower than the form_rank of the exterior derivative.

  • label::L: The exterior derivative label. This is a concatenation of "d" with the label of form.

Type parameters

  • manifold_dim, form_rank, expression_rank: See AbstractForm for the details.

  • F <: Forms.AbstractForm{manifold_dim, form_rank - 1, expression_rank}: The type of form.

  • L <: AbstractString: The type of the label. Since a "d" is added to the label, this type may differ from the label type of the underlying form.

source
Mantis.Forms.d Type
julia
d

Symbolic wrapper for the exterior derivative operator. See ExteriorDerivative for the details.

source

Wedge

The wedge-operator is a generalisation of products. It takes in two forms (say a k-form and an l-form) and produces another form (a k+l-form).

Mantis.Forms.Wedge Type
julia
Wedge{manifold_dim, form_rank, expression_rank, F1, F2, L} <:
AbstractForm{manifold_dim, form_rank, expression_rank}

Represents the wedge between two differential forms.

The manifold_dim of the Wedge is inherited from the input forms (which have the same manifold_dim). The form_rank and expression_rank of the Wedge are the sums of the respective ranks of the input forms. If the expression_rank of the Wedge would become larger than 2, an error is thrown.

Constructors

  • Wedge(form_1::F1, form_2::F2): General constructor.

Examples

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form");  # 0-form space with B as basis.

julia> Λ²ₕ = Forms.FormSpace(2, B, "2-form");  # 2-form space with B as basis.

julia> wedged = Λ⁰ₕ  Λ²ₕ;  # Wedge operator between the two spaces.

julia> isa(wedged, Forms.Wedge{2, 2, 2})
true

Fields

  • form_1::F1: The first form.

  • form_2::F2: The second form.

  • label::L: A label for the wedge.

Type parameters

  • manifold_dim, form_rank, expression_rank: See AbstractForm for the details.

  • F1 <: Forms.AbstractForm: The type of form_1.

  • F2 <: Forms.AbstractForm: The type of form_2.

  • L <: AbstractString: The type of the label. Since a "∧" is added to the label, this type may differ from the label type of the underlying form.

source
Mantis.Forms.:∧ Type
julia

Symbolic wrapper for the wedge operator. The unicode character command is \wedge. See Wedge for the details.

source

Hodge

The Hodge-star operator is a metric-dependent operator, which maps k-forms to manifold_dim-k forms.

Mantis.Forms.Hodge Type
julia
Hodge{manifold_dim, form_rank, expression_rank, F} <:
AbstractForm{manifold_dim, form_rank, expression_rank}

Represents the hodge star of an AbstractForm.

The manifold_dim of the Hodge is inherited from the input form, while the form_rank is the manifold_dim minus the form rank of the input form.

Inner Constructors

  • Hodge(form::F): General constructor.

Examples

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form");  # 0-form space with B as basis.

julia> Λ²ₕ = Forms.FormSpace(2, B, "2-form");  # 2-form space with B as basis.

julia> starΛ⁰ₕ =(Λ⁰ₕ);

julia> isa(starΛ⁰ₕ, Forms.Hodge{2, 2, 1})
true

julia> ★Λ²ₕ =(Λ²ₕ);

julia> isa(★Λ²ₕ, Forms.Hodge{2, 0, 1})
true

Fields

  • form::F: The form to which the hodge star is applied.

  • label::L: The hodge star label. This is a concatenation of "★" with the label of form.

Type parameters

  • manifold_dim, form_rank, expression_rank: See AbstractForm for the details.

  • F <: Forms.AbstractForm{manifold_dim, manifold_dim-form_rank, expression_rank}: The type of form.

  • L <: AbstractString: The type of the label. Since a "★" is added to the label, this type may differ from the label type of the underlying form.

source
Mantis.Forms.★ Type
julia

Symbolic wrapper for the hodge star operator. The unicode character command is \bigstar. See Hodge for the details.

source

Codifferential

The codifferential, often denoted d or δ, is a differential operator mapping k-forms to k1-forms. On manifolds without boundaries, it is the L2-adjoint of the exterior derivative. That is, (αk1,δβk)=(dαk1,βk), where (,) is an L2 inner-product.

Mantis.Forms.CoDifferential Type
julia
CoDifferential{manifold_dim, form_rank, expression_rank, F, L} <:
AbstractForm{manifold_dim, form_rank, expression_rank}

Represents the codifferential of an AbstractForm.

The manifold_dim of the CoDifferential is inherited from the input form, while the form_rank is the form rank of the input form minus 1.

Constructors

  • CoDifferential(form::F): General constructor.

Examples

julia
julia> using Mantis

julia> Bx = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 1), (1, 0));

julia> By = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (1, 2), (0, 1));

julia> B = FunctionSpaces.DirectSumSpace((Bx, By)); # A FunctionSpace with 2 components.

julia> Λ¹ₕ = Forms.FormSpace(1, B, "1-form");  # 1-form space with B as basis.

julia> δΛ¹ₕ = δ(Λ¹ₕ);

julia> isa(δΛ¹ₕ, Forms.CoDifferential{2, 0, 1})
true

Fields

  • form::F: The form to which the codifferential is applied.

  • label::L: The codifferential label. Adds "δ" to the label of form.

Type parameters

  • manifold_dim, form_rank, expression_rank: See AbstractForm for the details.

  • F <: Forms.AbstractForm{manifold_dim, form_rank+1, expression_rank}: The type of form.

  • L <: AbstractString: The type of the label. Since a "δ" is added to the label, this type may differ from the label type of the underlying form.

source
Mantis.Forms.dstar Type
julia
dstar

Symbolic wrapper for the codifferential. See CoDifferential for the details.

source
Mantis.Forms.δ Type
julia
δ

Symbolic wrapper for the codifferential. The unicode character command is \delta. See CoDifferential for the details.

source

Algebraic

The algebraic operators allow you to use operators like addition, subtraction, and multiplication by a scalar on any form. These operations are implemented as UnaryFormTransformation or BinaryFormTransformation, depending on whether the operator is a unary or binary operator, respectively.

Mantis.Forms.UnaryFormTransformation Type
julia
UnaryFormTransformation{manifold_dim, form_rank, expression_rank, F, T, L} <:
AbstractForm{manifold_dim, form_rank, expression_rank}

Unary, algebraic transformation of a differential form expression.

Constructors

  • UnaryFormTransformation(form::F, transformation::T, label::String): General constructor.

  • Base.:-(form::AbstractForm): Point-wise additive inverse of a form.

  • Base.:*(factor::Number, form::AbstractForm): Point-wise multiplication of a form with a number.

  • Base.:*(form::AbstractForm, factor::Number): Point-wise multiplication of a form with a number.

Fields

  • form::F: The differential form expression to which the transformation is applied.

  • transformation::T: The transformation function to apply to the form.

  • label::L: The label to associate with the resulting transformed form.

Type parameters

  • manifold_dim, form_rank, expression_rank: See AbstractForm for the details.

  • F <: AbstractForm{manifold_dim, form_rank, expression_rank}: The type of the original form expression .

  • T <: Function: The type of the algebraic transformation.

  • L <: AbstractString: The type of the label.

source
Mantis.Forms.BinaryFormTransformation Type
julia
BinaryFormTransformation{manifold_dim, form_rank, expression_rank, F1, F2, T, L} <:
AbstractForm{manifold_dim, form_rank, expression_rank}

Binary, algebraic transformation acting on two differential form expressions.

Compatibility of forms

When using these binary operations, you have to ensure that the operation makes sense for the given input. This is not checked!

Constructors

  • BinaryFormTransformation(form_1::F1, form_2::F2, transformation::T, label::AbstractString): General constructor.

  • Base.:+(form_1::AbstractForm, form_2::AbstractForm): Point-wise sum of two forms.

  • Base.:-(form_1::AbstractForm, form_2::AbstractForm): Point-wise difference of two froms.

  • Base.:*(form_1::AbstractForm, form_2::AbstractForm): Point-wise product of two forms.

Examples

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form 1");  # 0-form space with B as basis.

julia> sum_example = Λ⁰ₕ + Λ⁰ₕ;

julia> isa(sum_example, Forms.BinaryFormTransformation{2, 0, 1})
true

Fields

  • form_1::F1: The first differential form expression.

  • form_2::F2: The second differential form expression.

  • transformation::T: The transformation to apply to the differential forms.

  • label::L: The label to associate to the resulting differential form.

Type parameters

  • manifold_dim, form_rank, expression_rank: See AbstractForm for the details.

  • F1 <: AbstractForm{manifold_dim, form_rank, expression_rank}: The type of the first form expression.

  • F2 <: AbstractForm{manifold_dim, form_rank, expression_rank}: The type of the second form expression.

  • T <: Function: The type of the algebraic transformation.

  • L <: AbstractString: The type of the label.

source

Operators returning a vector

Next to operators that map forms to forms, there are operators that map forms to vectors. At the moment, Mantis does not have a type for vectors like it does for forms. The result of the operators in this section are thus not a subtype of AbstractForm.

Sharp

The sharp operator takes a 1-form and returns the proxy vector field.

Mantis.Forms.Sharp Type
julia
Sharp{manifold_dim, F}

Represents the sharp operator, which converts a differential 1-form into a vector field.

Constructors

  • Sharp(form::F): General constructor.

Examples

julia
julia> using Mantis

julia> Bx = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 1), (1, 0));

julia> By = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (1, 2), (0, 1));

julia> B = FunctionSpaces.DirectSumSpace((Bx, By)); # A FunctionSpace with 2 components.

julia> Λ¹ₕ = Forms.FormSpace(1, B, "1-form");  # 1-form space with B as basis.

julia> β¹ₕ = Forms.FormField(Λ¹ₕ);

julia> ♯β¹ₕ =(β¹ₕ); # This is no longer a form!

julia> isa(♯β¹ₕ, Forms.Sharp)
true

Fields

  • form::F: The differential 1-form to be converted into a vector field.

Type Parameters

  • manifold_dim: The dimension of the manifold.

  • F: The type of the differential 1-form.

source
Mantis.Forms.♯ Type
julia

Symbolic wrapper for the sharp operator. The unicode character command is \sharp. See Sharp for the details.

source

The sharp operator also has its own evaluate function, which, like the evaluate on forms, evaluates in the canonical domain.

Mantis.Forms.evaluate Method
julia
evaluate(
    sharp::Sharp{manifold_dim}, element_id::Int, xi::Points.AbstractPoints{manifold_dim}
) where {manifold_dim}

Evaluates the sharp operator on a differential 1-form over a specified element of a manifold, converting the form into a vector field. Note that both the 1-form and the vector-field are defined in reference, curvilinear coordinates.

Arguments

  • sharp::Sharp{manifold_dim}: The sharp structure containing the form to be evaluated.

  • element_id::Int: The identifier of the element on which the sharp is to be evaluated.

  • xi::Points.AbstractPoints{manifold_dim}: The points in the canonical domain at which to evaluate the form. See Geometry and Points for more details on the canonical domain and point structure.

Returns

  • ::Vector{Matrix{Float64}}: Each component of the vector, corresponding to each ∂ᵢ, stores the sharp evaluation. The size of each matrix is (number of evaluation points)x(number of basis functions).

  • ::Vector{Vector{Int}}: Each component of the vector, corresponding to each ∂ᵢ, stores the indices of the evaluated basis functions.

source

Pushforward

As explained above, the Sharp turns a 1-form into a vector field, but its evaluate still returns values in the canonical domain. To get values in the physical domain, the vector has to be pushforwarded. Note that this is not a structure in Mantis, just a function.

Mantis.Forms.evaluate_pushforward Function
julia
evaluate_pushforward(
    vfield::Vector{Matrix{Float64}}, jacobian::AbstractVector, manifold_dim::Int
)

Evaluate the pushforward of the vector field from the canonical to the physical domain.

The pushforward is the action of the Jacobian of the field on the field itself.

Arguments

  • vfield::Vector{Matrix{Float64}}: A pointwise evaluated vector field.

  • jacobian::AbstractVector: The Jacobian of the vector field evaluated at the same points as vfield. Each entry in the vector should contain the evaluated Jacobian at that point. This is also the default output of Geometry.jacobian.

  • manifold_dim::Int: The dimension of the embedding manifold.

Returns

  • ::Vector{Matrix{Float64}}: The evaluated pushforward of the vector field.
source

Because the Sharp and pushforward are often used in combination, there is a convenience function to call both operators directly.

Mantis.Forms.evaluate_sharp_pushforward Function
julia
evaluate_sharp_pushforward(
    form_expression::AbstractForm{manifold_dim, 1, 0},
    element_id::Int,
    xi::Points.AbstractPoints{manifold_dim},
) where {manifold_dim}

Compute the pushforward of the sharp of a differential 1-form. Note that the output vector- field is defined in physical coordinates. See Sharp and evaluate_pushforward for the details.

Arguments

  • form::AbstractForm{manifold_dim, 1, 0}: An expression representing the 1-form on the manifold.

  • element_id::Int, xi::Points.AbstractPoints{manifold_dim}: See evaluate.

Returns

  • evaluated_pushforward::Vector{Matrix{Float64}}: Each component of the vector, stores the evaluated pushforward of the sharp of the 1-form. The size of each matrix is (number of evaluation points)x(number of basis functions).

  • sharp_indices::Vector{Vector{Int}}: Each component of the vector, stores the indices of the evaluated basis functions.

source

Operators returning a real value

Another main class of operators are operators that return a value. These are all grouped under the AbstractRealValuedOperator-type.

Mantis.Forms.AbstractRealValuedOperator Type
julia
AbstractRealValuedOperator{manifold_dim}

Supertype for all real-valued operators.

source

Integrals

The most important AbstractRealValuedOperator is the integral.

Mantis.Forms.Integral Type
julia
Integral{manifold_dim, F, Q} <: AbstractRealValuedOperator{manifold_dim}

Integral of a form over a manifold.

Constructors

  • Integral( form::F, quad_rule::Q ) where { manifold_dim, F <: AbstractForm{manifold_dim, manifold_dim}, Q <: Quadrature.AbstractGlobalQuadratureRule{manifold_dim}, }: General constructor.

Examples

Basic syntax:

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ²ₕ = Forms.FormSpace(2, B, "2-form");  # 2-form space with B as basis.

julia> canonical_qrule = Quadrature.tensor_product_rule((3, 3), Quadrature.gauss_legendre);

julia>= Quadrature.StandardQuadrature(canonical_qrule, 4);

julia> integral =(Λ²ₕ, dΩ);

julia> isa(integral, Forms.Integral{2})
true

julia> isa(Forms.get_form(integral), Forms.FormSpace{2, 2})
true

The Integral is more commonly used to represent inner products in combination with the Wedge and Hodge operators:

julia
julia> using Mantis

julia> B = FunctionSpaces.create_bspline_space((0.0, 0.0), (1.0, 1.0), (2, 2), (2, 2), (1, 1));

julia> Λ⁰ₕ = Forms.FormSpace(0, B, "0-form");  # 0-form space with B as basis.

julia> canonical_qrule = Quadrature.tensor_product_rule((3, 3), Quadrature.gauss_legendre);

julia>= Quadrature.StandardQuadrature(canonical_qrule, 4);

julia> integral =(Λ⁰ₕ (Λ⁰ₕ), dΩ);

julia> isa(integral, Forms.Integral{2})
true

julia> isa(Forms.get_form(integral), Forms.Wedge{2, 2})
true

Fields

  • form::F: The form expression to be integrated.

  • quad_rule::Quadrature.AbstractGlobalQuadratureRule{manifold_dim}: The quadrature rule used for the integral.

Type Parameters

  • manifold_dim::Int: The dimension of the manifold.

  • F: The type of the form expression.

  • Q: The type of the quadrature expression.

source
Mantis.Forms.∫ Type
julia

Symbolic wrapper for the integral operator. The unicode character command is \int. See Integral for the details.

source

The integral has its own evaluate function, which only takes the integral and an element_id as input, since the integral operator already stores a quadrature rule and thus the evaluation points.

Mantis.Forms.evaluate Method
julia
evaluate(
    integral::Integral{manifold_dim, F, Q},
    global_element_id::Int,
) where {
    manifold_dim,
    form_rank,
    expression_rank,
    F <: AbstractForm{manifold_dim, form_rank, expression_rank},
}

Evaluates the integral of a form over a given global element using a specified quadrature rule.

Arguments

  • integral::Integral{manifold_dim, F, Q}: The integral operator to evaluate.

  • global_element_id::Int: The global element over which to evaluate the integral.

Returns

  • integral_eval::Vector{Float64}: The evaluated integral.

  • integral_indices::Vector{Vector{Int}}: The indices of the evaluated integral. The length of the outer vector depends on the expression_rank of the form expression.

source

You can retrieve the underlying quadrature rule and the underlying number of evaluation elements (see the docs page of Quadrature for this terminology) with the following functions.

Mantis.Forms.get_quadrature_rule Function
julia
get_quadrature_rule(integral::Integral)

Returns the quadrature rule associated with the integral operator.

Arguments

  • integral::Integral: The integral operator.

Returns

  • <:Quadrature.AbstractGlobalQuadratureRule: Returns the quadrature rule associated with the integral operator.
source
Mantis.Forms.get_num_evaluation_elements Function
julia
get_num_evaluation_elements(integral::Integral)

Returns the number of evaluation elements in the quadrature rule associated with the integral operator.

Arguments

  • integral::Integral: The integral operator.

Returns

  • ::Int: The number of evaluation elements associated with the integral operator.
source

Algebraic Operations on Integrals

Mantis.Forms.UnaryOperatorTransformation Type
julia
UnaryOperatorTransformation{manifold_dim, O, T} <:
AbstractRealValuedOperator{manifold_dim}

Unary, algebraic transformation of an AbstractRealValuedOperator.

Constructors

  • UnaryOperatorTransformation(operator::O, transformation::T): General constructor.

  • Base.:*(factor::Number, operator::AbstractRealValuedOperator): Point-wise multiplication of an operator with a number.

  • Base.:-(operator::AbstractRealValuedOperator): Point-wise additive inverse of an operator.

Fields

  • operator::O: The operator to which the transformation is applied.

  • transformation::T: The transformation to apply to the operator.

Type parameters

  • manifold_dim: See AbstractRealValuedOperator for the details.

  • O <: AbstractRealValuedOperator{manifold_dim}: Type of the original real-valued operator.

  • T <: Function: Function defining the algebraic transformation.

source
Mantis.Forms.BinaryOperatorTransformation Type

BinaryOperatorTransformation{manifold_dim, O1, O2, T} <: AbstractRealValuedOperator

Binary, algebraic transformation acting on two real-valued operators.

Warning

The basis underlying each operator must compatible, this is checked. If not compatible an ArgumentError is thrown.

Constructors

  • BinaryOperatorTransformation(operator_1::O1, operator_2::O2, transformation::T ): General constructor.

  • Base.:+(operator_1::O1, operator_1::O2): Point-wise sum of two operators.

  • Base.:-(operator_1::O1, operator_2::O2): Point-wise difference of two operators.

Fields

  • operator_1::O1: The first real-valued operator.

  • operator_2::O2: The second real-valued operator.

  • transformation::T: The transformation to apply to the operators.

Type parameters

  • manifold_dim: See AbstractRealValuedOperator for the details.

  • O1 <: AbstractRealValuedOperator{manifold_dim}: The type of the first operator.

  • O2 <: AbstractRealValuedOperator{manifold_dim}: The type of the second operator.

  • T <: Function: The type of the algebraic transformation.

source

Basic Operations

Next to the operators described in the previous section, you can also interact and inspect form objects using the following methods.

Every form in Mantis has a label. You can retrieve this label using the following function.

Mantis.Forms.get_label Function
julia
get_label(form::AbstractForm)

Returns the label of the form expression. This is some AbstractString, but the concrete type can vary. Unicode characters and LaTeX string are allowed.

source

Most forms or form operators in Mantis are structs that contain another form. For example, the ExteriorDerivative stores the form to which it is applied. To retrieve the underlying form, you can use one of the following functions.

Mantis.Forms.get_form Function
julia
get_form(form::AbstractForm)
get_form(op::AbstractRealValuedOperator)

Returns the form underlying the form expression or real-valued operator to which the given operator is applied.

source
Mantis.Forms.get_forms Function
julia
get_forms(form::Wedge)

Return both forms to which the wedge is applied.

source
julia
get_forms(bin_trans::BinaryFormTransformation)

Return both forms to which the binary form transformation is applied.

source
Mantis.Forms.get_form_space_tree Function
julia
get_form_space_tree(form::AbstractFormSpace)

Returns the list of forms of expression_rank > 0 in the tree of the expression.

For example, if form represents d((α ∧ β) ∧ γ), it returns the spaces of α, β, and γ, if all have expression_rank > 1. If, e.g., α has expression_rank = 0, it only returns the spaces of β and γ.

Arguments

  • form_space::AbstractFormSpace: The AbstractFormSpace structure.

Returns

  • ::Tuple(<:AbstractForm): The list of forms present in the tree of the expression.
source

Additionally, every form is defined on some geometry. While this geometry is not stored in every form explicitly, it can always be retrieved using the following getter.

Mantis.Forms.get_geometry Function
julia
get_geometry(form::AbstractForm)
get_geometry(op::AbstractRealValuedOperator)

Returns the geometry of the given form expression.

Will recurse using get_form to find the geometry.

source
julia
get_geometry(
    single_form::AbstractForm, additional_forms::AbstractForm...
)

If a single form is given, returns the geometry of that form. If additional forms are given, checks if the number of elements is the same between them; throws an error if not.

Warning

Even if the number of elements is the same, the geometries might be incompatible.

source

It is also possible to immediately obtain the number of elements in the underlying geometry using the following method.

Mantis.Forms.get_num_elements Function
julia
get_num_elements(form::AbstractForm)

Returns the number of elements in the geometry of the given form expression.

Arguments

  • form::AbstractForm: The form expression.

Returns

  • Int: The number of elements in the geometry of the form expression.
source
julia
get_num_elements(integral::Integral)

Returns the number of elements in the geometry associated with the integral operator.

Arguments

  • integral::Integral: The integral operator.

Returns

  • ::Int: The number of elements associated with the integral operator.
source

Most forms also have an underlying FunctionSpaces.AbstractFESpace. To obtain this function space, use the following getter.

Mantis.Forms.get_fe_space Function
julia
get_fe_space(form::FS) where {FS <: AbstractForm}

Returns the finite element space associated with the given form. Note that this function recurses untill it finds a form (usually a FormSpace) which has an underlying finite element space.

Arguments

  • form_space::AbstractForm: The form space.

Returns

  • <:FunctionSpaces.AbstractFESpace: The finite element space.
source

It is also possible to directly obtain some useful information about the underlying function space using the following functions.

Mantis.Forms.get_estimated_nnz_per_elem Function
julia
get_estimated_nnz_per_elem(form::AbstractForm)

Returns the estimated number of non-zero entries per element for the given form expression.

Arguments

  • form::AbstractForm: The form expression.

Returns

  • ::Int: The estimated number of non-zero entries per element.
source
julia
get_estimated_nnz_per_elem(integral::Integral)

Returns the estimated number of non-zero entries per element for the integral operator.

Arguments

  • integral::Integral: The integral operator.

Returns

  • ::Int: The estimated number of non-zero entries per element associated with the integral operator.
source
Mantis.Forms.get_max_local_dim Function
julia
get_max_local_dim(form_space::AbstractFormSpace)

Compute an upper bound of the element-local dimension of form_space. Note that this is not necessarily a tight upper bound.

Arguments

  • form_space::AbstractFormSpace: The form space.

Returns

  • ::Int: The element-local upper bound.
source
Mantis.Forms.get_num_basis Function
julia
get_num_basis(form_space::AbstractFormSpace)

Returns the number of basis functions of the function space associated with the given form space.

Arguments

  • form_space::AbstractFormSpace: The form space.

Returns

  • Int: The number of basis functions of the function space.
source
julia
get_num_basis(form_space::AbstractFormSpace, element_id::Int)

Returns the number of basis functions at the given element of the function space associated the given form space.

Arguments

  • form_space::AbstractFormSpace: The form space.

Returns

  • Int: The number of basis functions at the given element.
source

Helper Functions

De Rham Complexes

The De Rham complex (or any other complex for that matter) is an important construct which structure-preserving methods utilise. As such, there are some (well-)known sequences of Form Spaces that form a finite-dimensional De Rham complex. Mantis provides some helper functions to easily create the spaces in such a complex.

Mantis.Forms.create_tensor_product_bspline_de_rham_complex Function
julia
create_tensor_product_bspline_de_rham_complex(
    starting_points::NTuple{manifold_dim, Float64},
    box_sizes::NTuple{manifold_dim, Float64},
    num_elements::NTuple{manifold_dim, Int},
    section_spaces::NTuple{manifold_dim, F},
    regularities::NTuple{manifold_dim, Int},
    geometry::G,
) where {
    manifold_dim,
    F <: FunctionSpaces.AbstractCanonicalSpace,
    G <: Geometry.AbstractGeometry{manifold_dim},
}

Create a tensor-product B-spline de Rham complex.

Arguments

  • starting_points::NTuple{manifold_dim, Float64}: the starting points of the domain.

  • box_sizes::NTuple{manifold_dim, Float64}: the sizes of the domain.

  • num_elements::NTuple{manifold_dim, Int}: the number of elements in each direction.

  • section_spaces::NTuple{manifold_dim, F}: the section spaces.

  • regularities::NTuple{manifold_dim, Int}: the regularities of the B-spline spaces.

  • geometry::G: the geometry of the domain.

Returns

  • ::Tuple{<:AbstractFormSpace{manifold_dim, form_rank}}: Tuple with the form spaces of the complex, for each form_rank from 0 to manifold_dim+1.
source
julia
create_tensor_product_bspline_de_rham_complex(
    starting_points::NTuple{manifold_dim, Float64},
    box_sizes::NTuple{manifold_dim, Float64},
    num_elements::NTuple{manifold_dim, Int},
    section_spaces::NTuple{manifold_dim, F},
    regularities::NTuple{manifold_dim, Int},
	mapping::M,
) where {
    manifold_dim,
    F <: FunctionSpaces.AbstractCanonicalSpace,
	M <: Geometry.AbstractMapping{manifold_dim},
}

Create a tensor-product B-spline de Rham complex.

Arguments

  • starting_points::NTuple{manifold_dim, Float64}: the starting points of the domain.

  • box_sizes::NTuple{manifold_dim, Float64}: the sizes of the domain.

  • num_elements::NTuple{manifold_dim, Int}: the number of elements in each direction.

  • section_spaces::NTuple{manifold_dim, F}: the section spaces.

  • regularities::NTuple{manifold_dim, Int}: the regularities of the B-spline spaces.

  • mapping::M: the mapping that applied to be base geometry.

Returns

  • ::Tuple{<:AbstractFormSpace{manifold_dim, form_rank}}: Tuple with the form spaces of the complex, for each form_rank from 0 to manifold_dim+1.
source
julia
create_tensor_product_bspline_de_rham_complex(
    starting_points::NTuple{manifold_dim, Float64},
    box_sizes::NTuple{manifold_dim, Float64},
    num_elements::NTuple{manifold_dim, Int},
    degrees::NTuple{manifold_dim, Int},
    regularities::NTuple{manifold_dim, Int},
) where {manifold_dim}

Create a tensor-product B-spline de Rham complex.

Arguments

  • starting_points::NTuple{manifold_dim, Float64}: the starting points of the domain.

  • box_sizes::NTuple{manifold_dim, Float64}: the sizes of the domain.

  • num_elements::NTuple{manifold_dim, Int}: the number of elements in each direction.

  • degrees::NTuple{manifold_dim, Int}: the degrees of the B-spline spaces.

  • regularities::NTuple{manifold_dim, Int}: the regularities of the B-spline spaces.

Returns

  • Vector{AbstractFormSpace}: the manifold_dim+1 form spaces of the complex.
source
Mantis.Forms.create_curvilinear_tensor_product_bspline_de_rham_complex Function
julia
create_curvilinear_tensor_product_bspline_de_rham_complex(
    starting_points::NTuple{manifold_dim, Float64},
    box_sizes::NTuple{manifold_dim, Float64},
    num_elements::NTuple{manifold_dim, Int},
    section_spaces::NTuple{manifold_dim, F},
    regularities::NTuple{manifold_dim, Int},
) where {manifold_dim, F <: FunctionSpaces.AbstractCanonicalSpace}

Create a tensor-product B-spline de Rham complex on a crazy mesh.

Arguments

  • starting_points::NTuple{manifold_dim, Float64}: the starting points of the domain.

  • box_sizes::NTuple{manifold_dim, Float64}: the sizes of the domain.

  • num_elements::NTuple{manifold_dim, Int}: the number of elements in each direction.

  • section_spaces::NTuple{manifold_dim, F}: the section spaces.

  • regularities::NTuple{manifold_dim, Int}: the regularities of the B-spline spaces.

Returns

  • Vector{AbstractFormSpace}: the manifold_dim+1 form spaces of the complex.
source
julia
create_curvilinear_tensor_product_bspline_de_rham_complex(
    starting_points::NTuple{manifold_dim, Float64},
    box_sizes::NTuple{manifold_dim, Float64},
    num_elements::NTuple{manifold_dim, Int},
    degrees::NTuple{manifold_dim, Int},
    regularities::NTuple{manifold_dim, Int},
) where {manifold_dim}

Create a tensor-product B-spline de Rham complex on a crazy geometry.

Arguments

  • starting_points::NTuple{manifold_dim, Float64}: the starting points of the domain.

  • box_sizes::NTuple{manifold_dim, Float64}: the sizes of the domain.

  • num_elements::NTuple{manifold_dim, Int}: the number of elements in each direction.

  • degrees::NTuple{manifold_dim, Int}: the degrees of the B-spline spaces.

  • regularities::NTuple{manifold_dim, Int}: the regularities of the B-spline spaces.

Returns

  • Vector{AbstractFormSpace}: the manifold_dim+1 form spaces of the complex.
source
Mantis.Forms.create_hierarchical_de_rham_complex Function
julia
create_hierarchical_de_rham_complex(
    starting_points::NTuple{manifold_dim, Float64},
    box_sizes::NTuple{manifold_dim, Float64},
    num_elements::NTuple{manifold_dim, Int},
    section_spaces::NTuple{manifold_dim, F},
    regularities::NTuple{manifold_dim, Int},
    num_subdivisions::NTuple{manifold_dim, Int},
    truncate::Bool,
    simplified::Bool,
    geometry::G,
) where {
    manifold_dim,
    F <: FunctionSpaces.AbstractCanonicalSpace,
    G <: Geometry.AbstractGeometry{manifold_dim},
}

Construct a hierarchical discrete de Rham complex of finite element spaces over a tensor-product geometry, equivalent to a Cartesian grid, in manifold_dim dimensions.

This routine initializes, for each form degree k = 0,…,manifold_dim, a hierarchical B-spline space of differential k‑forms without refinement.

See also create_tensor_product_bspline_de_rham_complex and FunctionSpaces.HierarchicalFiniteElementSpace.

Returns

  • A tuple with the manifold_dim + 1 spaces that form the de Rham complex.
source
Mantis.Forms.update_hierarchical_de_rham_complex Function
julia
update_hierarchical_de_rham_complex(
	complex::C, data
) where {num_forms, C <: NTuple{num_forms, AbstractFormSpace}}

Returns a refined hierarchical de Rham complex, based on the given complex and refinement data. The input data should have a dedicated method in FunctionSpaces.refine_space(space, data).

See also FunctionSpaces.refine_space.

Arguments

  • complex::C: The hierarchical B-spline de Rham complex.

  • data: The information used for refinement. Examples include domains denoting active elements, of type Hierarchy.ActiveInfo, or elements marked for refinement, of type Vector{Vector{Int}}.

Returns

  • new_complex<:NTuple{num_forms, AbstractFormSpace}:A tuple with the manifold_dim + 1
julia
refined spaces that form the de Rham complex.
source
Mantis.Forms.create_polar_spline_de_rham_complex Function
julia
create_polar_spline_de_rham_complex(
    num_elements::NTuple{2, Int},
    degrees::NTuple{2, Int},
    regularities::NTuple{2, Int},
    R::Float64;
    refine::Bool=false,
    geom_coeffs_tp::Union{Nothing, Array{Float64,3}}=nothing
)

Create a polar B-spline de Rham complex.

Arguments

  • num_elements::NTuple{2, Int}: the number of elements in each direction.

  • degrees::NTuple{2, Int}: the degrees of the B-spline spaces.

  • regularities::NTuple{2, Int}: the regularities of the B-spline spaces.

  • R::Float64: the radius of the domain.

  • refine::Bool=false: whether to refine the domain.

  • geom_coeffs_tp::Union{Nothing, Array{Float64,3}}=nothing: the geometry coefficients.

Returns

  • ::Vector{AbstractFormSpace}: the 3 form spaces of the complex.

  • ::Vector{NTuple{N,SparseMatrixCSC{Float64,Int}} where {N}}: the global extraction operators.

  • ::NTuple{2, Array{Float64,3}}: the geometry coefficients for the underlying tensor-product B-spline spaces.

source
julia
create_polar_spline_de_rham_complex(
    num_elements::NTuple{2, Int},
    section_spaces::F,
    regularities::NTuple{2, Int},
    R::Float64;
    refine::Bool=false,
    geom_coeffs_tp::Union{Nothing, Array{Float64,3}}=nothing
) where {F <: NTuple{2, FunctionSpaces.AbstractCanonicalSpace}}

Create a polar B-spline de Rham complex.

Arguments

  • num_elements::NTuple{2, Int}: the number of elements in each direction.

  • section_spaces::F: the section spaces.

  • regularities::NTuple{2, Int}: the regularities of the B-spline spaces.

  • R::Float64: the radius of the domain.

  • refine::Bool=false: whether to refine the domain.

  • geom_coeffs_tp::Union{Nothing, Array{Float64,3}}=nothing: the geometry coefficients.

Returns

  • ::Vector{AbstractFormSpace}: the 3 form spaces of the complex.

  • ::Vector{NTuple{N,SparseMatrixCSC{Float64,Int}} where {N}}: the global extraction operators.

  • ::NTuple{2, Array{Float64,3}}: the geometry coefficients for the underlying tensor-product B-spline spaces.

source

Boundary Conditions

In Mantis, boundary conditions are set during assembly (see the assembly page for the details), but the following functions can help in specifying boundary conditions.

Mantis.Forms.set_dirichlet_boundary_conditions Function
julia
set_dirichlet_boundary_conditions(form::AbstractFormSpace, value::Float64)

Creates a dictionary of Dirichlet boundary conditions for a given form space.

Arguments

  • form::AbstractFormSpace: The form for which to compute the boundary conditions.

  • value::Float64: The value of the Dirichlet boundary condition.

Returns

  • ::Dict{Int, Float64}: The dictionary of Dirichlet boundary conditions.
source
Mantis.Forms.trace_basis_idxs Function
julia
trace_basis_idxs(
    form::AbstractForm{manifold_dim, form_rank, expression_rank}
) where {manifold_dim, form_rank, expression_rank}

Creates a list of basis function idxs which control the trace of the form on the boundary.

Arguments

  • form::AbstractForm: The form for which to compute the boundary conditions.

Returns

  • Vector{Int}: The list of basis idxs.
source

Other Helper Functions

Mantis.Forms.get_basis_index_combinations Function
julia
get_basis_index_combinations(manifold_dim::Int, form_rank::Int)

Generate all possible k-form basis index combinations.

Arguments

  • manifold_dim::Int: the dimension of the manifold.

  • form_rank::Int: the rank of the form.

Returns

  • NTuple{binomial(manifold_dim, form_rank), Vector{Int}}: the basis index combinations.
source