BESTEST
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 ofmesh_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 namedOmega_roomin 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_ ) );
}