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