Finite element back ends

ModularEIT itself contains no finite element code. The generic layer — electrode models, ForwardModel, objectives, regularizers, optimizers, linear solvers and synthetic data — works with any discretization that implements a small contract. The discretization comes from a back end package, which is loaded next to ModularEIT:

Back endPackageFinite element library
FerriteModularEITFerrite (in lib/ModularEITFerrite)Ferrite.jl (fork with triangle bisection)
GridapModularEITGridap (in lib/ModularEITGridap)Gridap.jl
using ModularEIT, ModularEITFerrite, Ferrite
disc = FerriteDiscretization(generate_grid(Triangle, (16, 16)))

using ModularEIT, ModularEITGridap, Gridap
disc = GridapDiscretization(simplexify(CartesianDiscreteModel((-1, 1, -1, 1), (16, 16))))

Only the back end that is used has to be installed; the others are separate packages. On the same mesh both back ends give the same matrices (up to the numbering of the dofs), voltages, objective values and gradients; the Gridap back end's tests check this.

The Ferrite back end additionally provides structured, polar and conformally mapped grids, image maps, pixel parametrizations and adaptive meshing. The Gridap back end covers the contract below (Lagrange u of any order, piecewise constant or Lagrange σ) and works with every Gridap DiscreteModel, e.g. meshes read with GridapGmsh.

ModularEITFerrite.ModularEITFerrite — Module
ModularEITFerrite

Ferrite.jl back end of ModularEIT: finite element discretizations with separate spaces for the potential and the conductivity, assembly, electrode geometry and forward models, grids (structured, polar, conformally mapped), image maps, pixel parametrizations, total variation on meshes, and adaptive meshing (hanging nodes on quadrilaterals, newest vertex bisection on triangles).

source
ModularEITGridap — Module
ModularEITGridap

Gridap.jl back end of ModularEIT: finite element discretizations of a Gridap DiscreteModel with separate spaces for the potential (Lagrange, any order) and the conductivity (piecewise constants by default, or Lagrange). It implements the back end contract of ModularEIT, so forward models of all electrode models, objectives, regularizers, optimizers and linear solvers work unchanged on Gridap meshes.

source
ModularEITGridap.GridapDiscretization — Type
GridapDiscretization(model; order_u = 1, order_σ = 0, σ_conformity = order_σ == 0 ? :L2 : :H1,
                     boundary = nothing, degree = nothing)

Finite element spaces for the potential u (Lagrange of order order_u) and the conductivity σ (Lagrange of order order_σ, discontinuous with σ_conformity = :L2, continuous with :H1; default: piecewise constants) on the Gridap DiscreteModel model (e.g. a CartesianDiscreteModel, simplexify(...) of it, or a mesh read with GridapGmsh).

  • boundary: boundary facets (global ids of the faces of dimension D-1). Default: all facets that belong to exactly one cell.
  • degree: quadrature degree. Default: exact for the weighted stiffness matrix ∫ σ ∇φᵢ⋅∇φⱼ and the mass matrices on affine cells.

Facets are assumed straight (affine geometry) for facet measures and midpoints.

Fields: model, V, U (test and trial space of u), Vσ, Uσ, Ω, dΩ, degree, boundary_facets, boundary_dofs (u dofs on the boundary), order_u, order_σ.

source

The contract

A back end defines a subtype of AbstractDiscretization and adds methods to these functions and constructors (the electrode and regularizer primitives behind the forward models and the regularizers are listed in src/Galerkin/Electrodes.jl and src/Galerkin/RegularizersFE.jl):

PurposeFunctions
Sizesndofs_u, ndofs_σ
MatricesFEMatrices(disc), ConductivityTensor(disc; pattern, to_device), assemble_weighted_stiffness
Functions on the meshinterpolate_function, l2_project, fe_inner, fe_norm, total_variation, lumped_mass
Electrodes and forward modelangular_electrodes, electrode_length, transfer_electrodes, ForwardModel(disc, model) for the electrode models
RegularizersTikhonovRegularizer(disc; kind), TotalVariationRegularizer(disc; ε) with objective_value, value_and_gradient!, gauss_newton_hessian, prox!
Fast preconditioners (optional)structured_grid, polar_structure
Pixel parametrizations (optional)pixel_image

The electrodes of GapModel and CompleteElectrodeModel are stored in the back end's representation (for Ferrite: vectors of FacetIndex). Everything else the generic layer needs is in the data types FEMatrices, ConductivityTensor and ForwardModel, which are back end independent.

ModularEIT.total_variation! — Function
total_variation(disc, σ; ε = 0)
total_variation!(g, disc, σ; ε = 0)

Total variation ∫ √(|∇σ|² + ε²) of a conductivity (for piecewise constants: the facet jumps), and its coefficient gradient (in place). Back end contract.

source