TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Modele_turbulence_hyd_RANS_Gen.h
1/****************************************************************************
2* Copyright (c) 2024, 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#ifndef Modele_turbulence_hyd_RANS_Gen_included
17#define Modele_turbulence_hyd_RANS_Gen_included
18
19#include <Modifier_pour_fluide_dilatable.h>
20#include <Schema_Temps_base.h>
21#include <Champ_Inc_P0_base.h>
22#include <Equation_base.h>
23#include <Process.h>
24#include <type_traits>
25
26enum class MODELE_TYPE
27{
28 K_EPS, K_EPS_2_COUCHES,
29 K_EPS_BAS_REYNOLDS, K_EPS_REALISABLE,
30 K_EPS_BICEPHALE, K_EPS_REALISABLE_BICEPHALE,
31 K_OMEGA
32};
33
34template <typename MODELE>
36{
37private:
38 template <MODELE_TYPE M_TYPE>
39 void print_evolution(const Champ_Inc_base& , const Schema_Temps_base& , double , int , const Champ_Inc_base* = nullptr /* Seulement si Bicephale */);
40
41public:
42 DoubleTab& complete_viscosity_field(const int , const Domaine_dis_base& , Champ_Inc_base& );
43
44 template <MODELE_TYPE M_TYPE> std::enable_if_t<(M_TYPE == MODELE_TYPE::K_EPS || M_TYPE == MODELE_TYPE::K_EPS_REALISABLE || M_TYPE == MODELE_TYPE::K_OMEGA), void>
46
47 template <MODELE_TYPE M_TYPE> std::enable_if_t<M_TYPE == MODELE_TYPE::K_EPS_2_COUCHES, void>
49
50 template <MODELE_TYPE M_TYPE> std::enable_if_t<M_TYPE == MODELE_TYPE::K_EPS_BAS_REYNOLDS, void>
52
53 template <MODELE_TYPE M_TYPE> std::enable_if_t<(M_TYPE == MODELE_TYPE::K_EPS_BICEPHALE || M_TYPE == MODELE_TYPE::K_EPS_REALISABLE_BICEPHALE), void>
55};
56
57template <typename MODELE>
59{
60 visc.associer_domaine_dis_base(dom_dis);
61 visc.nommer("diffusivite_turbulente");
62 visc.fixer_nb_comp(1);
64 visc.fixer_unite("inconnue");
65 visc.changer_temps(0.);
66 return visc.valeurs();
67}
68
69template<typename MODELE> template<MODELE_TYPE M_TYPE>
70std::enable_if_t<(M_TYPE == MODELE_TYPE::K_EPS || M_TYPE == MODELE_TYPE::K_EPS_REALISABLE || M_TYPE == MODELE_TYPE::K_OMEGA), void>
72{
73 constexpr bool IS_K_OMEGA = (M_TYPE == MODELE_TYPE::K_OMEGA);
74 auto *z_class = static_cast<MODELE*>(this); // CRTP --> I love you :*
75 const Milieu_base& mil = z_class->equation().probleme().milieu();
76
77 // on divise par rho en QC pour revenir a K et Eps/Omega
78 if (z_class->equation().probleme().is_dilatable())
79 diviser_par_rho_si_dilatable(ch_K_Eps_ou_Omega.valeurs(), mil);
80
81 print_evolution<M_TYPE>(ch_K_Eps_ou_Omega, z_class->equation().schema_temps(), LeCmu, 1);
82
83 z_class->loi_paroi().calculer_hyd(ch_K_Eps_ou_Omega);
84 z_class->controler();
85 z_class->calculer_viscosite_turbulente(ch_K_Eps_ou_Omega.temps());
86 z_class->limiter_viscosite_turbulente();
87
88 // on remultiplie par rho
89 if (z_class->equation().probleme().is_dilatable())
90 {
91 multiplier_par_rho_si_dilatable(ch_K_Eps_ou_Omega.valeurs(), mil);
92 if constexpr (!IS_K_OMEGA)
93 correction_nut_et_cisaillement_paroi_si_qc(*z_class);
94 }
95
96 z_class->viscosite_turbulente().valeurs().echange_espace_virtuel();
97
98 print_evolution<M_TYPE>(ch_K_Eps_ou_Omega, z_class->equation().schema_temps(), LeCmu, 0);
99}
100
101
102// note: LeCmu maybe unused because of if constexpr branches
103template<typename MODELE> template<MODELE_TYPE M_TYPE>
104std::enable_if_t<(M_TYPE == MODELE_TYPE::K_EPS_BICEPHALE || M_TYPE == MODELE_TYPE::K_EPS_REALISABLE_BICEPHALE), void>
106{
107 constexpr bool IS_K_EPS_REALISABLE_BICEPHALE = (M_TYPE == MODELE_TYPE::K_EPS_REALISABLE_BICEPHALE);
108
109 auto *z_class = static_cast<MODELE*>(this); // CRTP --> I love you :*
110 const Milieu_base& mil = z_class->equation().probleme().milieu();
111
112 // on divise par rho en QC pour revenir a K et Eps/Omega
113 if (z_class->equation().probleme().is_dilatable())
114 {
115 diviser_par_rho_si_dilatable(ch_K.valeurs(), mil);
116 diviser_par_rho_si_dilatable(ch_Eps.valeurs(), mil);
117 }
118
119 if constexpr (!IS_K_EPS_REALISABLE_BICEPHALE)
120 print_evolution<M_TYPE>(ch_K, z_class->equation().schema_temps(), LeCmu, 1, &ch_Eps);
121
122 z_class->loi_paroi().calculer_hyd_BiK(ch_K.valeurs(), ch_Eps.valeurs());
123 z_class->controler();
124 z_class->calculer_viscosite_turbulente(ch_K.temps());
125 z_class->limiter_viscosite_turbulente();
126
127 // on remultiplie par rho
128 if (z_class->equation().probleme().is_dilatable())
129 {
130 multiplier_par_rho_si_dilatable(ch_K.valeurs(), mil);
131 multiplier_par_rho_si_dilatable(ch_Eps.valeurs(), mil);
132 correction_nut_et_cisaillement_paroi_si_qc(*z_class);
133 }
134
135 z_class->viscosite_turbulente().valeurs().echange_espace_virtuel();
136
137 if constexpr (!IS_K_EPS_REALISABLE_BICEPHALE)
138 print_evolution<M_TYPE>(ch_K, z_class->equation().schema_temps(), LeCmu, 0, &ch_Eps);
139}
140
141template<typename MODELE> template<MODELE_TYPE M_TYPE>
142std::enable_if_t<M_TYPE == MODELE_TYPE::K_EPS_2_COUCHES, void>
144{
145 auto *z_class = static_cast<MODELE*>(this); // CRTP --> I love you :*
146 const Milieu_base& mil = z_class->equation().probleme().milieu();
147
148 z_class->controler();
149
150 // on divise par rho en QC pour revenir a K et Eps/Omega
151 if (z_class->equation().probleme().is_dilatable())
152 diviser_par_rho_si_dilatable(ch_K_Eps_ou_Omega.valeurs(), mil);
153
154 z_class->calculer_viscosite_turbulente(ch_K_Eps_ou_Omega.temps());
155 z_class->loi_paroi().calculer_hyd(ch_K_Eps_ou_Omega);
156 z_class->limiter_viscosite_turbulente();
157
158 // on remultiplie par rho
159 if (z_class->equation().probleme().is_dilatable())
160 {
161 multiplier_par_rho_si_dilatable(ch_K_Eps_ou_Omega.valeurs(), mil);
162 correction_nut_et_cisaillement_paroi_si_qc(*z_class);
163 }
164
165 z_class->viscosite_turbulente().valeurs().echange_espace_virtuel();
166}
167
168template<typename MODELE> template<MODELE_TYPE M_TYPE>
169std::enable_if_t<M_TYPE == MODELE_TYPE::K_EPS_BAS_REYNOLDS, void>
171{
172 auto *z_class = static_cast<MODELE*>(this); // CRTP --> I love you :*
173 z_class->controler();
174 z_class->calculer_viscosite_turbulente(ch_K_Eps_ou_Omega.temps());
175 z_class->limiter_viscosite_turbulente();
176 z_class->viscosite_turbulente().valeurs().echange_espace_virtuel();
177}
178
179template <typename MODELE> template <MODELE_TYPE M_TYPE>
180void Modele_turbulence_hyd_RANS_Gen<MODELE>::print_evolution(const Champ_Inc_base& le_champ_K_Eps_ou_Omega, const Schema_Temps_base& sch, const double LeCmu, const int avant, const Champ_Inc_base* le_champ_Eps)
181{
182
183 constexpr bool IS_K_OMEGA = (M_TYPE == MODELE_TYPE::K_OMEGA);
184 constexpr bool IS_2_COUCHES = (M_TYPE == MODELE_TYPE::K_EPS_2_COUCHES);
185 constexpr bool IS_BAS_REYNOLDS = (M_TYPE == MODELE_TYPE::K_EPS_BAS_REYNOLDS);
186 constexpr bool IS_K_EPS_BICEPHALE = (M_TYPE == MODELE_TYPE::K_EPS_BICEPHALE);
187 constexpr bool IS_K_EPS_REALISABLE_BICEPHALE = (M_TYPE == MODELE_TYPE::K_EPS_REALISABLE_BICEPHALE);
188
189 assert (!IS_K_EPS_BICEPHALE || (IS_K_EPS_BICEPHALE && le_champ_Eps != nullptr));
190
191 if constexpr (IS_2_COUCHES || IS_BAS_REYNOLDS || IS_K_EPS_REALISABLE_BICEPHALE) return; /* Do nothing */
192
193 if (sch.nb_pas_dt() == 0 || sch.limpr())
194 {
195 const DoubleTab& tab_K_Eps_ou_Omega = le_champ_K_Eps_ou_Omega.valeurs();
196 double k_min = DMAXFLOAT, eps_ou_omega_min = DMAXFLOAT, nut_min = DMAXFLOAT;
197 double k_max = 0, eps_ou_omega_max = 0, nut_max = 0;
198 int loc_k_min = -1, loc_eps_ou_omega_min = -1, loc_nut_min = -1;
199 int loc_k_max = -1, loc_eps_ou_omega_max = -1, loc_nut_max = -1;
200 int size = tab_K_Eps_ou_Omega.dimension(0);
201
202 if (size < 0)
203 {
204 if (!sub_type(Champ_Inc_P0_base, le_champ_K_Eps_ou_Omega))
205 {
206 Cerr << "Unsupported field in Modele_turbulence_hyd_RANS_Gen::imprimer_evolution()" << finl;
207 Process::exit(-1);
208 }
209
210 size = le_champ_K_Eps_ou_Omega.equation().domaine_dis().domaine().nb_elem();
211
212 if constexpr (IS_K_EPS_BICEPHALE)
213 {
214 if (!sub_type(Champ_Inc_P0_base, (*le_champ_Eps)))
215 {
216 Cerr << "Unsupported field in Modele_turbulence_hyd_RANS_Gen::imprimer_evolution()" << finl;
217 Process::exit(-1);
218 }
219 assert (size == (*le_champ_Eps).equation().domaine_dis().domaine().nb_elem());
220 }
221 }
222 // Structure to hold min/max values and their locations for reduction
223 struct MinMaxResult
224 {
225 double k_min, k_max;
226 double eps_ou_omega_min, eps_ou_omega_max;
227 double nut_min, nut_max;
228 int loc_k_min, loc_k_max;
229 int loc_eps_ou_omega_min, loc_eps_ou_omega_max;
230 int loc_nut_min, loc_nut_max;
231
232 KOKKOS_INLINE_FUNCTION
233 MinMaxResult() : k_min(DMAXFLOAT), k_max(-DMAXFLOAT), eps_ou_omega_min(DMAXFLOAT), eps_ou_omega_max(-DMAXFLOAT),
234 nut_min(DMAXFLOAT), nut_max(-DMAXFLOAT), loc_k_min(-1), loc_k_max(-1),
235 loc_eps_ou_omega_min(-1), loc_eps_ou_omega_max(-1), loc_nut_min(-1), loc_nut_max(-1) {}
236
237 KOKKOS_INLINE_FUNCTION
238 MinMaxResult(const MinMaxResult& rhs) : k_min(rhs.k_min), k_max(rhs.k_max),
239 eps_ou_omega_min(rhs.eps_ou_omega_min), eps_ou_omega_max(rhs.eps_ou_omega_max),
240 nut_min(rhs.nut_min), nut_max(rhs.nut_max),
241 loc_k_min(rhs.loc_k_min), loc_k_max(rhs.loc_k_max),
242 loc_eps_ou_omega_min(rhs.loc_eps_ou_omega_min), loc_eps_ou_omega_max(rhs.loc_eps_ou_omega_max),
243 loc_nut_min(rhs.loc_nut_min), loc_nut_max(rhs.loc_nut_max) {}
244
245 KOKKOS_INLINE_FUNCTION
246 MinMaxResult& operator=(const MinMaxResult&) = default;
247
248 KOKKOS_INLINE_FUNCTION
249 void operator += (const MinMaxResult& rhs)
250 {
251 if (rhs.k_min < k_min) { k_min = rhs.k_min; loc_k_min = rhs.loc_k_min; }
252 if (rhs.k_max > k_max) { k_max = rhs.k_max; loc_k_max = rhs.loc_k_max; }
253 if (rhs.eps_ou_omega_min < eps_ou_omega_min) { eps_ou_omega_min = rhs.eps_ou_omega_min; loc_eps_ou_omega_min = rhs.loc_eps_ou_omega_min; }
254 if (rhs.eps_ou_omega_max > eps_ou_omega_max) { eps_ou_omega_max = rhs.eps_ou_omega_max; loc_eps_ou_omega_max = rhs.loc_eps_ou_omega_max; }
255 if (rhs.nut_min < nut_min) { nut_min = rhs.nut_min; loc_nut_min = rhs.loc_nut_min; }
256 if (rhs.nut_max > nut_max) { nut_max = rhs.nut_max; loc_nut_max = rhs.loc_nut_max; }
257 }
258 };
259
260 MinMaxResult result;
261 CDoubleTabView K_Eps_ou_Omega = tab_K_Eps_ou_Omega.view_ro();
262 CDoubleArrView Eps;
263 if constexpr (IS_K_EPS_BICEPHALE) Eps = static_cast<const ArrOfDouble&>((*le_champ_Eps).valeurs()).view_ro();
264 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), size,
265 KOKKOS_LAMBDA(const int n, MinMaxResult& local_result)
266 {
267 const double k = IS_K_EPS_BICEPHALE ? K_Eps_ou_Omega(n, 0) : K_Eps_ou_Omega(n, 0);
268 const double epsOuomega = IS_K_EPS_BICEPHALE ? Eps(n) : K_Eps_ou_Omega(n, 1);
269 double nut = 0;
270
271 const double num = IS_K_OMEGA ? k : LeCmu * k * k;
272
273 if (epsOuomega > 0)
274 nut = num / epsOuomega;
275
276 // Always update k min/max (k is always computed)
277 if (local_result.loc_k_min == -1 || k < local_result.k_min)
278 {
279 local_result.k_min = k;
280 local_result.loc_k_min = n;
281 }
282 if (local_result.loc_k_max == -1 || k > local_result.k_max)
283 {
284 local_result.k_max = k;
285 local_result.loc_k_max = n;
286 }
287
288 // Always update eps/omega min/max (epsOuomega is always computed)
289 if (local_result.loc_eps_ou_omega_min == -1 || epsOuomega < local_result.eps_ou_omega_min)
290 {
291 local_result.eps_ou_omega_min = epsOuomega;
292 local_result.loc_eps_ou_omega_min = n;
293 }
294 if (local_result.loc_eps_ou_omega_max == -1 || epsOuomega > local_result.eps_ou_omega_max)
295 {
296 local_result.eps_ou_omega_max = epsOuomega;
297 local_result.loc_eps_ou_omega_max = n;
298 }
299
300 // Always update nut min/max (nut is always computed, even if 0)
301 if (local_result.loc_nut_min == -1 || nut < local_result.nut_min)
302 {
303 local_result.nut_min = nut;
304 local_result.loc_nut_min = n;
305 }
306 if (local_result.loc_nut_max == -1 || nut > local_result.nut_max)
307 {
308 local_result.nut_max = nut;
309 local_result.loc_nut_max = n;
310 }
311 }, result);
312 end_gpu_timer(__KERNEL_NAME__);
313
314 // Extract results
315 k_min = result.k_min;
316 k_max = result.k_max;
317 eps_ou_omega_min = result.eps_ou_omega_min;
318 eps_ou_omega_max = result.eps_ou_omega_max;
319 nut_min = result.nut_min;
320 nut_max = result.nut_max;
321 loc_k_min = result.loc_k_min;
322 loc_k_max = result.loc_k_max;
323 loc_eps_ou_omega_min = result.loc_eps_ou_omega_min;
324 loc_eps_ou_omega_max = result.loc_eps_ou_omega_max;
325 loc_nut_min = result.loc_nut_min;
326 loc_nut_max = result.loc_nut_max;
327
328
329 // min values
330 Process::mp_min_for_each(k_min, eps_ou_omega_min, nut_min);
331
332 // max values
333 Process::mp_max_for_each(k_max, eps_ou_omega_max, nut_max);
334
335 // ecriture
337 {
338 Cout << finl << "K_Eps/Omega evolution (" << (avant ? "before" : "after") << " law of the wall applies) at time " << le_champ_K_Eps_ou_Omega.temps() << ":" << finl;
339 Cout << "std::min(k)=" << k_min;
340 if (Process::is_sequential()) Cout << " located at node " << loc_k_min;
341 Cout << finl;
342 Cout << "std::min(eps/omega)=" << eps_ou_omega_min;
343 if (Process::is_sequential()) Cout << " located at node " << loc_eps_ou_omega_min;
344 Cout << finl;
345 Cout << "std::min(nut)=" << nut_min;
346 if (Process::is_sequential()) Cout << " located at node " << loc_nut_min;
347 Cout << finl;
348 Cout << "std::max(k)=" << k_max;
349 if (Process::is_sequential()) Cout << " located at node " << loc_k_max;
350 Cout << finl;
351 Cout << "std::max(eps/omega)=" << eps_ou_omega_max;
352 if (Process::is_sequential()) Cout << " located at node " << loc_eps_ou_omega_max;
353 Cout << finl;
354 Cout << "std::max(nut)=" << nut_max;
355 if (Process::is_sequential()) Cout << " located at node " << loc_nut_max;
356 Cout << finl;
357 }
358 }
359}
360
361#endif /* Modele_turbulence_hyd_RANS_Gen_included */
: class Champ_Inc_P0_base
Classe Champ_Inc_base.
void associer_domaine_dis_base(const Domaine_dis_base &) override
int fixer_nb_valeurs_nodales(int) override
double changer_temps(const double temps) override
Fixe le temps du champ.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
double temps() const
Renvoie le temps du champ.
int_t nb_elem() const
Definition Domaine.h:131
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
const Domaine & domaine() const
Probleme_base & probleme()
Renvoie le probleme associe 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.
virtual void fixer_nb_comp(int i)
Fixe le nombre de composantes du champ.
void nommer(const Nom &) override
Donne un nom au champ.
virtual const Nom & fixer_unite(const Nom &)
Specifie l'unite d'un champ scalaire ou dont toutes les composantes ont la meme unite.
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
virtual const Equation_base & equation(const std::string &nom_inc) const
DoubleTab & complete_viscosity_field(const int, const Domaine_dis_base &, Champ_Inc_base &)
std::enable_if_t<(M_TYPE==MODELE_TYPE::K_EPS||M_TYPE==MODELE_TYPE::K_EPS_REALISABLE||M_TYPE==MODELE_TYPE::K_OMEGA), void > calculate_limit_viscosity(Champ_Inc_base &, double)
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
virtual const Milieu_base & milieu() const
Renvoie le milieu physique associe au probleme.
static void mp_max_for_each(T &arg1, T &arg2)
C++14 compatible mp_max_for_each: combine multiple mp_max calls into one collective operation.
Definition Process.cpp:244
static void mp_min_for_each(T &arg1, T &arg2)
C++14 compatible mp_min_for_each: combine multiple mp_min calls into one collective operation.
Definition Process.cpp:281
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
static bool is_sequential()
Definition Process.cpp:115
class Schema_Temps_base
int limpr() const
Renvoie 1 s'il y a lieu d'effectuer une impression (cf dt_impr) Renvoie 0 sinon.
int nb_pas_dt() const
Renvoie le nombre de pas de temps effectues.
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, ConstView< _TYPE_, _SHAPE_ > > view_ro() const
Definition TRUSTTab.h:261
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133