TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Masse_DG_base.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Masse_DG_base.h>
17#include <Domaine_Cl_DG.h>
18#include <Domaine_DG.h>
19#include <Equation_base.h>
20#include <Milieu_base.h>
21#include <BasisFunction.h>
22
23Implemente_base(Masse_DG_base, "Masse_DG_base", Solveur_Masse_base);
24Sortie& Masse_DG_base::printOn(Sortie& s) const { return s << que_suis_je() << " " << le_nom(); }
25Entree& Masse_DG_base::readOn(Entree& s) { return s; }
26
28{
29 le_dom_dg_ = ref_cast(Domaine_DG, le_dom_dis_base);
30}
31
33{
34 le_dom_Cl_dg_ = ref_cast(Domaine_Cl_DG, le_dom_Cl_dis_base);
35}
36
37/**
38 * @brief Multiplies the mass coefficient vector element-wise by an optional temporal field.
39 *
40 * @details If a temporal coefficient has been registered (has_coefficient_temporel_ == true),
41 * the field named name_of_coefficient_temporel_ is retrieved from the equation and its
42 * values are applied to coef via tab_multiply_any_shape(). Three field types are handled:
43 * - Champ_Inc_base: uses the first part of the field's values (ConstDoubleTab_parts[0]).
44 * - Champ_Fonc_base: uses the field's values directly.
45 * - Champ_Don_base: evaluates the field at the unknown's node coordinates.
46 * If no temporal coefficient is registered, coef is left unchanged.
47 *
48 * @param coef The coefficient vector to scale in-place (typically initialized to 1).
49 */
50void Masse_DG_base::appliquer_coef(DoubleVect& coef) const
51{
53 {
54 OBS_PTR(Champ_base) ref_coeff;
56
57 DoubleTab values;
58 if (sub_type(Champ_Inc_base,ref_coeff.valeur()))
59 {
60 const Champ_Inc_base& coeff = ref_cast(Champ_Inc_base,ref_coeff.valeur());
61 ConstDoubleTab_parts val_parts(coeff.valeurs());
62 values.ref(val_parts[0]);
63
64 }
65 else if (sub_type(Champ_Fonc_base,ref_coeff.valeur()))
66 {
67 const Champ_Fonc_base& coeff = ref_cast(Champ_Fonc_base,ref_coeff.valeur());
68 values.ref(coeff.valeurs());
69
70 }
71 else if (sub_type(Champ_Don_base,ref_coeff.valeur()))
72 {
73 DoubleTab nodes;
75 ref_coeff->valeur_aux(nodes,values);
76 }
77 tab_multiply_any_shape(coef, values, VECT_REAL_ITEMS);
78 }
79}
80
81/**
82 * @brief Builds the sparsity pattern of the mass matrix block.
83 *
84 * @details The pattern depends on whether the basis is orthonormalized:
85 * - **Orthonormal basis**: purely diagonal — one non-zero per DOF
86 * (indice(k,0) == indice(k,1) for every k).
87 * - **Non-orthonormal basis**: full local block — every pair (i,j) within
88 * the same element and same spatial component is coupled.
89 *
90 * The number of spatial components (dim) is set to Objet_U::dimension for
91 * velocity unknowns and 1 for all other fields (scalar).
92 *
93 * @param matrices Map of matrix name → Matrice_Morse pointer to be sized.
94 * @param semi_impl Unused here; kept for interface compatibility.
95 */
96void Masse_DG_base::dimensionner_blocs(matrices_t matrices, const tabs_t& semi_impl) const
97{
98 const Nom& nom_inco = equation().inconnue().le_nom();
99 if (!matrices.count(nom_inco.getString())) return; //rien a faire
100
101 int order = Option_DG::Get_order_for(nom_inco);
102 int dim = nom_inco.debute_par("vitesse") ? Objet_U::dimension : 1;
103
104 const BasisFunction& bfunc = le_dom_dg_->get_basisFunction(order);
105 const int nb_bfunc = bfunc.nb_bfunc();
106
107 Matrice_Morse& mat = *matrices.at(nom_inco.getString());
108 const int nb_elem_tot = le_dom_dg_->nb_elem_tot();
109
110 int size_indices = le_dom_dg_->gram_schmidt() ? nb_elem_tot*dim*nb_bfunc : nb_elem_tot*dim*nb_bfunc*nb_bfunc;
111
112 IntTab indice(size_indices, 2);
113 int current_indice = 0;
114 if (le_dom_dg_->gram_schmidt())
115 {
116 for (int e = 0; e < nb_elem_tot; e++)
117 {
118 for (int d = 0; d<dim; d++)
119 {
120 for (int i = 0; i < nb_bfunc; i++ )
121 {
122 indice(current_indice+i, 0) = current_indice+i;
123 indice(current_indice+i, 1) = current_indice+i;
124 }
125 current_indice+=nb_bfunc;
126 }
127 }
128 }
129 else
130 {
131 int index = 0;
132 for (int e = 0; e < nb_elem_tot; e++)
133 {
134 for (int d = 0; d<dim; d++)
135 {
136 for (int i = 0; i < nb_bfunc; i++ )
137 for (int j = 0; j < nb_bfunc; j++ )
138 {
139 indice(index, 0) = current_indice+i;
140 indice(index, 1) = current_indice+j;
141 index++;
142 }
143 current_indice+=nb_bfunc;
144 }
145 }
146 }
147 mat.dimensionner(indice);
148}
149
150/**
151 * @brief Assembles the mass matrix contribution (M/dt) into the matrix and right-hand side.
152 *
153 * @details Computes and accumulates the term (M/dt) * u into the global system,
154 * where M is the L2 mass matrix and dt is the time step. The assembly strategy
155 * depends on whether the basis is orthonormalized:
156 *
157 * - **Orthonormal basis** (gram_schmidt == true):
158 * The mass matrix is diagonal with entries coef[e] * volume[e]. For each DOF:
159 * mat(dof, dof) += coef[e] * volume[e] / dt
160 * secmem(e, dof) += coef[e] * volume[e] * (u^n - delta * u^{n+1}) / dt
161 * where delta = resoudre_en_increments (1 if solving for the increment, 0 otherwise).
162 *
163 * - **Non-orthonormal basis, order 0**: reduces to a single scalar per element
164 * (one DOF), equivalent to the cell-average finite volume mass term.
165 *
166 * - **Non-orthonormal basis, order > 0**: the full local mass matrix M_ij is
167 * assembled by Gaussian quadrature (Ern, Finite Elements II, 2021, p.71):
168 * M_ij = integral of phi_i * phi_j
169 * accumulated as mat(i,j) += coef[e] * M_ij / dt and the corresponding RHS term.
170 *
171 * The temporal coefficient (e.g., density) is applied via appliquer_coef() before
172 * the loop, and the medium porosity is used as the base coefficient array.
173 *
174 * @param matrices Map of matrix name → Matrice_Morse pointer to accumulate into.
175 * @param secmem Right-hand side to accumulate into.
176 * @param dt Current time step size.
177 * @param semi_impl Map of semi-implicit field values; if the unknown is present,
178 * its values are used as u^n instead of the stored past values.
179 * @param resoudre_en_increments If 1, the system is solved for the increment (u^{n+1} - u^n);
180 * the current solution is subtracted from the RHS accordingly.
181 */
182void Masse_DG_base::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, double dt, const tabs_t& semi_impl, int resoudre_en_increments) const
183{
184 const Nom& nom_inco = equation().inconnue().le_nom();
185 const std::string& nom_inco_str = equation().inconnue().le_nom().getString();
186 const DoubleTab& passe = semi_impl.count(nom_inco_str) ? semi_impl.at(nom_inco_str) : equation().inconnue().passe();
187 const DoubleTab& inco = equation().inconnue().valeurs();
188 Matrice_Morse *mat = matrices.count(nom_inco_str) ? matrices.at(nom_inco_str) : nullptr;
189
190 int order = Option_DG::Get_order_for(nom_inco);
191 int dim = nom_inco.debute_par("vitesse") ? Objet_U::dimension : 1;
192
193 const BasisFunction& bfunc = le_dom_dg_->get_basisFunction(order);
194 const int nb_bfunc = bfunc.nb_bfunc();
195
196 assert(nb_bfunc*dim == inco.line_size());
197
198 const int quad_order = bfunc.get_default_quadrature_order();
199 const Quadrature_base& quad = le_dom_dg_->get_quadrature(quad_order);
200
201 const DoubleVect& volume = le_dom_dg_->volumes();
202 const int nb_elem_tot = inco.dimension_tot(0);
203
204 int nb_pts_integ_max = quad.nb_pts_integ_max();
205 const IntTab& tab_pts_integ= quad.get_tab_nb_pts_integ();
206
207 DoubleTab fbase(nb_bfunc, nb_pts_integ_max);
208 DoubleTab product(nb_pts_integ_max);
209
210 DoubleTrav coef(equation().milieu().porosite_elem());
211 coef = 1.;
212 appliquer_coef(coef);
213
214 int current_indice = 0;
215 if (le_dom_dg_->gram_schmidt())
216 {
217 for (int e = 0; e < nb_elem_tot; e++)
218 {
219 for (int i=0; i<nb_bfunc; i++)
220 {
221 for (int d = 0; d<dim; d++)
222 {
223 if (mat)
224 (*mat)(current_indice+i+d*nb_bfunc, current_indice+i+d*nb_bfunc) += coef[e]*volume[e] / dt;
225 secmem(e,i+d*nb_bfunc) += coef[e]*volume[e]*(passe(e,i+d*nb_bfunc) - resoudre_en_increments*inco(e,i+d*nb_bfunc))/ dt;
226 }
227 }
228 current_indice+=nb_bfunc*dim;
229 }
230 }
231 else
232 {
233 for (int e = 0; e < nb_elem_tot; e++)
234 {
235 if (order == 0)
236 for (int d = 0; d<dim; d++)
237 {
238 if (mat)
239 (*mat)(current_indice+d, current_indice+d) += coef[e]*volume[e] / dt;
240 secmem(e,d) += coef[e]*volume[e]*(passe(e,d)-resoudre_en_increments*inco(e,d)) / dt;
241 current_indice+=nb_bfunc;
242 }
243 else
244 {
245 bfunc.eval_bfunc(quad, e, fbase);
246 /****************************************************************/
247 /* Formule de quadrature : Ern, Finite Elements II, 2021, p 71 */
248 /****************************************************************/
249 for (int i=0; i<nb_bfunc; i++)
250 {
251 for (int j=0; j<nb_bfunc; j++)
252 {
253 product = 0.;
254 for (int k = 0; k < tab_pts_integ(e) ; k++)
255 product(k) = fbase(i, k) * fbase(j, k);
256
257 double integral = quad.compute_integral_on_elem(e, product);
258
259 for (int d = 0; d<dim; d++)
260 {
261 if (mat)
262 (*mat)(current_indice+i+d*nb_bfunc, current_indice+j+d*nb_bfunc) += coef[e]*integral / dt;
263 secmem(e,i+d*nb_bfunc) += coef[e]*integral*(passe(e,j+d*nb_bfunc) - resoudre_en_increments*inco(e,j+d*nb_bfunc)) / dt;
264 }
265 }
266 }
267 current_indice+=nb_bfunc*dim;
268 }
269 }
270 }
271}
Manages the local polynomial basis functions for Discontinuous Galerkin elements.
void eval_bfunc(const Quadrature_base &quad, const int &nelem, DoubleTab &fbasis) const
Evaluates all basis functions at the element quadrature points.
const int & nb_bfunc() const
const int & get_default_quadrature_order() const
classe Champ_Don_base classe de base des Champs donnes (non calcules)
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
Classe Champ_Inc_base.
DoubleTab & passe(int i=1) override
Renvoie les valeurs du champs a l'instant t-i.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & remplir_coord_noeuds(DoubleTab &) const =0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Champ_Inc_base & inconnue() const =0
const Champ_base & get_champ(const Motcle &nom) const override
const Nom & le_nom() const override
Renvoie le nom du champ.
Abstract base class for the DG mass matrix operator.
void associer_domaine_cl_dis_base(const Domaine_Cl_dis_base &) override
OBS_PTR(Domaine_DG) le_dom_dg_
void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl) const override
Builds the sparsity pattern of the mass matrix block.
void associer_domaine_dis_base(const Domaine_dis_base &) override
void appliquer_coef(DoubleVect &coef) const
Multiplies the mass coefficient vector element-wise by an optional temporal field.
void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, double dt, const tabs_t &semi_impl, int resoudre_en_increments) const override
Assembles the mass matrix contribution (M/dt) into the matrix and right-hand side.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
void dimensionner(int n, _SIZE_ nnz)
Size the matrix with n lines and n columns and nnz zero-values coefficients.
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
virtual int debute_par(const char *const n) const
Definition Nom.cpp:319
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
static int Get_order_for(const Nom &n)
Definition Option_DG.cpp:70
int nb_pts_integ_max() const
const IntTab & get_tab_nb_pts_integ() const
double compute_integral_on_elem(int num_elem, Parser_U &parser) const
classe Solveur_Masse_base Represente la matrice de masse d'une equation.
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual void ref(const TRUSTTab &)
Definition TRUSTTab.tpp:308
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
int line_size() const
Definition TRUSTVect.tpp:67