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.

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 );

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_t<functionspace_type<decltype(Xh)>, functionspace_type<decltype(Xh)>>


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

I: X_h \rightarrow Y_h


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


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

\nabla: X_h \rightarrow W_h


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


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

\nabla \times : W_h \rightarrow V_h


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


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