# BESTEST

 This page contains some technical details of the benchmark Bestest. See this page for the complete description, and the results of this benchmark. The complete model can be found here.

## 1. From 2D to 3D

Previously, the application `feelpp_hm_heat_moisture` worked only for two-dimensional geometries. For the simulations we want to make for Bestest, we need to use a three-dimensional geometry.

The easiest way to do it is the build two separates programs : `feelpp_hm_heat_moisture_2d` and `feelpp_hm_heat_moisture_3d`. In the beginning, the mesh was declared in the code with

``auto mesh = loadMesh( _mesh=new Mesh<Simplex<2>> );``

the `2` standing for the dimension. To work in 3D, we just have to replace this `2` by a `3`. The line is replaced in the code by

``auto mesh = loadMesh( _mesh=new Mesh<Simplex<FEELPP_DIM>> );``

The macro `FEELPP_DIM` is declared at the compilation with CMake with

``feelpp_add_application(heat_moisture_3d SRCS hm_main.cpp hm_options.cpp DEFS FEELPP_DIM=3)``

## 2. Resolution with Feel++

To solve such a problem with Feel++, we use product spaces. The space for heat in the walls is approximated by `Xh_ = Pch<1>` (polynomials of degree 1 on each element of the mesh), and the space for the heat in the room (which is constant) is approximated by `Wh_ = Pch<0>`. The space product is defined in Feel++ by the line

``ps_ = product (Xh_, Wh_) ;``

In the code (and therefore in the JSON file), the markers of the domains corresponding to the room ($\Omega_r$) in the description are named `Air`.

The principle of resolution of the variational problem is similar to was is done with a « simple » space, but we use here `blockform2` and `blockform1` (instead of `form2` and `form1`) to set the bilinear and linear forms used.

In the code, the `blockform2` is called `bbf_`. To set this form, we use the objects `0_c` and `1_c`, representing respectively the first and second row/column of the block-bilinear form.

To set the part of the variational problem corresponding to `Xh_`, we use `bbf_( 0_c,0_c )`, and on `Wh_` it is `bbf_( 1_c,1_c )`.

It works the same way for the block-linear form `blf_` : the set the member associated with `Xh_` (respectively `Wh_`) we use `blf_(0_c)` (resp. `blf_(1_c)`).

The `solve` function will solve the bloc problem, and we just have to get the two separate solutions, for the wall, and the room :

``````void solve()
{
auto T = this->ps_.element();
this->bbf_.solve( _solution = T, _rhs = this->blf_ );
T_  = T( 0_c );
Ta_ = T( 1_c );
}``````

The mesh `mesh_` from the geometry is divided into two meshes :

• `trace_mesh_` which corresponds to the submesh of `mesh_` containing the borders between the room and the wall. The marker of those faces has to be `"Air"`.

• `wall_mesh_` containing all the elements of the wall. Such mesh can be get with the complement of the room, which will be named `Omega_room` in the geometry (see here, on section 1.3 for more information about complement).

A distinction have to be done : for the previous cases (such as moisture-uptake), the coupling between the room and the wall mustn’t be taken. All the terms of the variationnal problem which are related to the air tranfer model are grouped in a `if` loop :

``if ( this->mesh_->hasAnyMarker( { "Air" } ) ) { ... }``

All the terms in this loop are the terms of the variational problem that are on $\Gamma_i$, and on $\Omega_r$.

Furthermore, if we are not on a case where we want to simulate in the room, we cannot let the bloc `(1_c,1_c)` of the bilinear form empty to avoid it, we just add an `else` statement to the `if ( this→mesh_→hasAnyMarker( { "Air" } ) )`

``````else {
this->bbf_( 1_c, 1_c ) += integrate( _range = boundaryfaces( this->mesh() ), _expr = id( Ta_ ) * idt( Ta_ ) );
this->blf_( 1_c ) += integrate( _range = boundaryfaces( this->mesh() ), _expr = idt( Ta_ ) );
}``````