Skip to content

Assemblers ​

The assembly module contains two important pieces for assembly: the weak formulation and the assembly routine itself. The weak formulation contains all the terms that need to be assembled, the assembler creates the final system matrix.

Weak Formulations ​

A weak formulation describes the problem in detail, see The Finite Element Method (FEM) for more information. It consists of a few key ingredients: the given data (forcings, boundary conditions, etc.), the trial spaces, the test spaces, and the equations. In Mantis, there are two structures that are used to represent all this data: WeakFormInputs and WeakForm.

Representing problem data using WeakFormInputs ​

The data, trial spaces, and test spaces are represented by the following object.

Mantis.Assemblers.WeakFormInputs Type
julia
WeakFormInputs{manifold_dim, TeF, TrF, F} <: AbstractInputs

Container for test and trial spaces, and forcing terms to be used in a WeakForm.

Constructors

  • WeakFormInputs(test_forms::TeF, trial_forms::TrF, forcings::F): Creates a new WeakFormInputs instance with the given test forms, trial forms, and forcing terms.

  • WeakFormInputs(test_forms::TeF, trial_forms::TrF): Creates a new WeakFormInputs instance with the given test forms and trial forms. The forcing terms are set to nothing.

  • WeakFormInputs(test_forms::TeF, trial_forms::TrF, forcing::F): Creates a new WeakFormInputs instance from a single test and trial space and a forcing term.

  • WeakFormInputs(test_forms::TeF, trial_forms::TrF): Creates a new WeakFormInputs instance from a single test and trial space. The forcing terms are set to nothing.

  • WeakFormInputs(forms::TrF, forcing::F): Creates a new WeakFormInputs instance with the given trial spaces and forcing terms. The test spaces are set to the same as the trial spaces.

  • WeakFormInputs(forms::TrF): Creates a new WeakFormInputs instance with the given trial spaces. The test spaces are set to the same as the trial spaces and the forcing terms are set to nothing.

  • WeakFormInputs(forms::TrF, forcing::F): Creates a new WeakFormInputs instance with a single trial space and forcing term. The test space is set to the same as the trial space.

  • WeakFormInputs(forms::TrF): Creates a new WeakFormInputs instance with a single trial space. The test space is set to the same as the trial space and the forcing term is set to nothing.

Example

julia
julia> using Mantis

julia> V0, V1, V2, V3 = Forms.create_tensor_product_bspline_de_rham_complex((0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (4, 4, 4), (3, 3, 3), (2, 2, 2));

julia> geometry = Forms.get_geometry(V2);

julia> forcing_function(x) = [ones(size(x))];

julia> f = Forms.AnalyticalFormField(3, forcing_function, geometry, "f");

julia> weak_form_inputs = Assemblers.WeakFormInputs((V2, V3), (f,));

julia> isa(weak_form_inputs, Assemblers.WeakFormInputs{3})
true

Fields

  • test_forms::TeF: The test forms for the weak-formulation.

  • trial_forms::TrF: The trial forms for the weak-formulation.

  • forcings::F: The forcing terms for the weak-formulation, possibly nothing.

Type parameters

  • manifold_dim::Int: The dimension of the manifold where the weak-formulation is defined.

  • TeF: The type of the tuple of test forms. Each entry should be a subtype of Forms.AbstractFormSpace.

  • TrF: The type of the tuple of trial forms. Each entry should be a subtype of Forms.AbstractFormSpace.

  • F: The type of the tuple of forcing terms. Each entry should be a subtype of Forms.AbstractFormField.

source

The following getters are defined to obtain the data from a WeakFormInputs object.

Mantis.Assemblers.get_trial_forms Method
julia
get_trial_forms(wfi::WeakFormInputs)

Return a tuple of Forms.AbstractFormSpace that are used as trial spaces.

source
Mantis.Assemblers.get_test_forms Method
julia
get_test_forms(wfi::WeakFormInputs)

Return a tuple of Forms.AbstractFormSpace that are used as test spaces.

source
Mantis.Assemblers.get_forcings Method
julia
get_forcings(wfi::WeakFormInputs)

Return a tuple of Forms.AbstractFormField that are used as test spaces.

source
Mantis.Assemblers.get_trial_form Function
julia
get_trial_form(wfi::WeakFormInputs, i::Int=1)

Return the i-th trial Forms.AbstractFormSpace.

source
Mantis.Assemblers.get_test_form Function
julia
get_test_form(wfi::WeakFormInputs, i::Int=1)

Return the i-th test Forms.AbstractFormSpace.

source
Mantis.Assemblers.get_forcing Function
julia
get_forcing(wfi::WeakFormInputs, i::Int=1)

Return the i-th forcing Forms.AbstractFormField.

source
Mantis.Assemblers.get_num_trial Method
julia
get_num_trial(wfi::WeakFormInputs)

Return the number of trial spaces.

source
Mantis.Assemblers.get_num_test Method
julia
get_num_test(wfi::WeakFormInputs)

Return the number of test spaces.

source
Mantis.Assemblers.get_num_forcings Method
julia
get_num_forcings(wfi::WeakFormInputs)

Return the number of forcing functions.

source

Representing weak formulations using WeakForm ​

The complete weak formulation is represented by the following object, that takes a WeakFormInputs and the left-hand and right-hand sides of the equations as inputs.

Mantis.Assemblers.WeakForm Type
julia
WeakForm{manifold_dim, LHS, RHS, I}

Structure representing the weak-formulation of a continuous Petrov-Galerking method. Both the left and right-hand sides of the formulation are given as blocks of real-valued operators; these are defined from a set of inputs holding the test, trial and forcing terms, and a constructor method that defines where the blocks are placed.

Constructors

  • WeakForm( lhs_expressions::LHS, rhs_expressions::RHS, inputs::I ) where { manifold_dim, lhs_num_rows, lhs_num_cols, rhs_num_rows, rhs_num_cols, LHS <: NTuple{ lhs_num_rows, NTuple{lhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}} }, RHS <: NTuple{ rhs_num_rows, NTuple{rhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}} }, I <: WeakFormInputs{manifold_dim}, }: Creates a new WeakForm instance with the given inputs (the problem data and spaces, see WeakFormInputs for more details), and the left- and right-hand side expressions.

Example

julia
julia> using Mantis

julia> V0, V1, V2, V3 = Forms.create_tensor_product_bspline_de_rham_complex((0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (4, 4, 4), (3, 3, 3), (2, 2, 2));

julia> geometry = Forms.get_geometry(V2);

julia> forcing_function(x) = [ones(size(x))];

julia> f = Forms.AnalyticalFormField(3, forcing_function, geometry, "f");

julia> weak_form_inputs = Assemblers.WeakFormInputs((V2, V3), (f,));

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

julia> dΩ = Quadrature.StandardQuadrature(canonical_qrule, Geometry.get_num_elements(geometry));

julia> tau_h, v_h = Assemblers.get_test_forms(weak_form_inputs);

julia> sigma_h, u_h = Assemblers.get_trial_forms(weak_form_inputs);

julia> f = Assemblers.get_forcing(weak_form_inputs);

julia> A_11 = ∫(tau_h ∧ ★(sigma_h), dΩ);

julia> A_12 = -∫(d(tau_h) ∧ ★(u_h), dΩ);

julia> A_21 = ∫(v_h ∧ ★(d(sigma_h)), dΩ);

julia> lhs_expressions = ((A_11, A_12), (A_21, 0));

julia> b_21 = ∫(v_h ∧ ★(f), dΩ);

julia> rhs_expressions = ((0,), (b_21,));

julia> weak_form = Assemblers.WeakForm(lhs_expressions, rhs_expressions, weak_form_inputs);

julia> isa(weak_form, Assemblers.WeakForm{3})
true

Fields

  • lhs_expressions::LHS: The left-hand side blocks of the weak-formulation.

  • rhs_expressions::RHS: The right-hand side blocks of the weak-formulation.

  • inputs::I: The inputs for the weak-formulation, which include the test and trial spaces, and forcing terms.

Type parameters

  • manifold_dim::Int: The dimension of the manifold where the weak-formulation is defined.

  • LHS: The type of the left-hand side expressions. Each row-column entry should be a subtype of AbstractRealValuedOperator or 0.

  • RHS: The type of the right-hand side expressions. Each row-column entry should be a subtype of AbstractRealValuedOperator or 0.

  • I: The type of the inputs. It should be a subtype of WeakFormInputs{manifold_dim}.

source

For this object, the following getters are defined.

Mantis.Assemblers.get_lhs_expressions Function
julia
get_lhs_expressions(wf::WeakForm)

Return a tuple of Forms.AbstractRealValuedOperator representing the left-hand sides of the weak formulation.

source
Mantis.Assemblers.get_rhs_expressions Function
julia
get_rhs_expressions(wf::WeakForm)

Return a tuple of Forms.AbstractRealValuedOperator representing the right-hand sides of the weak formulation.

source
Mantis.Assemblers.get_inputs Function
julia
get_inputs(wf::WeakForm)

Return the WeakFormInputs object used in the weak form.

source
Mantis.Assemblers.get_test_forms Method
julia
get_test_forms(wf::WeakForm)

Return a tuple of Forms.AbstractFormSpace that are used as test spaces.

source
Mantis.Assemblers.get_trial_forms Method
julia
get_trial_forms(wf::WeakForm)

Return a tuple of Forms.AbstractFormSpace that are used as trial spaces.

source
Mantis.Assemblers.get_forcings Method
julia
get_forcings(wf::WeakForm)

Return a tuple of Forms.AbstractFormField that are used as test spaces.

source
Mantis.Assemblers.get_forcing Function
julia
get_forcing(wf::WeakForm, id::Int=1)

Return the id-th forcing Forms.AbstractFormField.

source
Mantis.Assemblers.get_test_sizes Function
julia
get_test_sizes(wf::WeakForm)

Return the number of degrees of freedom for each test form. Uses Forms.get_num_basis.

source
Mantis.Assemblers.get_trial_sizes Function
julia
get_trial_sizes(wf::WeakForm)

Return the number of degrees of freedom for each trial form. Uses Forms.get_num_basis.

source
Mantis.Assemblers.get_test_size Function
julia
get_test_size(wf::WeakForm)

Return the total number of degrees of freedom for all test forms combined.

source
Mantis.Assemblers.get_trial_size Function
julia
get_trial_size(wf::WeakForm)

Return the total number of degrees of freedom for all trial forms combined.

source
Mantis.Assemblers.get_lhs_size Function
julia
get_lhs_size(wf::WeakForm)

Return the size of the left-hand-side matrix. Does not require assembly.

source
Mantis.Assemblers.get_rhs_size Function
julia
get_rhs_size(wf::WeakForm)

Return the size of the right-hand-side matrix (or vector). Does not require assembly.

source
Mantis.Assemblers.get_test_offsets Function
julia
get_test_offsets(
    wf::WeakForm{manifold_dim, LHS, RHS, I}
) where {
    manifold_dim,
    num_rows,
    lhs_num_cols,
    rhs_num_cols,
    LHS <:
    NTuple{
        num_rows, NTuple{lhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}}
    },
    RHS <:
    NTuple{
        num_rows, NTuple{rhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}}
    },
    I,
}

Returns the offsets of the test function spaces used in the weak form.

Arguments

  • wf::WeakForm{manifold_dim, LHS, RHS, I}: The weak form being used.

Returns

  • NTuple{num_rows, Int}: The offsets of the test function spaces.
source
Mantis.Assemblers.get_trial_offsets Function
julia
get_trial_offsets(
    wf::WeakForm{manifold_dim, LHS, RHS, I}
) where {
    manifold_dim,
    num_rows,
    lhs_num_cols,
    rhs_num_cols,
    LHS <:
    NTuple{
        num_rows, NTuple{lhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}}
    },
    RHS <:
    NTuple{
        num_rows, NTuple{rhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}}
    },
    I,
}

Returns the offsets of the trial function spaces used in the weak form.

Arguments

  • wf::WeakForm{manifold_dim, LHS, RHS, I}: The weak form being used.

Returns

  • NTuple{lhs_num_cols, lhs_num_cols}: The offsets of the trial function spaces.
source
Mantis.Assemblers.get_estimated_nnz_per_elem Function
julia
get_estimated_nnz_per_elem(wf::WeakForm)

Returns the estimated number of non-zero entries per element for the left- and right-hand sides of the weak-formulation.

Arguments

  • wf::WeakForm: The weak-formulation for which the estimated number of non-zero entries is to be determined.

Returns

  • Tuple(Int, Int): The estimated number of non-zero entries per element for the left-hand side and right-hand side of the weak-formulation, respectively.
source
Mantis.Assemblers.get_num_elements Function
julia
get_num_elements(wf::WeakForm)

Returns the number of elements over which the discrete weak-formulation is defined.

Arguments

  • wf::WeakForm: The weak-formulation for which the number of elements is to be determined.

Returns

  • ::Int: The number of elements.
source
Mantis.Assemblers.get_num_evaluation_elements Function
julia
get_num_evaluation_elements(wf::WeakForm)

Returns the maximum number of elements over which the weak form blocks are evaluated. This is the max over all lhs and rhs expression blocks.

Arguments

  • wf::WeakForm: The weak-formulation for which the number of quadrature elements is to be determined.

Returns

  • ::Int: The number of quadrature elements.
source

Example: setting up a weak form. ​

As an example, consider the mixed -form Hodge-Laplacian in 3D also treated in Finite Element Exterior Calculus (FEEC). The weak formulation is written as: Given  , find    such that

We first create a WeakFormInputs object containing the test and trial spaces (which are the same in this case, so we only have to include them once), and the forcing (which we set to return one here for simplicity).

julia
julia> using Mantis

julia> V0, V1, V2, V3 = Forms.create_tensor_product_bspline_de_rham_complex(
           (0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (4, 4, 4), (3, 3, 3), (2, 2, 2)
       );

julia> geometry = Forms.get_geometry(V2);

julia> forcing_function(x) = [ones(size(x, 1))]
forcing_function (generic function with 1 method)

julia> f = Forms.AnalyticalFormField(3, forcing_function, geometry, "f");

julia> weak_form_inputs = Assemblers.WeakFormInputs((V2, V3), (f,));

With the WeakFormInputs object ready, we can create the complete WeakForm object. Note that the lhs_expressions and rhs_expressions contain the integer 0 where we don't need a term.

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

julia> dΩ = Quadrature.StandardQuadrature(canonical_qrule, Geometry.get_num_elements(geometry));

julia> τ_h, v_h = Assemblers.get_test_forms(weak_form_inputs);

julia> σ_h, u_h = Assemblers.get_trial_forms(weak_form_inputs);

julia> f = Assemblers.get_forcing(weak_form_inputs);

julia> A_11 = ∫(τ_h ∧ ★(σ_h), dΩ);

julia> A_12 = -∫(d(τ_h) ∧ ★(u_h), dΩ);

julia> A_21 = ∫(v_h ∧ ★(d(σ_h)), dΩ);

julia> lhs_expressions = ((A_11, A_12), (A_21, 0));

julia> b_21 = ∫(v_h ∧ ★(f), dΩ);

julia> rhs_expressions = ((0,), (b_21,));

julia> weak_form = Assemblers.WeakForm(lhs_expressions, rhs_expressions, weak_form_inputs);

The weak form object can now be assembled using the assemble function.

Pre-implemented weak formulations ​

While you can always write your own weak formulation, Mantis does provide a few common pre-made weak formulations. The pre-implemented weak formulations require input spaces, forcings, and quadrature, but simplify the remaining steps. Most pre-implemented weak formulations consist of two parts: one that encodes the equations, another that also performs the remaining setup and solve steps.

-projection
Mantis.Assemblers.L2_projection Function
julia
L2_projection(inputs::AbstractInputs, dΩ::Quadrature.AbstractGlobalQuadratureRule)

Set up the L2 projection equations of projecting a function onto a discrete form space.

Weak form: for given  , find   such that

Arguments

  • inputs::AbstractInputs: The inputs for the weak form assembly. See WeakFormInputs for the details.

  • dΩ::Quadrature.AbstractGlobalQuadratureRule: The quadrature rule to use for the integral evaluation.

Returns

  • lhs_expression<:NTuple{1, NTuple{1, AbstractRealValuedOperator}}: The left-hand side of the weak form.

  • rhs_expression<:NTuple{1, NTuple{1, AbstractRealValuedOperator}}: The right-hand side of the weak form.

source
Mantis.Assemblers.solve_L2_projection Function
julia
solve_L2_projection(Xᵏ, fₑ, dΩ)

Returns the solution of the weak form of the L2 projection.

Weak form: for given  , find   such that

Arguments

  • Xᵏ: The k-form space to use as trial and test space.

  • fₑ: The forcing term to use for the right-hand side of the weak formulation.

  • dΩ: The quadrature rule to use for the assembly.

Returns

  • fₕ::FormField: The projection of fₑ onto Xᵏ.
source
Hodge-Laplacians
Mantis.Assemblers.zero_form_hodge_laplacian Function
julia
zero_form_hodge_laplacian(
    inputs::AbstractInputs, dΩ::Quadrature.AbstractGlobalQuadratureRule
)

Set up the equations for the -form Hodge-Laplacian. Does not specify any boundary conditions.

Weak form: for given  , find   such that

Arguments

  • inputs::AbstractInputs: The inputs for the weak form assembly. See WeakFormInputs for the details.

  • dΩ::Quadrature.AbstractGlobalQuadratureRule: The quadrature rule to use for the integral evaluation.

Returns

  • lhs_expression<:NTuple{1, NTuple{1, AbstractRealValuedOperator}}: The left-hand side of the weak form.

  • rhs_expression<:NTuple{1, NTuple{1, AbstractRealValuedOperator}}: The right-hand side of the weak form.

source
Mantis.Assemblers.solve_zero_form_hodge_laplacian Function
julia
solve_zero_form_hodge_laplacian(X⁰, fₑ, dΩ)

Returns the solution of the weak form of the 0-form Hodge Laplacian using homogeneous Dirichlet boundary conditions.

Weak form: for given  , find   such that

Arguments

  • X⁰: The 0-form space to use as trial and test space.

  • fₑ: The forcing term to use for the right-hand side of the weak formulation.

  • dΩ: The quadrature rule to use for the assembly.

Returns

  • uₕ::Forms.FormField: The solution of the weak-formulation.
source
Mantis.Assemblers.one_form_hodge_laplacian Function
julia
one_form_hodge_laplacian(
    inputs::AbstractInputs, dΩ::Quadrature.AbstractGlobalQuadratureRule
)

Set up the equations for the -form Hodge-Laplacian. Does not specify any boundary conditions.

Weak form: for given  , find    such that

Arguments

  • inputs::AbstractInputs: The inputs for the weak form assembly. See WeakFormInputs for the details.

  • dΩ::Quadrature.AbstractGlobalQuadratureRule: The quadrature rule to use for the integral evaluation.

Returns

  • lhs_expression<:NTuple{2, NTuple{2, Union{Int, AbstractRealValuedOperator}}}: The left-hand side of the weak form.

  • rhs_expression<:NTuple{2, NTuple{1, Union{Int, AbstractRealValuedOperator}}}: The right-hand side of the weak form.

Function for assembling the weak form of the 1-form Hodge Laplacian problem.

source
Mantis.Assemblers.solve_one_form_hodge_laplacian Function
julia
solve_one_form_hodge_laplacian(X⁰, X¹, f¹, dΩ)

Returns the solution of the weak form of the 1-form Hodge Laplacian.

Weak form: for given  , find    such that

Arguments

  • X⁰: The 0-form space to use as trial and test space.

  • X¹: The 1-form space to use as trial and test space.

  • f¹: The forcing term to use for the right-hand side of the weak formulation.

  • dΩ: The quadrature rule to use for the assembly.

Returns

  • σ⁰ₕ::Forms.FormField: The 0-form solution of the weak-formulation.

  • u¹ₕ::Forms.FormField: The 1-form solution of the weak-formulation.

source
julia
solve_one_form_hodge_laplacian(
    complex::C,
    forcing_function::Function,
    dΩₐ::Quadrature.AbstractGlobalQuadratureRule{manifold_dim},
    num_steps::Int,
    dorfler_parameter::Float64,
    dΩₑ::Quadrature.AbstractGlobalQuadratureRule{manifold_dim},
    Lchains::Bool;
    verbose::Bool=false
) where {manifold_dim, num_forms, C <: NTuple{num_forms, Forms.AbstractFormSpace}}

Returns the solution of the weak form of the 1-form Hodge Laplacian from an adaptive loop.

Arguments

  • complex::C: The initial de Rham complex to use for the problem.

  • forcing_function::Function: The function to use for the forcing term.

  • dΩₐ::Quadrature.AbstractGlobalQuadratureRule{manifold_dim}: The quadrature rule to use for the assembly.

  • num_steps::Int: The number of steps to use for the adaptive loop.

  • dorfler_parameter::Float64: The parameter to use for the Dörfler marking.

  • dΩₑ::Quadrature.AbstractGlobalQuadratureRule{manifold_dim}: The quadrature rule to use for the error estimation.

  • Lchains::Bool: Whether to use L-chains for the refinement.

  • verbose::Bool=false: Whether to print the progress of the adaptive loop.

source
Mantis.Assemblers.n_form_hodge_laplacian Function
julia
n_form_hodge_laplacian(
    inputs::WeakFormInputs, dΩ::Quadrature.AbstractGlobalQuadratureRule
)

Set up the equations for the -form Hodge-Laplacian. Does not specify any boundary conditions.

Weak form: for given  , find    such that

Arguments

  • inputs::AbstractInputs: The inputs for the weak form assembly. See WeakFormInputs for the details.

  • dΩ::Quadrature.AbstractGlobalQuadratureRule: The quadrature rule to use for the integral evaluation.

Returns

  • lhs_expression<:NTuple{2, NTuple{2, Union{Int, AbstractRealValuedOperator}}}: The left-hand side of the weak form.

  • rhs_expression<:NTuple{2, NTuple{1, Union{Int, AbstractRealValuedOperator}}}: The right-hand side of the weak form.

source
Mantis.Assemblers.solve_volume_form_hodge_laplacian Function
julia
solve_volume_form_hodge_laplacian(Xⁿ⁻¹, Xⁿ, fₑ, dΩ)

Returns the solution of the weak form of the n-form Hodge Laplacian.

Weak form: for given  , find    such that

Arguments

  • Xⁿ⁻¹: The (n-1)-form space to use as trial and test space.

  • Xⁿ: The n-form space to use as trial and test space.

  • fₑ: The forcing term to use for the right-hand side of the weak formulation.

  • dΩ: The quadrature rule to use for the assembly.

Returns

  • uⁿ⁻¹ₕ: The (n-1)-form solution of the weak-formulation.

  • ϕⁿₕ: The n-form solution of the weak-formulation.

source
Maxwell Eigenvalue Problems

In this case, next to the functions maxwell_eigenvalue and solve_maxwell_eig, Mantis also provides two functions to obtain the analytical eigenvalues.

Mantis.Assemblers.maxwell_eigenvalue Function
julia
maxwell_eigenvalue(inputs::WeakFormInputs, dΩ::Quadrature.AbstractGlobalQuadratureRule)

Set up the equations for Maxwell's eigenvalue problem.

Weak form: find   such that

Arguments

  • inputs::AbstractInputs: The inputs for the weak form assembly. See WeakFormInputs for the details.

  • dΩ::Quadrature.AbstractGlobalQuadratureRule: The quadrature rule to use for the integral evaluation.

Returns

  • lhs_expression<:NTuple{1, NTuple{1, AbstractRealValuedOperator}}: The left-hand side of the weak form.

  • rhs_expression<:NTuple{1, NTuple{1, AbstractRealValuedOperator}}: The right-hand side of the weak form.

source
Mantis.Assemblers.analytical_maxwell_eigenfunction Function
julia
analytical_maxwell_eigenfunction(
    m::Int, n::Int, scale_factors::NTuple{2, Float64}, x::Matrix{Float64}
)

Evaluates the analytical Maxwell eigenfunction for the eigenmode (m, n) at points x.

Arguments

  • m::Int: Eigenmode component x.

  • n::Int: Eigenmode component y.

  • scale_factors::NTuple{2, Int}: Scaling factors based on the size of the domain.

  • x::Matrix{Float64}: Evaluation points.

Returns

  • NTuple{2, Vector{Float64}}: The evaluated Maxwell eigenfunction at points x.
source
Mantis.Assemblers.get_analytical_maxwell_eig Function
julia
get_maxwell_eig(num_eig::Int, geom::G) where {G <: Geometry.AbstractGeometry{2}}

Returns the first num_eig eigenvalues and 1-form eigenfunctions on the geometry geom.

Arguments

  • num_eig::Int: Number of eigenvalues and eigenfunctions to compute.

  • geom::Geometry.AbstractGeometry{2}: The two-dimensional geometry.

Returns

  • Vector{Float64}: The first num_eig analytical eigenvalues.

  • Vector{Forms.AnalyticalFormField{2, 1, G}: The first num_eig analytical eigenfunctions.

source
Mantis.Assemblers.solve_maxwell_eig Function
julia
solve_maxwell_eig(
    X⁰::Forms.AbstractFormSpace{2, 0},
    X¹::Forms.AbstractFormSpace{2, 1},
    dΩ::Quadrature.AbstractGlobalQuadratureRule{2},
    num_eig::Int;
    verbose::Bool=false,
)

Returns the first num_eig eigenvalues and 1-form eigenfunctions of the Maxwell eigenvalue problem.

Weak form: find   such that

Arguments

  • X⁰::Forms.AbstractFormSpace{2, 0}: The 0-form space to compute the nullspace offset with.

  • X¹::Forms.AbstractFormSpace{2, 1}: The 1-form space to use as trial and test space.

  • dΩ::Quadrature.AbstractGlobalQuadratureRule{2}: The quadrature rule to use for the assembly.

  • num_eig::Int: The number of eigenvalues and eigenfunctions to compute.

  • verbose::Bool=false: Whether to print the nullspace offset.

Returns

  • ω²ₕ::Vector{Float64}: The first num_eig eigenvalues.

  • u¹ₕ::Vector{Forms.FormField{2, 1}}: The first num_eig eigenfunctions.

source
julia
solve_maxwell_eig(
    complex::C,
    dΩₐ::Quadrature.StandardQuadrature{manifold_dim},
    num_steps::Int,
    dorfler_parameter::Float64,
    dΩₑ::Quadrature.StandardQuadrature{manifold_dim},
    Lchains::Bool,
    eigenfunction::Int,
    num_eig::Int,
    scale_factors::NTuple{manifold_dim, Float64};
    verbose::Bool=false,
) where {manifold_dim, num_forms, C <: NTuple{num_forms, Forms.AbstractFormSpace}}

Returns the first num_eig eigenvalues and 1-form eigenfunctions of the Maxwell eigenvalue problem for an adaptive loop.

Arguments

  • complex::C: The initial de Rham complex to use for the problem.

  • dΩₐ::Quadrature.StandardQuadrature{manifold_dim}: The quadrature rule to use for the assembly.

  • num_steps::Int: The number of adaptive steps to perform.

  • dorfler_parameter::Float64: The Dörfler marking parameter.

  • dΩₑ::Quadrature.StandardQuadrature{manifold_dim}: The quadrature rule to use for the error estimation.

  • Lchains::Bool: Whether to use L-chains for the refinement.

  • eigenfunction::Int: The index of the eigenfunction to use for the error estimation.

  • num_eig::Int: The number of eigenvalues and eigenfunctions to compute.

  • scale_factors::NTuple{manifold_dim, Float64}: The scaling factors for the geometry.

  • verbose::Bool=false: Whether to print the progress of the adaptive loop.

Returns

  • ω²ₕ::Vector{Float64}: The first num_eig eigenvalues.

  • u¹ₕ::Vector{Forms.FormField{manifold_dim, 1, G}}: The first num_eig eigenfunctions.

source

Assembling a weak formulation ​

In Mantis, the actual assembly routine can be used by simply calling the following function.

Mantis.Assemblers.assemble Function
julia
assemble(
    weak_form::WeakForm{manifold_dim, LHS, RHS, I},
    dirichlet_bcs::Dict{Int, Float64}=Dict{Int, Float64}();
    lhs_type::Type=spa.SparseMatrixCSC{Float64, Int},
    rhs_type::Type=Vector{Float64},
) where {
    manifold_dim,
    num_rows,
    lhs_num_cols,
    rhs_num_cols,
    LHS <: NTuple{
        num_rows, NTuple{lhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}}
    },
    RHS <: NTuple{
        num_rows, NTuple{rhs_num_cols, Union{Int, Forms.AbstractRealValuedOperator}}
    },
    I,
}

Assemble the left- and right-hand sides of a discrete Petrov-Galerkin problem for the given weak-formulation and Dirichlet boundary conditions.

Arguments

  • weak_form::WeakForm{manifold_dim, LHS, RHS, I}: The weak form to assemble.

  • dirichlet_bcs::Dict{Int, Float64}: A dictionary containing the Dirichlet boundary conditions, where the key is the index of the boundary condition and the value is the boundary condition value.

  • lhs_type::Type: The type of the left-hand side array. Default is SparseMatrixCSC{Float64, Int}.

  • rhs_type::Type: The type of the right-hand side array. Default is Vector{Float64}.

Returns

  • lhs::lhs_type: The assembled left-hand side array.

  • rhs::rhs_type: The assembled right-hand side vector.

source

So, continuing the previous example, we can assemble our problem by simply calling

julia
julia> A, b = Assemblers.assemble(weak_form);

This gives us the left-hand side matrix A and right-hand side vector b. You can solve this with a solver of your choosing. Here we pick Julia's backslash operator. We can obtain the final solution as a FormField using the build_form_fields helper. This helper takes the trial spaces and full solution vector as inputs, and combines the spaces and coefficients into the final solution objects.

julia
julia> sol = A \ b;

julia> sigma_h, u_h = Forms.build_form_fields((V2, V3), sol);
Helpers used within assemble

The assembly module also provides the following helper functions that are used within the assembly routine.

Mantis.Assemblers.get_pre_allocation Function
julia
get_pre_allocation(
    weak_form::WeakForm, side::String, ::Type{A}
) where {T, A <: AbstractArray{T}}

Returns pre-allocated row, column, and value vectors for the left-hand side (lhs) or right-hand side (rhs) array.

Arguments

  • weak_form::WeakForm: The weak form to use for the pre-allocation.

  • side::String: The side of the array to pre-allocate. Must be either "lhs" or "rhs".

Returns

  • rows::Vector{Int}: The pre-allocated row indices.

  • cols::Vector{Int}: The pre-allocated column indices.

  • vals::Vector{T}: The pre-allocated values.

source
Mantis.Assemblers.add_expression_contributions! Function
julia
add_expression_contributions!(
    rows::Vector{Int},
    cols::Vector{Int},
    vals::AbstractVector,
    counts::Int,
    expression,
    element_id::Int,
    test_offset::Int,
    trial_offset::Int,
)

Updates the row, column, and value vectors with contributions from the specified real-valued expression at the element given by element_id.

Arguments

  • rows::Vector{Int}: The row indices of the array.

  • cols::Vector{Int}: The column indices of the array.

  • vals::AbstractVector: The values of the array.

  • counts::Int: The current count of non-zero entries in the array.

  • expressions: The expression to evaluate.

  • element_id::Int: The identifier of the element.

  • test_offsets::Int: The offset for the test function.

  • trial_offsets::Int: The offset for the trial function.

Returns

  • rows::Vector{Int}: The updated row indices of the array.

  • cols::Vector{Int}: The updated column indices of the array.

  • vals::AbstractVector: The updated values of the array.

  • counts::Int: The updated count of non-zero entries in the array.

source
Mantis.Assemblers.zero_rows! Function
julia
zero_rows!(
    lhs_vals::AbstractVector{T},
    rhs_vals::AbstractVector{T},
    lhs_rows::Vector{Int},
    rhs_rows::Vector{Int},
    dirichlet_bcs::Dict{Int, T},
) where {T}

For each index i that is a key of dirichlet_bcs, set the corresponding values from that row to zero, both in lhs_vals and rhs_vals.

Examples

julia
using Mantis

Assemblers.zero_rows!([1., 1., 1.], [1., 2., 3.], [1, 2, 3], [1, 3, 2], Dict(2 => 42.0))

# output

([1.0, 0.0, 1.0], [1.0, 2.0, 0.0])
source
Mantis.Assemblers.add_bc! Function
julia
add_bc!(
    lhs::AbstractMatrix{T}, rhs::AbstractVector{T}, dirichlet_bcs::Dict{Int, T}
) where {T}

Set the rows to 0 and diagonals to 1 in lhs, and rows of rhs to a value, as specified by the row indices (keys) and values of dirichlet_bcs.

Examples

julia
using Mantis

Assemblers.add_bc!([2.0 2.0 2.0; 2.0 2. 2.0; 2.0 2.0 2.0], zeros(3), Dict(2 => 42.0))

# output

([2.0 2.0 2.0; 0.0 1.0 0.0; 2.0 2.0 2.0], [0.0, 42.0, 0.0])
source
julia
add_bc!(lhs::AbstractMatrix, rhs::AbstractMatrix, dirichlet_bcs::Dict)

Remove the rows and columns of lhs and rhs as specified by the keys of dirichlet_bcs. See also set_diagonal!.

source
Mantis.Assemblers.set_diagonal! Function
julia
set_diagonal!(
    lhs::AbstractMatrix{T}, rhs::AbstractVector{T}, dirichlet_bcs::Dict{Int, T}
) where {T}

Set the diagonals of lhs to 1 and rows of rhs to a value, as specified by the row indices (keys) and values of dirichlet_bcs. See also add_bc!.

Examples

julia
using Mantis

Assemblers.set_diagonal!([2.0 2.0 2.0; 2.0 2. 2.0; 2.0 2.0 2.0], zeros(3), Dict(2 => 42.0))

# output

([2.0 2.0 2.0; 2.0 1.0 2.0; 2.0 2.0 2.0], [0.0, 42.0, 0.0])
source
julia
set_diagonal!(lhs::AbstractMatrix, rhs::AbstractMatrix, dirichlet_bcs::Dict)

Remove the rows and columns of lhs and rhs as specified by the keys of dirichlet_bcs.

Examples

julia
using Mantis

Assemblers.set_diagonal!(
    [2. 0. 0.; 0. 2. 0.; 0. 0. 2.], [2. 0. 0.; 0. 2. 0.; 0. 0. 2.], Dict(2 => 42.0)
)

# output

([2.0 0.0; 0.0 2.0], [2.0 0.0; 0.0 2.0])
source
Mantis.Assemblers.build_array Function
julia
build_array(
    array_type::Type{A},
    rows::Vector{Int},
    cols::Vector{Int},
    vals::AbstractVector,
    size::Tuple{Int, Int},
) where {A <: AbstractArray}

Returns a array of the specified type with the given row and column indices and values.

Arguments

  • array_type::Type{AbstractArray}: The type of array to build.

  • rows::Vector{Int}: The row indices of the array.

  • cols::Vector{Int}: The column indices of the array.

  • vals::AbstractVector: The values of the array.

  • size::Tuple{Int, Int}: The size of the array.

Returns

  • ::array_type: The constructed array of the specified type.
source