TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Terme_Source_Acceleration_VDF_Face.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 <Terme_Source_Acceleration_VDF_Face.h>
17#include <Navier_Stokes_std.h>
18#include <Champ_Fonc_P0_VDF.h>
19#include <Milieu_base.h>
20
21#include <Domaine_Cl_VDF.h>
22#include <Periodique.h>
23#include <Domaine_VDF.h>
24
25Implemente_instanciable(Terme_Source_Acceleration_VDF_Face,"Acceleration_VDF_Face",Terme_Source_Acceleration);
26
28{
29 return s << que_suis_je() ;
30}
31
32/*! @brief Appel a Terme_Source_Acceleration::lire_data
33 *
34 */
36{
37 lire_data(s);
38 return s;
39}
40
41/*! @brief Method called by Source_base::completer() after associer_domaines. Fills the refs.
42 *
43 * to domaines and domaine_cl.
44 *
45 */
47 const Domaine_Cl_dis_base& domaine_Cl_dis)
48{
49 if (je_suis_maitre())
50 Cerr << "Terme_Source_Acceleration_VDF_Face::associer_domaines" << finl;
51 le_dom_VDF_ = ref_cast(Domaine_VDF, domaine_dis);
52 le_dom_Cl_VDF_ = ref_cast(Domaine_Cl_VDF, domaine_Cl_dis);
53}
54
55/*! @brief Utility function for Terme_Source_Acceleration_VDF_Face::ajouter. Adds contributions of a contiguous list of faces of the translation source term:
56 *
57 * s_face = terme_source * rho
58 * resu += integral (s_face) over the velocity control volume.
59 * Handles the following cases:
60 * rho = null reference (=> rho = 1.) otherwise rho != null
61 * boundary faces => free outlet
62 * periodicity
63 * internal_faces
64 *
65 */
66static void TSAVDF_ajouter_liste_faces(const int premiere_face, const int derniere_face,
67 const DoubleVect& volumes_entrelaces,
68 const DoubleVect& volumes_elements,
69 const DoubleVect& porosite_surf,
70 const IntVect& orientation,
71 const IntTab& face_voisins,
72 const OBS_PTR(Champ_base) & ref_rho,
73 const DoubleTab& terme_source,
74 DoubleTab& s_face,
75 DoubleTab& resu)
76{
77 int num_face;
78 // Constant pointer to constant array.
79 // Null pointer if ref_rho_ is a null reference.
80 const DoubleTab * const rho_elem =
81 (bool(ref_rho)) ? &(ref_rho->valeurs()) : 0;
82
83 for (num_face=premiere_face; num_face<derniere_face; num_face++)
84 {
85 const double vol = volumes_entrelaces(num_face)*porosite_surf(num_face);
86 const int ncomp = orientation(num_face);
87 const double src = terme_source(num_face, ncomp);
88
89 double rho = 1.;
90
91 // Compute an average rho over the velocity control volume
92 if (rho_elem)
93 {
94 const int elem0 = face_voisins(num_face,0);
95 const int elem1 = face_voisins(num_face,1);
96 double rho0 = 0, rho1 = 0, vol0 = 0, vol1 = 0;
97 if (elem0 >= 0)
98 {
99 rho0 = (*rho_elem)(elem0);
100 vol0 = volumes_elements(elem0);
101 }
102 if (elem1 >= 0)
103 {
104 rho1 = (*rho_elem)(elem1);
105 vol1 = volumes_elements(elem1);
106 }
107 rho = (rho0 * vol0 + rho1 * vol1) / (vol0 + vol1);
108 }
109
110 double a = src * rho;
111 s_face(num_face) = a;
112 // Integral over the control volume:
113 resu(num_face) += a * vol;
114 }
115}
116
117/*! @brief Adds the term (la_source_ * rho * volume_entrelace) to the field resu.
118 *
119 * Assumes that resu is discretized like the velocity in VDF.
120 * Side effect:
121 * Sets (la_source_ * rho) in terme_source_post_
122 *
123 */
124void Terme_Source_Acceleration_VDF_Face::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl) const
125{
126 const Domaine_VDF& domaine_VDF = le_dom_VDF_.valeur();
127 const Domaine_Cl_VDF& domaine_Cl_VDF = le_dom_Cl_VDF_.valeur();
128 const IntTab& face_voisins = domaine_VDF.face_voisins();
129 const IntVect& orientation = domaine_VDF.orientation();
130 const DoubleVect& porosite_surf = equation().milieu().porosite_face();
131 const DoubleVect& volumes_entrelaces = domaine_VDF.volumes_entrelaces();
132
133 DoubleTab& s_face = get_set_terme_source_post().valeurs();
134 s_face = 0.;
135
136 // Compute la_source_ from the acceleration fields and the
137 // fluid velocity.
138 const int dim = Objet_U::dimension;
139 const int nb_faces = secmem.dimension(0);
140 DoubleTab acceleration_aux_faces(nb_faces, dim);
141 calculer_la_source(acceleration_aux_faces);
142
143 // Loop over boundary conditions to process boundary faces
144
145 for (int n_bord=0; n_bord<domaine_VDF.nb_front_Cl(); n_bord++)
146 {
147 // for each boundary condition, check its type
148 // If Dirichlet or Symmetry face, do nothing
149 // If Neumann face, compute the contribution to the source term
150 const Cond_lim& la_cl = domaine_Cl_VDF.les_conditions_limites(n_bord);
151 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
152 const int ndeb = le_bord.num_premiere_face();
153 const int nfin = ndeb + le_bord.nb_faces();
154 TSAVDF_ajouter_liste_faces(ndeb, nfin,
155 volumes_entrelaces,
156 le_dom_VDF_->volumes(),
157 porosite_surf,
158 orientation,
159 face_voisins,
160 ref_rho_,
161 acceleration_aux_faces,
162 s_face,
163 secmem);
164 }
165
166
167 // Loop over internal faces
168 {
169 const int ndeb = domaine_VDF.premiere_face_int();
170 const int nfin = domaine_VDF.nb_faces();
171 TSAVDF_ajouter_liste_faces(ndeb, nfin,
172 volumes_entrelaces,
173 le_dom_VDF_->volumes(),
174 porosite_surf,
175 orientation,
176 face_voisins,
177 ref_rho_,
178 acceleration_aux_faces,
179 s_face,
180 secmem);
181 }
182 {
183 // Force la periodicite
184 for (int n_bord=0; n_bord<domaine_VDF.nb_front_Cl(); n_bord++)
185 {
186 const Cond_lim& la_cl = domaine_Cl_VDF.les_conditions_limites(n_bord);
187 if (sub_type(Periodique,la_cl.valeur()))
188 {
189 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
190 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
191 int nb_faces_bord=le_bord.nb_faces();
192 ArrOfInt fait(nb_faces_bord);
193 fait = 0;
194 for (int ind_face=0; ind_face<nb_faces_bord; ind_face++)
195 {
196 if (fait[ind_face] == 0)
197 {
198 int ind_face_associee = la_cl_perio.face_associee(ind_face);
199 fait[ind_face] = 1;
200 fait[ind_face_associee] = 1;
201 int face = le_bord.num_face(ind_face);
202 int face_associee = le_bord.num_face(ind_face_associee);
203 double val = 0.5*(secmem(face_associee)+secmem(face));
204 secmem(face)=secmem(face_associee) = val;
205 }// if fait
206 }// for face
207 }// sub_type Perio
208 }
209 }
210}
211
212/*! @brief Computes the three components of the fluid velocity field at the center of each face.
213 *
214 * The result is stored in v_faces_stockage and a reference to
215 * the array is returned. No virtual space in the array.
216 * The normal component to the face is already known: it is the discrete value.
217 * The other components are computed by averaging the velocities
218 * of the neighbouring element faces with the correct orientation, weighted
219 * by the element volume.
220 * Boundary treatment: take the velocity of the neighbouring element (a priori
221 * not correct for velocity-imposed boundary conditions at the boundary,
222 * but vpoint is corrected afterward to impose the velocity).
223 *
224 */
226 DoubleTab& v_faces_stockage) const
227{
228 const Domaine_VDF& domaine_VDF = le_dom_VDF_.valeur();
229 const IntVect& orientation = domaine_VDF.orientation();
230 const IntTab& faces_voisins = domaine_VDF.face_voisins();
231 const DoubleVect& volumes = domaine_VDF.volumes(); // element volumes
232 const IntTab& elem_faces = domaine_VDF.elem_faces();
233 const DoubleTab& v_faces = get_eq_hydraulique().inconnue().valeurs();
234 const int dim = Objet_U::dimension;
235 const int nb_faces = v_faces.dimension(0);
236 v_faces_stockage.resize(nb_faces, dim);
237 int i_face;
238 ArrOfDouble composante_vitesse(3);
239 for (i_face = 0; i_face < nb_faces; i_face++)
240 {
241 const int orientation_face = orientation(i_face);
242 composante_vitesse=0;
243 int composante;
244
245 // Indices of the two neighbouring elements of the face (-1 if boundary face)
246 int elem[2];
247 elem[0] = faces_voisins(i_face, 0);
248 elem[1] = faces_voisins(i_face, 1);
249
250 // Volumes of these two elements (0. if no neighbour)
251 double volume_elem[2] = {0., 0.};
252 if (elem[0] >= 0)
253 volume_elem[0] = volumes(elem[0]);
254 if (elem[1] >= 0)
255 volume_elem[1] = volumes(elem[1]);
256
257 const double i_volume_total = 1. / (volume_elem[0] + volume_elem[1]);
258
259 for (composante = 0; composante < dim; composante++)
260 {
261 if (composante == orientation_face)
262 {
263 composante_vitesse[composante] = v_faces(i_face);
264 }
265 else
266 {
267 // Compute the average of velocities on the neighbouring faces
268 // that have the correct orientation:
269 composante_vitesse[composante] = 0.;
270 int i_elem;
271 for (i_elem = 0; i_elem < 2; i_elem++)
272 {
273 if (elem[i_elem] >= 0)
274 {
275 const int element = elem[i_elem];
276 const int face1 = elem_faces(element, composante);
277 const int face2 = elem_faces(element, composante + dim);
278 const double v1 = v_faces(face1);
279 const double v2 = v_faces(face2);
280 const double p = volume_elem[i_elem]; // Ponderation par le volume
281 composante_vitesse[composante] += (v1 + v2) * 0.5 * p;
282 }
283 }
284 composante_vitesse[composante] *= i_volume_total;
285 }
286 }
287 for (composante = 0; composante < dim; composante++)
288 {
289 v_faces_stockage(i_face, composante) = composante_vitesse[composante];
290 }
291 }
292 return v_faces_stockage;
293}
294
295/*! @brief Associates the density field. The computed source term will then be homogeneous to d/dt(integral(rho*v)).
296 *
297 * @param champ_rho a field of type Champ_Fonc_P0_VDF that will be used during calls to "ajouter()" to evaluate the density.
298 */
299
301{
302 // The field must be discretized at elements: possibility
303 // to allow other types if needed (Champ_Don, Champ_Inc, etc.)
304 // as long as they are P0 fields.
305 if (!sub_type(Champ_Fonc_P0_VDF, champ_rho))
306 {
307 Cerr << "Error in Terme_Source_Acceleration_VDF_Face::associer_champ_rho" << finl;
308 Cerr << " The density field must be of type Champ_Fonc_P0_VDF" << finl;
309 Cerr << " Type of the associated field: " << champ_rho.que_suis_je() << finl;
310 Cerr << " Name of the associated field: " << champ_rho.le_nom() << finl;
311 assert(0);
312 exit();
313 }
314 ref_rho_ = champ_rho;
315}
316
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
class Champ_Fonc_P0_VDF
DoubleTab & valeurs() override
Returns the array of field values at the current time.
virtual DoubleTab & valeurs()=0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
class Domaine_Cl_VDF
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
class Domaine_VDF
Definition Domaine_VDF.h:61
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
double volumes(int i) const
Definition Domaine_VF.h:113
int elem_faces(int i, int j) const
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
int nb_front_Cl() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
const Nom & le_nom() const override
Returns the name of the field.
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
int num_face(const int) const
Definition Front_VF.h:68
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
const Champ_Inc_base & inconnue() const override
Returns the velocity (unknown field of the equation) (const version).
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 Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
Base class for output streams.
Definition Sortie.h:52
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
Terme source d'acceleration specialise pour la discretisation VDF.
void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl) const override
Adds the term (la_source_ * rho * volume_entrelace) to the field resu.
void associer_domaines(const Domaine_dis_base &, const Domaine_Cl_dis_base &) override
Method called by Source_base::completer() after associer_domaines. Fills the refs.
const DoubleTab & calculer_vitesse_faces(DoubleTab &v_faces_stockage) const override
Computes the three components of the fluid velocity field at the center of each face.
void associer_champ_rho(const Champ_base &champ_rho) override
Associates the density field. The computed source term will then be homogeneous to d/dt(integral(rho*...
virtual const Navier_Stokes_std & get_eq_hydraulique() const
Returns eq_hydraulique_ !
const DoubleTab & calculer_la_source(DoubleTab &src_faces) const
Computes the value of the la_source field at faces based on - calculer_vitesse_faces().
virtual Champ_Fonc_base & get_set_terme_source_post() const
virtual void lire_data(Entree &s)
Method called by readOn of derived classes Terme_Source_Acceleration_VDF_Face, .