1. Interpolation

Feel++ has a very powerful interpolation framework which allows to:

  • transfer functions from one mesh to another

  • transfer functions from one space type to another.

this is done seamlessly in parallel. The framework provides a set of C++ classes and C++ free-functions enabled short, concise and expressive handling of interpolation.

1.1. Using interpolation operator

Building interpolation operator \(I_h : P^1_{c,h} \rightarrow P^0_{td.h}\)
using MeshType = Mesh<Simplex<2>>;
auto mesh = loadMesh( _mesh=new MeshType );
auto P1h = Pch<1>( mesh );
auto P0h = Pdh<0>( mesh );
auto Ih = I( _domain=P1h, _image=P0h );

1.2. De Rahm Diagram

The De Rahm diagram reads as follows: the range of each of the operators coincides with the null space of the next operator in the sequence below, and the last map is a surjection.

\[\begin{array}{ccccccc} H^1(\Omega)& \overset{\nabla}{\longrightarrow}& H^{\mathrm{curl}}(\Omega)& \overset{\nabla \times}{\longrightarrow}& H^{\mathrm{div}}(\Omega)& \overset{\nabla \cdot}{\longrightarrow}& L^2(\Omega) \end{array}\]

An important result is that the diagram transfers to the discrete level

\[\begin{array}{ccccccc} H^1(\Omega)& \overset{\nabla}{\longrightarrow}& H^{\mathrm{curl}}(\Omega)& \overset{\nabla \times}{\longrightarrow}& H^{\mathrm{div}}(\Omega)& \overset{\nabla \cdot}{\longrightarrow}& L^2(\Omega) \\ \left\downarrow\right.\pi_{c,h}& ~ & \left\downarrow\right.\pi_{\mathrm{curl},h}& ~ & \left\downarrow\right.\pi_{\mathrm{div},_h}& ~ & \left\downarrow\right.\pi_{d,h}& ~ \\ U_h& \overset{\nabla}{\longrightarrow}& V_h& \overset{\nabla \times}{\longrightarrow}& W_h& \overset{\nabla \cdot}{\longrightarrow}& Z_h\\ \end{array}\]

The diagram above is commutative which means that we have the following properties:

\[\begin{aligned} \nabla(\pi_{c,h} u) &= \pi_{\mathrm{curl},h}( \nabla u ),\\ \nabla\times(\pi_{\mathrm{curl},h} u) &= \pi_{\mathrm{div},h}( \nabla\times u ),\\ \nabla\cdot(\pi_{\mathrm{div},h} u) &= \pi_{d,h}( \nabla\cdot u ) \end{aligned}\]
The diagram can be restricted to functions satisfying the homogeneous Dirichlet boundary conditions
\[\begin{array}{ccccccc} H^1_0(\Omega)& \overset{\nabla}{\longrightarrow}& H_0^{\mathrm{curl}}(\Omega)& \overset{\nabla \times}{\longrightarrow}& H_0^{\mathrm{div}}(\Omega)& \overset{\nabla \cdot}{\longrightarrow}& L^2_0(\Omega) \end{array}\]

Interpolation operators are provided as is or as shared pointers. The table below presents the alternatives.

Table 1. Table of Interpolation operators

C++ object

C++ Type

C++ shared object

C++ Type

Mathematical operator

I(_domain=Xh,_image=Yh)

I_t<functionspace_type<decltype(Xh)>, functionspace_type<decltype(Xh)>>

IPtr(…​)

I_ptr_t<functionspace_type<decltype(Xh)>, functionspace_type<decltype(Xh)>>

\(I: X_h \rightarrow Y_h \)

Grad(_domain=Xh,_image=Wh)

Grad_t<functionspace_type<decltype(Xh)>, functionspace_type<decltype(Wh)>>

GradPtr(…​)

Grad_ptr_t<functionspace_type<decltype(Xh)>, functionspace_type<decltype(Wh)>>

\(\nabla: X_h \rightarrow W_h \)

Curl(_domain=Wh,_image=Vh)

Curl_t<functionspace_type<decltype(Wh)>, functionspace_type<decltype(Vh)>>

CurlPtr(…​)

Curl_ptr_t<functionspace_type<decltype(Wh)>, functionspace_type<decltype(Vh)>>

\(\nabla \times : W_h \rightarrow V_h \)

Div(_domain=Vh,_image=Zh)

Div_t<functionspace_type<decltype(Vh)>, functionspace_type<decltype(Zh)>>

DivPtr(…​)

Div_ptr_t<functionspace_type<decltype(Vh)>, functionspace_type<decltype(Zh)>>

\(\nabla \cdot: V_h \rightarrow Z_h \)

Building the discrete operators associated to the De Rahm diagram in Feel++
auto mesh = loadMesh( _mesh=new Mesh<Simplex<Dim>>());
auto Xh = Pch<1>(mesh);
auto Gh = Ned1h<0>(mesh);
auto Ch = Dh<0>(mesh);
auto P0h = Pdh<0>(mesh);
auto Igrad = Grad( _domainSpace = Xh, _imageSpace=Gh );
auto Icurl = Curl( _domainSpace = Gh, _imageSpace=Ch );
auto Idiv = Div( _domainSpace = Ch, _imageSpace=P0h );

auto u = Xh->element(<expr>);
auto w = Igrad(u); // w in Gh
auto x = Icurl(w); // z in Ch
auto y = Idiv(x); // y in P0h