BESTEST
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 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 a mesh can be obtained 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 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_ ) );
}