TrioCFD 1.9.8
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 : appel invalide" << finl;
58 assert(0);
59 exit();
60 return s;
61}
62
63/*! @brief Appel a Terme_Source_Acceleration::lire_data
64 *
65 */
67{
68 Cerr << "Terme_Source_Acceleration::readOn : appel invalide" << finl;
69 assert(0);
70 exit();
71 return s;
72}
73
74/*! @brief Methode appelee par readOn des classes derivees Terme_Source_Acceleration_VDF_Face, .
75 *
76 * ..
77 *
78 * Le format attendu est le suivant
79 * {
80 * [ omega Un_Champ_uniforme
81 * domegadt Un_Champ_uniforme
82 * centre_rotation Un_Champ_uniforme
83 * option TERME_COMPLET | CORIOLIS_SEUL | ENTRAINEMENT_SEUL ]
84 * [ acceleration Un_Champ_uniforme ]
85 * }
86 * Un_Champ_uniforme est typiquement:
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 << "Erreur dans Terme_Source_Acceleration::lire_data" << finl;
112 Cerr << " On attendait {" << 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 << "Lecture de " << 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 << "Erreur, les options valides sont : " << 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 << "Erreur dans Terme_Source_Acceleration::lire_data" << finl;
184 Cerr << " On ne comprend pas le mot " << motlu << finl;
185 Cerr << " Les mots compris sont : " << les_mots << finl;
186 assert(0);
187 exit();
188 }
189 }
190
191 // On verifie que c'est coherent:
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 << "Erreur dans Terme_Source_Acceleration::lire_data" << finl;
199 Cerr << " Si OMEGA ou DOMEGADT ou CENTRE_GRAVITE est donne" << finl;
200 Cerr << " alors les trois doivent etre donnes" << 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 << "Erreur dans Terme_Source_Acceleration::lire_data" << finl;
212 Cerr << " les champs OMEGA et DOMEGADT doivent etre des champs" << finl;
213 Cerr << " uniformes a trois composantes (vecteur aligne sur Z en 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 << "Erreur dans Terme_Source_Acceleration::lire_data" << finl;
223 Cerr << " Le champ ACCELERATION doit etre un champ uniforme" << finl;
224 assert(0);
225 exit();
226 }
227 }
228
229 // Discretisation de la_source et terme_source_post
230 // Il faut absolument le faire ici pour disposer des champs au moment de
231 // la lecture des postraitements (appel a a_pour_Champ_Fonc)
232 {
233 const Equation_base& eqn = equation();
234 if (!sub_type(Navier_Stokes_std, eqn))
235 {
236 Cerr << "Erreur dans Terme_Source_Acceleration::lire_data\n"
237 << " Ce terme source ne peut etre insere que dans une equation\n"
238 << " derivee de 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_ est mutable, on peut donc le renvoyer "non const"
265 return terme_source_post_.valeur();
266}
267
268/*! @brief Calcul de la valeur du champ la_source aux faces en fonction de - calculer_vitesse_faces()
269 *
270 * - champ_acceleration_
271 * - omega_
272 * - domegadt_
273 * - centre_rotation_
274 *
275 * @param (champ_source) un champ discretise aux elements du domaine_VF dans lequel on stocke le resultat du calcul. Espace virtuel a jour.
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 // INITIALISATION DE 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 // L'utilisateur a specifie un mouvement de rotation solide
306 const DoubleTab& champ_w = omega_ ->valeurs();
307 const DoubleTab& champ_dw = domegadt_ ->valeurs();
308 const DoubleTab& champ_c = centre_rotation_->valeurs();
309 // Attention: en 2D, le vecteur rotation est typiquement oriente
310 // dans la direction Z : donc boucle jusqu'a 3 dans tous les cas:
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 // Si on a un terme source de rotation solide, on a besoin des trois
319 // composantes de la vitesse du fluide aux faces:
320
321 // Un espace de stockage pour la vitesse si elle doit etre
322 // calculee (en VDF, on calcule les trois composantes a chaque face)
323 DoubleTab vitesse_faces_stockage;
324 // Calcul du champ de vitesse aux faces (a partir de l'inconnue
325 // de l'equation de N.S.)
326 const DoubleTab& vitesse_faces =
327 (rotation_solide)
328 ? calculer_vitesse_faces(vitesse_faces_stockage)
329 : vitesse_faces_stockage;
330
331 // **************************************************
332 // BOUCLE SUR LES FACES
333 int i_face;
334 const int nb_faces = acceleration_aux_faces.dimension(0);
335
336 // Vecteur vitesse du fluide dans l'element courant
337 // (attention: initialisation de la composante Z pour le 2D)
338 double v[3] = {0., 0., 0.};
339 // Vecteur (centre_face - centre_rotation)
340 // (idem)
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); (appel a ajouter() de la classe derivee)
385 *
386 */
387DoubleTab& Terme_Source_Acceleration::calculer(DoubleTab& resu) const
388{
389 resu = 0;
390 ajouter(resu);
392 return resu;
393}
394
395/*! @brief Evalue les champs d'acceleration et de rotation au temps 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 Methode surchargee de Source_base.
413 *
414 * Les mots compris sont:
415 * "ACCELERATION" => renvoie terme_source_post_, homogene a d/dt(rho*v)
416 * Attention a l'effet de bord de ajouter() (voir commentaires de 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 Renvoie eq_hydraulique_ !
432 *
433 */
435{
436 const Navier_Stokes_std& ns = ref_cast(Navier_Stokes_std, equation());
437 return ns;
438}
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
void mettre_a_jour(double temps) override
Mise a jour en temps du champ.
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
classe Discretisation_base Cette classe represente un schema de discretisation en espace,...
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
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
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
const Discretisation_base & discretisation() const
Renvoie la discretisation associee a l'equation.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
OBS_PTR(Equation_base) mon_equation
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:321
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
friend class Entree
Definition Objet_U.h:76
static int dimension
Definition Objet_U.h:99
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
double temps_courant() const
Renvoie le temps courant.
Classe de base des flux de sortie.
Definition Sortie.h:52
classe Source_base Un objet Source_base est un terme apparaissant au second membre d'une
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
Renvoie eq_hydraulique_ !
DoubleTab & calculer(DoubleTab &) const override
resu=0; ajouter(resu); (appel a ajouter() de la classe derivee)
const DoubleTab & calculer_la_source(DoubleTab &src_faces) const
Calcul de la valeur du champ la_source aux faces en fonction de - calculer_vitesse_faces().
int a_pour_Champ_Fonc(const Motcle &mot, OBS_PTR(Champ_base) &ch_ref) const override
Methode surchargee de Source_base.
virtual const DoubleTab & calculer_vitesse_faces(DoubleTab &stockage) const =0
void mettre_a_jour(double temps) override
Evalue les champs d'acceleration et de rotation au temps 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)
Methode appelee par readOn des classes derivees Terme_Source_Acceleration_VDF_Face,...