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. In the following, it is adapted for 3D geometry and applied to Bestest benchmark.

The easiest way to do this is the build two separated 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 air (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 air (\(\Omega_r\)) in the description are named Air.

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

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 the 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 ).

The same can be applied to the block-linear form blf_ : to 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 a mesh can be obtained 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 heat and moisture transfers model in volume 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 don’t want to solve the equation related to the room air, the bloc (1_c,1_c) of the bilinear form should not be left emprty. To prevent this, an else statement is added 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_ ) );
}