Function and FE spaces
AbstractFunctionSpace
In Bcube, a FunctionSpace
is defined by a type (nodal Lagrange polynomials, modal Taylor expansion, etc) and a degree. For each implemented FunctionSpace
, a list of shape functions is associated on a given Shape
. For instance, one can get the shape functions associated to the Lagrange polynomials or order 3 on a Square
. Note that for "tensor" elements such as Line
, Square
or Cube
; the Lagrange polynomials are available at any order; being computed symbolically.
fs = FunctionSpae(:Lagrange, 2)
AbstractFESpace
Then, an FESpace
(more precisely SingleFESpace
) is a function space associated to a numbering of the degrees of freedom. Note that the numbering may depend on the continuous or discontinuous feature of the space. Hence a SingleFESpace
takes basically four input to be built : a FunctionSpace
, the number of components of this space (scalar or vector), an indicator of the continuous/discontinuous characteristic, and the mesh. The dof numbering is built by combining the mesh numberings (nodes, cells, faces) and the function space. Note that the degree of the FunctionSpace
can differ from the "degree" of the mesh elements : it is possible to build a SingleFESpace
with P2 polynomials on a mesh only containing straight lines (defined by only two nodes, Bar2_t
).
For more clarity, the SingleFESpace
is actually declined in two flavors : TrialFESpace
and TestFESpace
. These are the ones exposed to the API. The naming convention should be clear to the user familiar to the FE (and/or GD) method. Optionaly, a TrialFESpace
can also contain the tags of the boundaries where Dirichlet condition(s) applies.
A MultiFESpace
is simply a set of TrialFESpace
(or a set of TestFESpace
), eventually of different natures. Its befenit is that it allows to build a "global" numbering of all the dofs represented by this space. This is especially convenient to solve systems of equations.
fs = FunctionSpace(:Lagrange, 2)
U_fem_sca = TrialFEspace(fs, mesh) # scalar FEM FESpace
U_dg_sca = TrialFEspace(fs, mesh, :discontinuous) # scalar DG FESpace
U_dg_vec = TrialFEspace(fs, mesh, :discontinuous; size = 2) # 2-components DG FESpace
U = MultiFESpace(U_fem_sca, U_dg_sca, U_dg_vec)
V_fem_sca = TestFESpace(U_fem_sca)
V_dg_sca = TestFESpace(U_dg_sca)
V_dg_vec = TestFESpace(U_dg_vec)
V = MultiFESpace(V_fem_sca, V_dg_sca, V_dg_vec)
AbstractFEFunction
With a TrialFESpace
, one can build the representation of a function discretized on this space: a FEFunction
. This structure stores a vector of values, one for each degree of freedom of the finite element space. To set or get the values of a FEFunction
, the functions set_dof_values!
and get_dof_values
are available respectively. A FEFunction
can be projected on another FESpace
; or evaluated at some specific mesh location (a coordinates, all the nodes, all the mesh centers, etc).
U = TrialFESpace(FunctionSpace(:Lagrange, 1), mesh)
u = FEFunction(U) # an FEFunction with all zeros as the initial value
u = FEFunction(U, rand(nnodes(mesh))) # a random value at each dof
dofs = get_dof_values(u) # get the values of the FEFunction
set_dof_values!(u, 2. * dofs) # assign the dof values
projection_l2!(u, PhysicalFunction(x -> norm(x)), mesh) # set the dof values using an L2 projection