## 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 `test` function space e.g. `Xh` define test function space Required

Here are some examples taken from the Feel++ tutorial.

``````// 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 `test` function space e.g. `Xh` define test function space Required `trial` function space e.g. `Xh` 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),

From `mystokes.cpp`:

``````// left hand side
auto a = form2( _trial=Vh, _test=Vh );
a = integrate(_range=elements(mesh),
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

Example
``````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 `_solution` element of domain function space the solution Required `_rhs` linear form right hand side Required `_rebuild` boolean(Default = `false`) rebuild the solver components Optional `_name` string(Default = "") name of the associated Backend Optional

Here are some examples from the Feel++ tutorial.

From `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

Interface
``on(_range=..., _rhs=..., _element=..., _expr=...);``

Required Parameters:

• `_range` domain concerned by this condition (see Integrals ).

• `_rhs` right hand side. The linear form.

• `_element` element concerned.

• `_expr` the condition.

This function is used with += operator.

Here are some examples from the Feel++ tutorial.

From `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 \;.

From `mystokes.cpp`
``````a+=on(_range=boundaryfaces(mesh), _rhs=l, _element=u,
_expr=expr<2,1,5>(u_exact,syms));``````

You can also apply boundary conditions per component:

Component-wise Dirichlet conditions
``````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.