TrioCFD 1.9.9_beta
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; //nothing to do
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 /* Quadrature formula: 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
class Champ_Don_base base class of Given Fields (not calculated)
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
Class Champ_Inc_base.
DoubleTab & passe(int i=1) override
Returns field values at instant t-i.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
virtual DoubleTab & remplir_coord_noeuds(DoubleTab &) const =0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
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
Returns the name of the field.
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.
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
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
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
virtual int debute_par(const char *const n) const
Definition Nom.cpp:314
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:94
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual const Nom & le_nom() const
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Objet_U.cpp:317
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
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
Compute the integral of a function on one triangle.
Solveur_Masse_base Represents the mass matrix of an equation.
Base class for output streams.
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