1. Bilinear and Linears Forms
We consider in this section bilinear and linear forms \(a: X_h \times X_h \rightarrow \mathbb{R}\) and \(\ell: X_h \rightarrow \mathbb{R}.\)
We suppose in this section that you know how to define your Mesh and your function spaces. You may need integration tools too, see Integrals.
There are Feel++ tools you need to create linear and bilinear forms in order to solve variational formulation.
from now on, u denotes an element from your trial function
space (unknown function) and v an element from your test function
space
 | 
1.1. Building Forms
1.1.1. Using form1
To construct a linear form \ell: X_h \rightarrow \mathbb{R}, proceed as follows
auto mesh = ...;
// build a P1/Q1 approximation space
auto Xh = Pch<1>( mesh );
auto l = form1(_test=Xh);
Name  | 
Parameter  | 
Description  | 
Status  | 
  | 
function space e.g.   | 
define test function space  | 
Required  | 
Here are some examples taken from the Feel++ tutorial.
From mylaplacian.cpp
// right hand side
auto l = form1( _test=Vh );
l = integrate(_range=elements(mesh), _expr=id(v));
From myadvection.cpp
// right hand side
auto l = form1( _test=Xh );
l+= integrate( _range=elements( mesh ), _expr=f*id( v ) );
The operators += and = are supported by linear and bilinear forms.
 | 
auto a1 = form2(_test=Xh,_trial=Xh);
auto a2 = form2(_test=Xh,_trial=Xh);
// operations on a2 ...
// check that they have the same type and
// copy matrix associated to a2 in a1
a1 = a2;
1.1.2. Using form2
To define a bilinear form a: X_h \times X_h \rightarrow \mathbb{R}, for example a(u,v)=\int_\Omega uv
Building form2
The free-function form2 allows you to simply define such a bilinear form using the Feel++ language:
// define function space
auto Xh = ...;
// define a : Xh x Xh -> R
auto a = form2(_trial=Xh, _test=Xh );
// a(u,v) = \int_\Omega u v
a = integrate(_range=elements(mesh), _expr=idt(u)*id(v));
Name  | 
Parameter  | 
Description  | 
Status  | 
  | 
function space e.g.   | 
define test function space  | 
Required  | 
  | 
function space e.g.   | 
define trial function space  | 
Optional  | 
Here are some examples taken from the Feel++ tutorial
From mylaplacian.cpp
// left hand side
auto a = form2( _trial=Vh, _test=Vh );
a = integrate(_range=elements(mesh),
              _expr=gradt(u)*trans(grad(v)) );
From mystokes.cpp:
// left hand side
auto a = form2( _trial=Vh, _test=Vh );
a = integrate(_range=elements(mesh),
              _expr=trace(gradt(u)*trans(grad(u))) );
a+= integrate(_range=elements(mesh),
              _expr=-div(u)*idt(p)-divt(u)*id(p));
see note above on operators += and =
 | 
Solving variational formulations
Once you created your linear and bilinear forms you can use the solve()  member function of your bilinear form.
The following generic example solves: find u \in X_h \text{ such that } a(u,v)=l(v) \forall v \in X_h
auto Xh = ...; // function space
auto u = Xh->element();
auto a = form2(_test=Xh, _trial=Xh);
auto l = form1(_test=Xh);
a.solve(_solution=u, _rhs=l, _rebuild=false, _name="");
Name  | 
Parameter  | 
Description  | 
Status  | 
  | 
element of domain function space  | 
the solution  | 
Required  | 
  | 
linear form  | 
right hand side  | 
Required  | 
  | 
boolean(Default =   | 
rebuild the solver components  | 
Optional  | 
  | 
string(Default = "")  | 
name of the associated Backend  | 
Optional  | 
Here are some examples from the Feel++ tutorial.
laplacian.cpp// solve the equation  a(u,v) = l(v)
a.solve(_rhs=l,_solution=u);
Using on for Dirichlet conditions
The function on()  allows you to add Dirichlet  conditions to your bilinear form before using the solve  function.
The interface is as follows
on(_range=..., _rhs=..., _element=..., _expr=...);
Required Parameters:
- 
_rangedomain concerned by this condition (see Integrals ). - 
_rhsright hand side. The linear form. - 
_elementelement concerned. - 
_exprthe condition. 
This function is used with += operator.
Here are some examples from the Feel++ tutorial.
mylaplacian.cpp// apply the boundary condition
a+=on(_range=boundaryfaces(mesh),
       _rhs=l,
       _element=u,
      _expr=expr(soption("functions.alpha")) );
There we add the condition: u = 0 \text{ on }\;\partial\Omega \;.
mystokes.cppa+=on(_range=boundaryfaces(mesh), _rhs=l, _element=u,
      _expr=expr<2,1,5>(u_exact,syms));
You can also apply boundary conditions per component:
a+=on(_range=markedfaces(mesh,"top"),
      _element=u[Component::Y],
      _rhs=l,
      _expr=cst(0.))
The notation u[Component:Y] allows to access the Y component of
u. Component::X and Component::Z are respectively the X and
Z components.