As always, we initialize the {feelpp} environment (see section [FirstApp] ).
The unitSquare() will generate a mesh for a square geometry.
Feel++ provides several functions to automate the GMSH mesh generation for different topologies.
These functions will create a geometry file .geo and a mesh file .msh.
We can visualize them in {uri-gmsh-www}[Gmsh].

$ gmsh <entity_name>.msh

Finally we use the exporter() (see \ref Exporter) function to export the mesh for post processing. It will create by default a Paraview format file .sos and an Ensight format file .case.

$ paraview <app_name>.case

In this section, we present some of the mesh definition and manipulation tools provided by Feel++.
For more information you can also read {uri-gmsh-manual}[the Gmsh manual].

Basic Meshes

There is a list of basic geometries you can automatically generate with Feel++ library.

Table 1. Table of function generation basic primitive mesh

Feel++ function

Dim

Description

unitSegment()

1

Build a mesh of the unit segment \$[0,1\$]

unitSquare()

2

Build a mesh of the unit square \$[0,1\$^2] using triangles

unitCircle()

2

Build a mesh of the unit circle using triangles

unitHypercube()

3

Build a mesh of the unit hypercube \$[0,1\$^3] using tetrahedrons

unitSphere()

3

Build a mesh of the unit sphere using tetrahedrons

Example

automesh=unitSquare();

Loading Meshes

loadMesh

You can use this function to load mesh from different formats

in the case of a .geo file, {feelpp} automatically generate a mesh data structure on this geometrical structure.

All the elements of the mesh which share a face with the boundary of the mesh.

internalelements_t<MeshType>

internalelements(mesh)

All the elements of the mesh which share a face with the boundary of the mesh.

pid_faces_t<MeshType>

faces(mesh)

All the faces of the mesh.

markedfaces_t<MeshType>

markedfaces(mesh)

All the faces of the mesh which are marked.

boundaryfaces_t<MeshType>

boundaryfaces(mesh)

All elements that own a topological dimension one below the mesh. For example, if you mesh is a 2D one, boundaryfaces(mesh) will return all the lines (because of dimension 2-1=1). These elements which have one dimension less, are corresponding to the boundary faces.

internalfaces_t<MeshType>

internalelements(mesh)

All the elements of the mesh which are stricly within the domain that is to say they do not share a face with the boundary.

edges_t<MeshType>

edges(mesh)

All the edges of the mesh.

boundaryedges_t<MeshType>

boundaryedges(mesh)

All boundary edges of the mesh.

points_t<MeshType>

points(mesh)

All the points of the mesh.

markedpoints_t<MeshType>

markedpoints(mesh,id)

All the points marked id of mesh.

boundarypoints_t<MeshType>

boundarypoints(mesh)

All boundary points of the mesh.

internalpoints_t<MeshType>

internalpoints(mesh)

All internal points of the mesh(not on the boundary)

Here are some examples on how to use these functionSpace

automesh=...;autor1=elements(mesh);// iterate over the set of elements local to the process(no ghost cell selected, see next section)for(autoconst&e:r2){autoconst&elt=unwrap_ref(e);// work with element elt...}autor2=markedelements(mesh,"iron");// iterate over the set of elements marked iron in the meshfor(autoconst&e:r2){autoconst&elt=unwrap_ref(e);// work with element elt...}autor3=boundaryfaces(mesh);// iterate over the set of faces on the boundary of the meshfor(autoconst&e:r3){autoconst&elt=unwrap_ref(e);// work with element elt...}autor4=markededges(mesh,"line");// iterate over the set of edges marked "line" in the meshfor(autoconst&e:r4){autoconst&elt=unwrap_ref(e);// work with element elt...}

Extended set of entities

Feel++ allows also to select an extended sets of entities from the mesh, you can extract entities which belongs to the local process but also ghost entities which satisfy the same property as the local ones.

Actually you can select both or one one of them thanks to the enum data structure entity_process_t which provides the following options

entity_process_t

Description

LOCAL_ONLY

only local entities

GHOST_ONLY

only ghost entities

ALL

both local and ghost entities

Type

Function

Description

ext_elements_t<MeshType>

elements(mesh,entity_process_t)

all the elements of mesh associated to entity_process_t.

ext_elements_t<MeshType>

markedelements(mesh, id, entity_process_t)

all the elements marked id of mesh associated to entity_process_t.

ext_faces_t<MeshType>

faces(mesh,entity_process_t)

all the faces of mesh associated to entity_process_t.

ext_faces_t<MeshType>

markedfaces(mesh, id, entity_process_t)

all the faces marked id of mesh associated to entity_process_t.

ext_edges_t<MeshType>

edges(mesh,entity_process_t)

all the edges of mesh associated to entity_process_t.

ext_edges_t<MeshType>

markededges(mesh, id, entity_process_t)

all the edges marked id of mesh associated to entity_process_t.

The type of the object returned for an entity is always the same, for elements it is ext_elements_t<MeshType> whether the elements are marked or not.
The reason is that in fact we have to create a temporary data structure embedded in the range object that stores a reference to the elements which are selected.

Here is how to select both local and ghost elements from a Mesh

automesh=...;autor=elements(mesh,entity_process_t::ALL);for(autoconst&e:r){// do something on the local and ghost element...// do something special on ghost cellsif(unwrap_ref(e).isGhostCell()){...}}

Compute the complement of a set of entities

Denote \$\mathcal{E}\$ a set of entities, eg. the set of all faces
(both internal and boundary faces). Denote \$\mathcal{E}_\Gamma\$ a
set of entities marked by \$\Gamma\$. We wish to build
\${\Gamma}^c=\mathcal{E}\backslash\Gamma\$. To compute the complement,
Feel++ provides a complement template function that requires
\$\mathcal{E}\$ and a predicate that return true if an entity of
\$\mathcal{E}\$ belongs to \$\Gamma\$, false otherwise. The function
returns mesh iterators over \$\Gamma^c\$.

#include<feel/feelmesh/complement.hpp>...autoE=faces(mesh);// build set of boundary faces, equivalent to boundaryfaces(mesh)autobdyfaces=complement(E,[](autoconst&e){returne.isOnBoundary()});cout<<"measure of bdyfaces = "<<integrate(_range=bdyfaces,_expr=cst(1.)).evaluate()<<std::endl;// should be the same as abovecout<<"measure of boundaryfaces = "<<integrate(_range=boundaryfaces(mesh),_expr=cst(1.)).evaluate()<<std::endl;

Helper function on entities set

Feel++ provides some helper functions to apply on set of entities. We
denote by range_t the type of the entities set.

Table 3. Utility functions

Type

Function

Description

size_type

nelements(range_t,bool)

returns the local number of elements in entities set range_t of bool is false, other the global number which requires communication (default: global number)

WorldComm

worldComm(range_t)

returns the WorldComm associated to the entities set

Create a new range

A range can be also build directly by the user. This customized range
is stored in a std container which contains the c++ references of
entity object. We use boost::reference_wrapper for take c++ references
and avoid copy of mesh data. All entities enumerated in the range must
have same type (elements,faces,edges,points). Below we have an example
which select all active elements in mesh for the current partition
(i.e. identical to elements(mesh)).

Mesh Operations

straightenMesh

One of the optimisations that allows to have a huge gain in computational effort is to straighten all the high order elements except for the boundary faces of the computational mesh.
This is achieved by moving all the nodes associated to the high order transformation to the position these nodes would have if a first order geometrical transformation were applied.
This procedure can be formalized in the following operator

where \$\mathbf{x}^*\$ is any point in \$K^*\$ and \$\mathbf{\varphi}^1_{K}(\mathbf{x}^*)\$ and \$\mathbf{\varphi}^N_{K}(\mathbf{x}^*)\$ its images by the geometrical transformation of order one and order \$N\$, respectively.
On one hand, the first two terms ensure that for all \$K\$ not intersecting \$\Gamma\$, the order one and \$N\$ transformations produce the same image.
On the other hand, the last two terms are 0 unless the image of \$\mathbf{x}^*\$ in on \$\Gamma\$ and, in this case, we don’t move the high order image of \$\mathbf{x}^*\$.
This allows to have straight internal elements and elements touching the boundary to remain high order.
When applying numerical integration, specific quadratures are considered when dealing with internal elements or elements sharing a face with the boundary.
The performances, thanks to this transformation, are similar to the ones obtained with first order meshes.
However, it needs to be used with care as it can generate folded meshes.

createSubmesh

In multiphysics applications or using advanced numerical methods e.g. involving Lagrange multipliers, it is often required to define Function Spaces on different meshes.
Theses meshes are often related.
Consider for example a heat transfer problem on a domain \$\Omega\$ coupled with fluid flow problem on a domain \$\Omega_f \subset \Omega\$ as in the {uri-benchmarks}heat[Heat Transfer benchmarks].
createSubmesh allows to extract \$\Omega_f\$ out of \$\Omega\$ while keeping information on the relation between the two meshes to be able to transfer data between these meshes very efficiently.