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
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.-form, -form, -form, etc. expression_rank: The number of bases present in an expression. Isif no bases are present, for a single basis, and for two bases. Expression ranks larger than are not allowed.
Non-zero expression rank does not mean that the full expression has a basis.
If expression_rank is larger than FormSpace will result in a form with expression rank FormSpace has a basis, this does not generate a basis for the exterior derivative (only a spanning set).
There are two aliases for AbstractForm, which are AbstractFormField and AbstractFormSpace.
Mantis.Forms.AbstractFormField Type
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.
Mantis.Forms.AbstractFormSpace Type
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.
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
get_manifold_dim(::AbstractForm{manifold_dim}) where {manifold_dim}Returns the manifold_dim of the given form.
Mantis.Forms.get_form_rank Function
get_form_rank(
::AbstractForm{manifold_dim, form_rank}
) where {manifold_dim, form_rank}Returns the form_rank of the given form.
Mantis.Forms.get_expression_rank Function
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.
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
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
Constructors
FormSpace(form_rank::Int, fem_space::F, label::AbstractString): General constructor.
Example
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, themanifold_dimand geometry are inherited. Additionally, thenum_componentsof the function space must be consistent with the providedform_rankand themanifold_dim, i.e., a real-valued-form has 1 component (in any dimension), a -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
manifold_dim,form_rank,expression_rank: See AbstractForm for the details.F: Type of the finite element space (a FunctionSpaces.AbstractFESpace).L: Type of the label (anAbstractString).
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
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
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 manifold_dim-form (so a top form), and will always evaluate to ConstantFormSpace can act as the form basis for the real numbers ConstantFormSpace does not require a function space but only the geometry.
Mantis.Forms.ConstantFormSpace Type
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> 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 theConstantFormSpaceshould be created. Themanifold_dimwill 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 (anAbstractString).
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
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> 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 (anAbstractString).
Mantis.Forms.AnalyticalFormField Type
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> 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 (anAbstractString).
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
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.
Mantis.Forms.get_num_coefficients Function
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.
Mantis.Forms.get_expression Function
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.
Evaluating Forms
As with any object in Mantis, evaluating a form is a matter of calling the evaluate-function:
Mantis.Forms.evaluate Method
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 aArray{Float64, expression_rank+1}(so, aVectorforAbstractFormFields and aMatrixforAbstractFormSpaces) of size(num_evaluation_points,),(num_evaluation_points, num_basis_functions_on_element), respectively. For expressions involving two forms (such as thewedge), the entries will be of typeArray{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). ForAbstractFormFields (things without a basis), this will always be [[1]].
Examples
Evaluating a
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
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]])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
_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.
Mantis.Forms._pullback_to_canonical_coordinates Function
_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.
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
_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
- See evaluate for the details.
Returns
- See evaluate for the details.
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
Mantis.Forms.ExteriorDerivative Type
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 anyAbstractForm.
Examples
Creating the exterior derivative of a
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})
trueFields
form::F: The form to which the exterior derivative is applied. Note that the form rank of this form is one lower than theform_rankof the exterior derivative.label::L: The exterior derivative label. This is a concatenation of "d" with the label ofform.
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 ofform.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.
Mantis.Forms.d Type
dSymbolic wrapper for the exterior derivative operator. See ExteriorDerivative for the details.
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
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> 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})
trueFields
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 ofform_1.F2 <: Forms.AbstractForm: The type ofform_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.
Mantis.Forms.:∧ Type
∧Symbolic wrapper for the wedge operator. The unicode character command is \wedge. See Wedge for the details.
Hodge
The Hodge-star operator is a metric-dependent operator, which maps k-forms to manifold_dim-k forms.
Mantis.Forms.Hodge Type
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> 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})
trueFields
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 ofform.
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 ofform.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.
Mantis.Forms.★ Type
★Symbolic wrapper for the hodge star operator. The unicode character command is \bigstar. See Hodge for the details.
Codifferential
The codifferential, often denoted
Mantis.Forms.CoDifferential Type
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> 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})
trueFields
form::F: The form to which the codifferential is applied.label::L: The codifferential label. Adds "δ" to the label ofform.
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 ofform.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.
Mantis.Forms.dstar Type
dstarSymbolic wrapper for the codifferential. See CoDifferential for the details.
Mantis.Forms.δ Type
δSymbolic wrapper for the codifferential. The unicode character command is \delta. See CoDifferential for the details.
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
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.
Mantis.Forms.BinaryFormTransformation Type
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> 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})
trueFields
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.
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
Mantis.Forms.Sharp Type
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> 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)
trueFields
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.
Mantis.Forms.♯ Type
♯Symbolic wrapper for the sharp operator. The unicode character command is \sharp. See Sharp for the details.
The sharp operator also has its own evaluate function, which, like the evaluate on forms, evaluates in the canonical domain.
Mantis.Forms.evaluate Method
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.
Pushforward
As explained above, the Sharp turns a Mantis, just a function.
Mantis.Forms.evaluate_pushforward Function
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 asvfield. 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.
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
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.
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
AbstractRealValuedOperator{manifold_dim}Supertype for all real-valued operators.
sourceIntegrals
The most important AbstractRealValuedOperator is the integral.
Mantis.Forms.Integral Type
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> 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> dΩ = 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})
trueThe Integral is more commonly used to represent inner products in combination with the Wedge and Hodge operators:
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> dΩ = 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})
trueFields
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.
Mantis.Forms.∫ Type
∫Symbolic wrapper for the integral operator. The unicode character command is \int. See Integral for the details.
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
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 theexpression_rankof the form expression.
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
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.
Mantis.Forms.get_num_evaluation_elements Function
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.
Algebraic Operations on Integrals
Mantis.Forms.UnaryOperatorTransformation Type
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.
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.
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
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.
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
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.
sourceMantis.Forms.get_forms Function
get_forms(form::Wedge)Return both forms to which the wedge is applied.
sourceget_forms(bin_trans::BinaryFormTransformation)Return both forms to which the binary form transformation is applied.
sourceMantis.Forms.get_form_space_tree Function
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.
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
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.
sourceget_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.
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
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.
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.
Most forms also have an underlying FunctionSpaces.AbstractFESpace. To obtain this function space, use the following getter.
Mantis.Forms.get_fe_space Function
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.
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
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.
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.
Mantis.Forms.get_max_local_dim Function
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.
Mantis.Forms.get_num_basis Function
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.
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.
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
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 eachform_rankfrom0tomanifold_dim+1.
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 eachform_rankfrom0tomanifold_dim+1.
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}: themanifold_dim+1form spaces of the complex.
Mantis.Forms.create_curvilinear_tensor_product_bspline_de_rham_complex Function
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}: themanifold_dim+1form spaces of the complex.
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}: themanifold_dim+1form spaces of the complex.
Mantis.Forms.create_hierarchical_de_rham_complex Function
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 + 1spaces that form the de Rham complex.
Mantis.Forms.update_hierarchical_de_rham_complex Function
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 typeHierarchy.ActiveInfo, or elements marked for refinement, of typeVector{Vector{Int}}.
Returns
new_complex<:NTuple{num_forms, AbstractFormSpace}:A tuple with themanifold_dim + 1
refined spaces that form the de Rham complex.Mantis.Forms.create_polar_spline_de_rham_complex Function
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.
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.
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
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.
Mantis.Forms.trace_basis_idxs Function
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.
Other Helper Functions
Mantis.Forms.get_basis_index_combinations Function
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.