TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Modele_turbulence_hyd_Longueur_Melange_VEF.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 <Modele_turbulence_hyd_Longueur_Melange_VEF.h>
17#include <EcritureLectureSpecial.h>
18#include <VEF_discretisation.h>
19#include <Champ_Uniforme.h>
20#include <Postraitement.h>
21#include <LecFicDiffuse.h>
22#include <Fluide_base.h>
23#include <Champ_P1NC.h>
24#include <Motcle.h>
25#include <Debog.h>
26#include <Param.h>
27
28Implemente_instanciable(Modele_turbulence_hyd_Longueur_Melange_VEF, "Modele_turbulence_hyd_Longueur_Melange_VEF", Modele_turbulence_hyd_Longueur_Melange_base);
29// XD longueur_melange mod_turb_hyd_ss_maille longueur_melange INHERITS_BRACE This model is based on mixing length
30// XD_CONT modelling. For a non academic configuration, formulation used in the code can be expressed basically as : NL2
31// XD_CONT $nu_t=(Kappa.y)^2$.dU/dy NL2 Till a maximum distance (dmax) set by the user in the data file, y is set equal
32// XD_CONT to the distance from the wall (dist_w) calculated previously and saved in file Wall_length.xyz. [see
33// XD_CONT Distance_paroi keyword] NL2 Then (from y=dmax), y decreases as an exponential function :
34// XD_CONT y=dmax*exp[-2.*(dist_w-dmax)/dmax]
35// XD attr canalx floattant canalx OPT [height] : plane channel according to Ox direction (for the moment, formulation
36// XD_CONT in the code relies on fixed heigh : H=2).
37// XD attr tuyauz floattant tuyauz OPT [diameter] : pipe according to Oz direction (for the moment, formulation in the
38// XD_CONT code relies on fixed diameter : D=2).
39// XD attr dmax floattant dmax OPT Maximum distance.
40// XD attr fichier chaine fichier OPT not_set
41// XD attr fichier_ecriture_K_Eps chaine fichier_ecriture_K_Eps OPT When a resume with k-epsilon model is envisaged,
42// XD_CONT this keyword allows to generate external MED-format file with evaluation of k and epsilon quantities (based
43// XD_CONT on eddy turbulent viscosity and turbulent characteristic length returned by mixing length model). The
44// XD_CONT frequency of the MED file print is set equal to dt_impr_ustar. Moreover, k-eps MED field is automatically
45// XD_CONT saved at the last time step. MED file is then used for resuming a K-Epsilon calculation with the
46// XD_CONT Champ_Fonc_Med keyword.
48{
49 return s << que_suis_je() << " " << le_nom();
50}
51
53{
54 Param param(que_suis_je());
55 set_param(param);
56 param.lire_avec_accolades_depuis(is);
57 const LIST(Nom) &params_lu = param.get_list_mots_lus();
58 if (params_lu.contient(Motcle("canalx")))
59 cas_ = 1;
60 else if (params_lu.contient(Motcle("tuyauz")))
61 cas_ = 2;
62 else if (params_lu.contient(Motcle("tuyaux")))
63 cas_ = 21;
64 else if (params_lu.contient(Motcle("tuyauy")))
65 cas_ = 22;
66 else if ((params_lu.contient(Motcle("dmax"))) || (params_lu.contient(Motcle("fichier"))))
67 cas_ = 4;
68 else
69 {
70 Cerr << " Error while reading the Longueur_Melange turbulence model. " << finl;
71 Cerr << " Case not selected, choose among : canalx tuyauz dmax fichier " << finl;
72 Cerr << " Please refer to the reference manual for a detailed documentation. " << finl;
73 exit();
74 }
75
76 return is;
77}
78
80{
82 param.ajouter("canalx", &hauteur_);
83 param.ajouter_condition("value_of_canalx_eq_2", " canalx has been coded presently only for h=2.");
84 param.ajouter("tuyauz", &diametre_);
85 param.ajouter("tuyaux", &diametre_);
86 param.ajouter("tuyauy", &diametre_);
87 param.ajouter_condition("value_of_tuyauz_eq_2", " tuyauz has been coded presently only for d=2.");
88 param.ajouter_condition("value_of_tuyaux_eq_2", " tuyaux has been coded presently only for d=2.");
89 param.ajouter_condition("value_of_tuyauy_eq_2", " tuyauy has been coded presently only for d=2.");
90 param.ajouter("dmax", &dmax_);
91 param.ajouter("fichier", &nom_fic_);
92}
93
98
100{
101 const double Kappa = 0.415;
102 double Cmu = CMU;
103
104 double temps = mon_equation_->inconnue().temps();
105 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, le_dom_VF_.valeur());
106 DoubleTab& visco_turb = la_viscosite_turbulente_->valeurs();
107 DoubleVect& k = energie_cinetique_turb_->valeurs();
108 const int nb_elem = domaine_VEF.nb_elem();
109 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
110 const DoubleTab& xp = domaine_VEF.xp();
111
112 Sij2_.resize(nb_elem_tot);
113
115
116 if (visco_turb.size() != nb_elem)
117 {
118 Cerr << "Size error for the array containing the values of the turbulent viscosity." << finl;
119 exit();
120 }
121
122 Debog::verifier("Modele_turbulence_hyd_Longueur_Melange_VEF::calculer_viscosite_turbulente visco_turb 0", visco_turb);
123
124 if (k.size() != nb_elem)
125 {
126 Cerr << "Size error for the array containing the values of the turbulent kinetic energy." << finl;
127 exit();
128 }
129
130 // PLANE CHANNEL along (Ox - h=2) **********************************
131 if (cas_ == 1)
132 {
133 for (int elem = 0; elem < nb_elem; elem++)
134 {
135 double y = xp(elem, 1);
136 if (y > 1.)
137 y = 2. - y;
138
139 visco_turb(elem) = Kappa * Kappa * y * y * (1. - y) * sqrt(2. * Sij2_[elem]);
140 k(elem) = pow(visco_turb(elem) / (Cmu * y), 2);
141 }
142 }
143 else
144 // CYLINDER along (D=2) ************************************
145
146 if ((cas_ == 2) || (cas_ == 21) || (cas_ == 22))
147 {
148 int dir1;
149 int dir2;
150
151 if (cas_ == 2)
152 {
153 dir1 = 0; //Pipe along z
154 dir2 = 1;
155 }
156 else if (cas_ == 21)
157 {
158 dir1 = 1; //Pipe along x
159 dir2 = 2;
160 }
161 else
162 {
163 dir1 = 0; //Pipe along y
164 dir2 = 2;
165 }
166
167 for (int elem = 0; elem < nb_elem; elem++)
168 {
169 double x = xp(elem, dir1);
170 double y = xp(elem, dir2);
171 double r = sqrt(x * x + y * y);
172
173 visco_turb(elem) = Kappa * Kappa * (1. - r) * (1. - r) * (1. - r) * sqrt(2. * Sij2_[elem]);
174 k(elem) = pow(visco_turb(elem) / (Cmu * (1. - r)), 2);
175 }
176 }
177 // GENERIC CASE ***************************************************
178 else if (cas_ == 4)
179 {
181
182 const DoubleTab& wall_length = wall_length_->valeurs();
183
184 for (int elem = 0; elem < nb_elem; elem++)
185 {
186 double f_vd = f_amortissement_(elem);
187 double wl = wall_length(elem);
188 double lm = (wl <= dmax_) ? wl : dmax_ * exp(-2. * (wl - dmax_) / dmax_);
189
190 visco_turb(elem) = pow(f_vd * f_vd * Kappa * lm, 2) * sqrt(2. * Sij2_[elem]);
191 k(elem) = pow(visco_turb(elem) / (Cmu * lm), 2);
192 }
193 }
194 else
195 {
196 Cerr << cas_ << " not handled in " << que_suis_je() << finl;
197 Cerr << que_suis_je() << " Case " << cas_ << " not known." << finl;
198 exit();
199 }
200
201 Debog::verifier("Modele_turbulence_hyd_Longueur_Melange_VEF::calculer_viscosite_turbulente visco_turb 1", visco_turb);
202
203 la_viscosite_turbulente_->changer_temps(temps);
204
205 wall_length_->changer_temps(temps);
206 return la_viscosite_turbulente_;
207}
208
210{
211 const DoubleTab& la_vitesse = mon_equation_->inconnue().valeurs();
212 const Champ_P1NC& ch = ref_cast(Champ_P1NC, mon_equation_->inconnue());
213 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF, le_dom_Cl_.valeur());
214 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, le_dom_VF_.valeur());
215 const int nb_elem = domaine_VEF.nb_elem_tot();
216
217 DoubleTab duidxj(nb_elem, dimension, dimension);
218 int i, j;
219 double Sij;
220
221 Sij2_ = 0.;
222
223 DoubleTab ubar(la_vitesse);
224 // ch.filtrer_L2(ubar); // Patrick: we work on the filtered field.
225
226 ch.calcul_gradient(ubar, duidxj, domaine_Cl_VEF);
227
228 for (int elem = 0; elem < nb_elem; elem++)
229 {
230 for (i = 0; i < dimension; i++)
231 for (j = 0; j < dimension; j++)
232 {
233 //Sij computation moved here
234 Sij = 0.5 * (duidxj(elem, i, j) + duidxj(elem, j, i));
235 Sij2_(elem) += Sij * Sij;
236 }
237 }
238}
239
241{
242
243 // PQ: 25/02/04 retrieval of wall distance from Wall_length.xyz
244
245 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, le_dom_VF_.valeur());
246 DoubleTab& wall_length = wall_length_->valeurs();
247 wall_length = -1.;
248
249 LecFicDiffuse fic;
250 fic.set_bin(1);
251 if (!fic.ouvrir(nom_fic_))
252 {
253 Cerr << " File " << nom_fic_ << " doesn't exist. To generate it, please, refer to html.doc (Distance_paroi) " << finl;
254 exit();
255 }
256
257 Noms nom_paroi;
258
259 fic >> nom_paroi;
260
261 if (je_suis_maitre())
262 {
263
264 Cerr << "Recall : " << nom_fic_ << " obtained from boundaries nammed : " << finl;
265 for (int b = 0; b < nom_paroi.size(); b++)
266 {
267 Cerr << nom_paroi[b] << finl;
268 //test to ensure consistency between Wall_length.xyz and the dataset:
269 domaine_VEF.rang_frontiere(nom_paroi[b]);
270 }
271 }
272 EcritureLectureSpecial::lecture_special(domaine_VEF, fic, wall_length);
273}
274
276{
277 const double Kappa = 0.415;
278 const double A_plus = 26.;
279
280 // PQ : 23/02/04 compute the Van Driest damping function
281 // from the wall distance and an approximation
282 // of the friction
283
284 // the damping function f_vd = 1 - exp(-y+/A+) appears in the computation of nu_t
285 // to the power 4 (calibration from a plane channel giving the "best" results).
286 //
287 // we restrict the computation of f_vd to y+ values such that: f_vd^4 < 0.99
288 // i.e.: y+ < -A+. ln(1-0.99^(1/4)) = 155
289 // i.e., according to Reichardt's law: u+ < 17.96
290 // hence:
291 // f_vd^4 < 0.99 => u+.y+ < 2784
292 //
293
294 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, le_dom_VF_.valeur());
295 const int nb_elem = domaine_VEF.nb_elem();
296 DoubleTab& wall_length = wall_length_->valeurs();
297 int nb_face_elem = domaine_VEF.domaine().nb_faces_elem();
298 const IntTab& elem_faces = domaine_VEF.elem_faces();
299
300 const Fluide_base& le_fluide = ref_cast(Fluide_base, mon_equation_->milieu());
301 const Champ_Don_base& ch_visco_cin = le_fluide.viscosite_cinematique();
302 const DoubleTab& tab_visco = ch_visco_cin.valeurs();
303 const DoubleTab& vit = mon_equation_->inconnue().valeurs();
304
305 f_amortissement_.resize(nb_elem);
306 f_amortissement_ = 1.;
307
308 ArrOfDouble vc(dimension);
309 double dist, d_visco, norm_v, u_plus_d_plus, dp, up1, up2, r, y_plus;
310 int iter;
311 const int itmax = 25;
312 double seuil = 0.001;
313
314 double visco = -1;
315 int l_unif;
316
317 if (sub_type(Champ_Uniforme, ch_visco_cin))
318 {
319 visco = std::max(tab_visco(0, 0), DMINFLOAT);
320 l_unif = 1;
321 }
322 else
323 l_unif = 0;
324
325 if ((!l_unif) && (tab_visco.local_min_vect() < DMINFLOAT))
326 // tab_visco must not be modified here!
327 {
328 Cerr << "In Modele_turbulence_hyd_Longueur_Melange_VEF::calculer_f_amortissement : visco = " << tab_visco.local_min_vect() << " <= 0 ? " << finl;
329 exit();
330 }
331 //tab_visco+=DMINFLOAT;
332
333 for (int elem = 0; elem < nb_elem; elem++)
334 {
335 vc = 0.;
336 dist = wall_length(elem);
337
338 if (l_unif)
339 d_visco = visco;
340 else
341 d_visco = tab_visco[elem];
342
343 for (int i = 0; i < nb_face_elem; i++)
344 {
345 int face = elem_faces(elem, i);
346
347 for (int comp = 0; comp < dimension; comp++)
348 vc[comp] += vit(face, comp);
349 }
350
351 vc /= dimension;
352 norm_v = norme_array(vc);
353
354 u_plus_d_plus = norm_v * dist / d_visco;
355
356 if (u_plus_d_plus < 1.) // to avoid running the iterative procedure
357 {
358 y_plus = sqrt(u_plus_d_plus);
359 f_amortissement_(elem) -= exp(-y_plus / A_plus);
360 }
361 else if (u_plus_d_plus < 2784.) // cf. explanation above
362 {
363 up1 = u_plus_d_plus / 100.;
364 iter = 0;
365 r = 1.;
366
367 while ((iter++ < itmax) && (r > seuil))
368 {
369 dp = u_plus_d_plus / up1;
370 up2 = ((1 / Kappa) * log(1 + Kappa * dp)) + 7.8 * (1 - exp(-dp / 11.) - exp(-dp / 3.) * dp / 11.); // Reichardt's equation
371 up1 = 0.5 * (up1 + up2);
372 r = std::fabs(up1 - up2) / up1;
373 }
374 if (iter >= itmax)
375 erreur_non_convergence();
376
377 y_plus = u_plus_d_plus / up1;
378 f_amortissement_(elem) -= exp(-y_plus / A_plus);
379 }
380 }
381}
382
384{
385 // lire_distance_paroi must not be called when postprocessing the Distance_paroi field
386 // because it is already done in the base class Modele_turbulence_hyd_base
387 bool contient_distance_paroi = false;
388 for (auto &itr : equation().probleme().postraitements())
389 if (!contient_distance_paroi)
390 {
391 if (sub_type(Postraitement, itr.valeur()))
392 {
393 Postraitement& post = ref_cast(Postraitement, itr.valeur());
394 for (int i = 0; i < post.noms_champs_a_post().size(); i++)
395 {
396 if (post.noms_champs_a_post()[i].contient("DISTANCE_PAROI"))
397 {
398 contient_distance_paroi = true;
399 break;
400 }
401 }
402 }
403 }
404 if (!contient_distance_paroi && cas_ == 4)
407 mettre_a_jour(0.);
408
409 return 1;
410}
class Champ_Don_base base class of Given Fields (not calculated)
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
static DoubleTab & calcul_gradient(const DoubleTab &, DoubleTab &, const Domaine_Cl_VEF &)
Champ_Uniforme Represents a field that is constant in space and time.
double temps() const
Returns the time of the field.
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
int nb_faces_elem(int=0) const
Returns the number of faces of type i of the geometric elements that make up the domain.
Definition Domaine.h:484
class Domaine_VEF
Definition Domaine_VEF.h:53
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
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
int nb_elem_tot() const
int rang_frontiere(const Nom &)
const Domaine & domaine() const
static void lecture_special(Champ_base &ch, Entree &fich)
Simple call to EcritureLectureSpecial::lecture_special (const Domaine_VF& zvf,Entree& fich,...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Base class for an incompressible fluid and its properties:
Definition Fluide_base.h:36
const Champ_Don_base & viscosite_cinematique() const
Definition Fluide_base.h:56
This class implements the operators and virtual methods of the EFichier class as follows: The file to...
int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::in) override
Opens the file.
void set_bin(bool bin) override
Calls get_entree_master().
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
Mixing-length turbulence model for the Navier-Stokes equations.
LIST(Nom) boundaries_list_
virtual int preparer_calcul()
Prepares the computation.
Equation_base & equation()
Returns the equation associated with the turbulence model.
A character string (Nom) in uppercase.
Definition Motcle.h:26
An array of character strings (VECT(Nom)).
Definition Noms.h:26
virtual void set_param(Param &) const
Definition Objet_U.h:130
virtual int lire_motcle_non_standard(const Motcle &motlu, Entree &is)
Reads non-simple-type parameters of an Objet_U from an input stream.
Definition Objet_U.cpp:115
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
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_condition(const char *condition, const char *message, const char *name=0)
Declare a post-read logical condition that must hold on the parameter values.
Definition Param.cpp:496
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
class Postraitement. The class holds -a list of generic fields champs_post_complet_ containing
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
_SIZE_ size() const
Definition TRUSTVect.tpp:45
_TYPE_ local_min_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:155