TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Terme_Source_Acceleration.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.h>
17
18#include <Probleme_base.h>
19#include <Navier_Stokes_std.h>
20#include <Discretisation_base.h>
21#include <Domaine_VF.h>
22#include <Schema_Temps_base.h>
23
24Implemente_base_sans_constructeur(Terme_Source_Acceleration,"Terme_Source_Acceleration",Source_base);
25// XD acceleration source_base acceleration BRACE Momentum source term to take in account the forces due to rotation or
26// XD_CONT translation of a non Galilean referential R\' (centre 0\') into the Galilean referential R (centre 0).
27// XD attr vitesse field_base vitesse OPT Keyword for the velocity of the referential R\' into the R referential
28// XD_CONT (dOO\'/dt term [m.s-1]). The velocity is mandatory when you want to print the total cinetic energy into the
29// XD_CONT non-mobile Galilean referential R (see Ec_dans_repere_fixe keyword).
30// XD attr acceleration field_base acceleration OPT Keyword for the acceleration of the referential R\' into the R
31// XD_CONT referential (d2OO\'/dt2 term [m.s-2]). field_base is a time dependant field (eg: Champ_Fonc_t).
32// XD attr omega field_base omega OPT Keyword for a rotation of the referential R\' into the R referential [rad.s-1].
33// XD_CONT field_base is a 3D time dependant field specified for example by a Champ_Fonc_t keyword. The time_field field
34// XD_CONT should have 3 components even in 2D (In 2D: 0 0 omega).
35// XD attr domegadt field_base domegadt OPT Keyword to define the time derivative of the previous rotation [rad.s-2].
36// XD_CONT Should be zero if the rotation is constant. The time_field field should have 3 components even in 2D (In 2D:
37// XD_CONT 0 0 domegadt).
38// XD attr centre_rotation field_base centre_rotation OPT Keyword to specify the centre of rotation (expressed in R\'
39// XD_CONT coordinates) of R\' into R (if the domain rotates with the R\' referential, the centre of rotation is
40// XD_CONT 0\'=(0,0,0)). The time_field should have 2 or 3 components according the dimension 2 or 3.
41// XD attr option chaine(into=["terme_complet","coriolis_seul","entrainement_seul"]) option OPT Keyword to specify the
42// XD_CONT kind of calculation: terme_complet (default option) will calculate both the Coriolis and centrifugal forces,
43// XD_CONT coriolis_seul will calculate the first one only, entrainement_seul will calculate the second one only.
44
45
47{
48 /*
49 Noms& nom=champs_compris_.liste_noms_compris();
50 nom.dimensionner(1);
51 nom[0]="ACCELERATION_TERME_SOURCE";
52 */
53}
54
56{
57 Cerr << "Terme_Source_Acceleration::printOn : invalid call" << finl;
58 assert(0);
59 exit();
60 return s;
61}
62
63/*! @brief Call to Terme_Source_Acceleration::lire_data
64 *
65 */
67{
68 Cerr << "Terme_Source_Acceleration::readOn : invalid call" << finl;
69 assert(0);
70 exit();
71 return s;
72}
73
74/*! @brief Method called by readOn of derived classes Terme_Source_Acceleration_VDF_Face, .
75 *
76 * ..
77 *
78 * Expected format:
79 * {
80 * [ omega A_Uniform_Field
81 * domegadt A_Uniform_Field
82 * centre_rotation A_Uniform_Field
83 * option TERME_COMPLET | CORIOLIS_SEUL | ENTRAINEMENT_SEUL ]
84 * [ acceleration A_Uniform_Field ]
85 * }
86 * A_Uniform_Field is typically:
87 * Champ_Uniforme 3 x y z
88 * ou
89 * Champ_Fonc_t DOM 3 fx(t) fy(t) fz(t)
90 *
91 */
92
94{
95 if (je_suis_maitre())
96 Cerr << "Terme_Source_Acceleration::lire_data" << finl;
97
98 Motcles les_mots(7);
99 les_mots[0] = "omega";
100 les_mots[1] = "domegadt";
101 les_mots[2] = "centre_rotation";
102 les_mots[3] = "option";
103 les_mots[4] = "acceleration";
104 les_mots[5] = "}";
105 les_mots[6] = "vitesse";
106
107 Motcle motlu;
108 s >> motlu;
109 if (motlu != "{")
110 {
111 Cerr << "Error in Terme_Source_Acceleration::lire_data" << finl;
112 Cerr << " Expected {" << finl;
113 assert(0);
114 exit();
115 }
116 int fini = 0;
117 while (!fini)
118 {
119 s >> motlu;
120 const int i_mot = les_mots.search(motlu);
121 if (je_suis_maitre() && i_mot < 5)
122 Cerr << "Reading " << motlu << " : ";
123 switch(i_mot)
124 {
125 case 0:
126 s >> omega_;
127 if (je_suis_maitre())
128 Cerr << omega_.que_suis_je() << finl;
129 break;
130 case 1:
131 s >> domegadt_;
132 if (je_suis_maitre())
133 Cerr << domegadt_.que_suis_je() << finl;
134 break;
135 case 2:
136 s >> centre_rotation_;
137 if (je_suis_maitre())
138 Cerr << centre_rotation_.que_suis_je() << finl;
139 break;
140 case 3:
141 {
142 Motcles les_options(3);
143 les_options[0] = "terme_complet";
144 les_options[1] = "coriolis_seul";
145 les_options[2] = "entrainement_seul";
146 s >> motlu;
147 const int i = les_options.search(motlu);
148 switch (i)
149 {
150 case 0:
151 option_ = TERME_COMPLET;
152 break;
153 case 1:
154 option_ = CORIOLIS_SEUL;
155 break;
156 case 2:
157 option_ = ENTRAINEMENT_SEUL;
158 break;
159 default:
160 Cerr << "Error, valid options are: " << finl;
161 Cerr << les_options << finl;
162 assert(0);
163 exit();
164 }
165 if (je_suis_maitre())
166 Cerr << motlu << finl;
167 break;
168 }
169 case 4:
170 s >> champ_acceleration_;
171 if (je_suis_maitre())
172 Cerr << champ_acceleration_.que_suis_je() << finl;
173 break;
174 case 5:
175 fini = 1;
176 break;
177 case 6:
178 s >> champ_vitesse_;
179 if (je_suis_maitre())
180 Cerr << champ_vitesse_.que_suis_je() << finl;
181 break;
182 default:
183 Cerr << "Error in Terme_Source_Acceleration::lire_data" << finl;
184 Cerr << " Keyword not recognized: " << motlu << finl;
185 Cerr << " Recognized keywords are: " << les_mots << finl;
186 assert(0);
187 exit();
188 }
189 }
190
191 // Check consistency:
192 int n = 0;
193 if (omega_) n++;
194 if (domegadt_) n++;
195 if (centre_rotation_) n++;
196 if (n != 0 && n != 3)
197 {
198 Cerr << "Error in Terme_Source_Acceleration::lire_data" << finl;
199 Cerr << " If OMEGA or DOMEGADT or CENTRE_GRAVITE is given" << finl;
200 Cerr << " then all three must be given" << finl;
201 assert(0);
202 exit();
203 }
204 if (n > 0)
205 {
206 if (omega_->valeurs().dimension(0) != 1
207 || domegadt_->valeurs().dimension(0) != 1
208 || omega_->valeurs().dimension(1) != 3
209 || domegadt_->valeurs().dimension(1) != 3)
210 {
211 Cerr << "Error in Terme_Source_Acceleration::lire_data" << finl;
212 Cerr << " the OMEGA and DOMEGADT fields must be uniform fields" << finl;
213 Cerr << " with three components (vector aligned on Z in 2D)" << finl;
214 assert(0);
215 exit();
216 }
217 }
218 if (champ_acceleration_)
219 {
220 if (champ_acceleration_->valeurs().dimension(0) != 1)
221 {
222 Cerr << "Error in Terme_Source_Acceleration::lire_data" << finl;
223 Cerr << " The ACCELERATION field must be a uniform field" << finl;
224 assert(0);
225 exit();
226 }
227 }
228
229 // Discretization of la_source and terme_source_post
230 // This must be done here so that the fields are available at the time
231 // post-processing is read (call to a_pour_Champ_Fonc)
232 {
233 const Equation_base& eqn = equation();
234 if (!sub_type(Navier_Stokes_std, eqn))
235 {
236 Cerr << "Error in Terme_Source_Acceleration::lire_data\n"
237 << " This source term can only be inserted into an equation\n"
238 << " derived from Navier_Stokes_std" << finl;
239 assert(0);
240 exit();
241 }
242 const Discretisation_base& dis = eqn.discretisation();
243 const Domaine_dis_base& domaine = eqn.domaine_dis();
244 const double temps = eqn.schema_temps().temps_courant();
245 dis.discretiser_champ("vitesse", domaine, "acceleration_terme_source", "kg/ms^2",
246 Objet_U::dimension, /* composantes */
247 temps,
248 terme_source_post_);
249 champs_compris_.ajoute_champ(terme_source_post_);
250 }
251}
252
256
258{
259 return terme_source_post_.valeur();
260}
261
263{
264 // terme_source_post_ is mutable, so it can be returned as "non-const"
265 return terme_source_post_.valeur();
266}
267
268/*! @brief Computes the value of the la_source field at faces based on - calculer_vitesse_faces()
269 *
270 * - champ_acceleration_
271 * - omega_
272 * - domegadt_
273 * - centre_rotation_
274 *
275 * @param acceleration_aux_faces a field discretized at elements of the domaine_VF in which the result of the computation is stored. Virtual space up to date.
276 */
277const DoubleTab&
278Terme_Source_Acceleration::calculer_la_source(DoubleTab& acceleration_aux_faces) const
279{
280 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, equation().domaine_dis());;
281
282 const DoubleTab& centre_faces = domaine_VF.xv();
283
284 double a[3] = {0., 0., 0.}; // champ acceleration
285 double w[3] = {0., 0., 0.}; // omega
286 double dw[3] = {0., 0., 0.}; // domegadt
287 double c[3] = {0., 0., 0.}; // centre_gravite
288 const int dim = Objet_U::dimension;
289
290 // ****************************************************************
291 // INITIALIZATION OF a, w, dw, c
292 int rotation_solide = 0;
293 {
294 int j;
295
296 if (champ_acceleration_)
297 {
298 const DoubleTab& a_ = champ_acceleration_->valeurs();
299 for (j = 0; j < dim; j++)
300 a[j] = a_(0, j);
301 }
302
303 if (omega_)
304 {
305 // The user has specified a solid rotation motion
306 const DoubleTab& champ_w = omega_ ->valeurs();
307 const DoubleTab& champ_dw = domegadt_ ->valeurs();
308 const DoubleTab& champ_c = centre_rotation_->valeurs();
309 // Note: in 2D, the rotation vector is typically oriented
310 // in the Z direction: so loop up to 3 in all cases:
311 for (j = 0; j < 3; j++) w[j] = champ_w(0,j);
312 for (j = 0; j < 3; j++) dw[j] = champ_dw(0,j);
313 for (j = 0; j < dim; j++) c[j] = champ_c(0,j);
314 rotation_solide = 1;
315 }
316 }
317
318 // If we have a solid rotation source term, we need the three
319 // components of the fluid velocity at the faces:
320
321 // A storage space for the velocity if it needs to be
322 // computed (in VDF, the three components are computed at each face)
323 DoubleTab vitesse_faces_stockage;
324 // Computation of the velocity field at the faces (from the unknown
325 // of the N.S. equation)
326 const DoubleTab& vitesse_faces =
327 (rotation_solide)
328 ? calculer_vitesse_faces(vitesse_faces_stockage)
329 : vitesse_faces_stockage;
330
331 // **************************************************
332 // LOOP OVER FACES
333 int i_face;
334 const int nb_faces = acceleration_aux_faces.dimension(0);
335
336 // Fluid velocity vector in the current element
337 // (note: Z component initialized for 2D)
338 double v[3] = {0., 0., 0.};
339 // Vector (centre_face - centre_rotation)
340 // (same)
341 double xgr[3] = {0., 0., 0.};
342
343 for (i_face = 0; i_face < nb_faces; i_face++)
344 {
345
346 int j;
347 double src[3];
348 src[0] = -a[0]; // Terme d'acceleration
349 src[1] = -a[1];
350 src[2] = -a[2]; // =0. en 2D
351
352 // Formules identiques en 2D et en 3D :
353 // en 2D, les composantes z de v et xgr sont nulles.
354 if (rotation_solide)
355 {
356 for (j = 0; j < dim; j++) // en 2D, v[3]=0.
357 v[j] = vitesse_faces(i_face, j);
358
359 for (j = 0; j < dim; j++) // en 2D, xgr[3]=0.
360 xgr[j] = centre_faces(i_face, j) - c[j];
361
362 if (option_ != ENTRAINEMENT_SEUL)
363 {
364 src[0] += -2. * (w[1] * v[2] - w[2] * v[1]);
365 src[1] += -2. * (w[2] * v[0] - w[0] * v[2]);
366 src[2] += -2. * (w[0] * v[1] - w[1] * v[0]);
367 src[0] += dw[2] * xgr[1] - dw[1] * xgr[2];
368 src[1] += dw[0] * xgr[2] - dw[2] * xgr[0];
369 src[2] += dw[1] * xgr[0] - dw[0] * xgr[1];
370 }
371 if (option_ != CORIOLIS_SEUL)
372 {
373 src[0] += w[2]*w[2]*xgr[0] - w[0]*w[2]*xgr[2] - w[0]*w[1]*xgr[1] + w[1]*w[1]*xgr[0];
374 src[1] += w[0]*w[0]*xgr[1] - w[0]*w[1]*xgr[0] - w[1]*w[2]*xgr[2] + w[2]*w[2]*xgr[1];
375 src[2] += w[1]*w[1]*xgr[2] - w[1]*w[2]*xgr[1] - w[2]*w[0]*xgr[0] + w[0]*w[0]*xgr[2];
376 }
377 }
378 for (j = 0; j < dim; j++)
379 acceleration_aux_faces(i_face, j) = src[j];
380 }
381 return acceleration_aux_faces;
382}
383
384/*! @brief resu=0; ajouter(resu); (calls ajouter() of the derived class)
385 *
386 */
387DoubleTab& Terme_Source_Acceleration::calculer(DoubleTab& resu) const
388{
389 resu = 0;
390 ajouter(resu);
392 return resu;
393}
394
395/*! @brief Evaluates the acceleration and rotation fields at time t.
396 *
397 */
399{
400 //Cerr << "Terme_Source_Acceleration::mettre_a_jour temps=" << temps << finl;
401 if (champ_acceleration_)
402 champ_acceleration_->mettre_a_jour(temps);
403 if (omega_)
404 {
405 omega_->mettre_a_jour(temps);
406 domegadt_->mettre_a_jour(temps);
407 centre_rotation_->mettre_a_jour(temps);
408 }
410}
411
412/*! @brief Overridden method from Source_base.
413 *
414 * Recognized keywords:
415 * "ACCELERATION" => returns terme_source_post_, homogeneous to d/dt(rho*v)
416 * Beware of the side effect of ajouter() (see comments of ajouter())
417 *
418 */
420 OBS_PTR(Champ_base) & ch_ref) const
421{
422 int ok = 0;
423 if (mot == "ACCELERATION_TERME_SOURCE")
424 {
425 ch_ref = terme_source_post_.valeur();
426 ok = 1;
427 }
428 return ok;
429}
430
431/*! @brief Returns eq_hydraulique_ !
432 *
433 */
435{
436 const Navier_Stokes_std& ns = ref_cast(Navier_Stokes_std, equation());
437 return ns;
438}
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
void mettre_a_jour(double temps) override
Time update of the field.
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
class Discretisation_base This class represents a spatial discretization scheme, which
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
class Domaine_VF
Definition Domaine_VF.h:44
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
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
class Equation_base The role of an equation is the calculation of one or more fields....
const Discretisation_base & discretisation() const
Returns the discretization associated with the equation.
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
Domaine_dis_base & domaine_dis()
Returns the discretized domain associated with the equation.
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
OBS_PTR(Equation_base) mon_equation
A character string (Nom) in uppercase.
Definition Motcle.h:26
An array of Motcle objects.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:319
Navier_Stokes_std This class carries the terms of the momentum equation.
friend class Entree
Definition Objet_U.h:71
static int dimension
Definition Objet_U.h:94
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 Probleme_base It is a Probleme_U that is not a coupling.
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
double temps_courant() const
Returns the current time.
Base class for output streams.
Definition Sortie.h:52
Source_base A Source_base object is a term appearing on the right-hand side of an.
Definition Source_base.h:42
Champs_compris champs_compris_
virtual DoubleTab & ajouter(DoubleTab &) const
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
virtual const Navier_Stokes_std & get_eq_hydraulique() const
Returns eq_hydraulique_ !
DoubleTab & calculer(DoubleTab &) const override
resu=0; ajouter(resu); (calls ajouter() of the derived class)
const DoubleTab & calculer_la_source(DoubleTab &src_faces) const
Computes the value of the la_source field at faces based on - calculer_vitesse_faces().
int a_pour_Champ_Fonc(const Motcle &mot, OBS_PTR(Champ_base) &ch_ref) const override
Overridden method from Source_base.
virtual const DoubleTab & calculer_vitesse_faces(DoubleTab &stockage) const =0
void mettre_a_jour(double temps) override
Evaluates the acceleration and rotation fields at time t.
void associer_pb(const Probleme_base &) override
virtual Champ_Fonc_base & get_set_terme_source_post() const
virtual const Champ_Fonc_base & get_terme_source_post() const
virtual void lire_data(Entree &s)
Method called by readOn of derived classes Terme_Source_Acceleration_VDF_Face, .