TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Transport_K_Omega_base.cpp
1/****************************************************************************
2* Copyright (c) 2023, 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 <Transport_K_Omega_base.h>
17#include <Schema_Temps_base.h>
18#include <Champ_Inc_P0_base.h>
19#include <communications.h>
20#include <Probleme_base.h>
21#include <Discret_Thyd.h>
22#include <Domaine_VF.h>
23#include <Domaine_VEF.h>
24#include <Param.h>
25#include <Debog.h>
26
27Implemente_base(Transport_K_Omega_base, "Transport_K_Omega_base", Transport_2eq_base);
28
29// X_D Transport_K_Omega_base Transport_2eq_base Transport_K_Omega_base 1 Base equation for RANS k-omega model. Should not be used directly
30
31/*! @brief
32 *
33 * @param (Sortie& is) un flot de sortie
34 * @return (Sortie&) le flot de sortie modifie
35 */
37{ return is << que_suis_je() << "\n"; }
38
39/*! @brief Simple appel a Equation_base::readOn(Entree&)
40 *
41 * @param (Entree& is) un flot d'entree
42 * @return (Entree&) le flot d'entree modifie
43 */
45{
47 return is;
48}
50{
52 param.ajouter_flag("exit_on_negative_k_omega", &exit_on_negative_k_omega_); // X_D_ADD_P flag Flag to exit (with postprocessing of fields) if a negative value is found for k or omega
53 param.ajouter_flag("exit_on_big_omega", &exit_on_big_omega_); // X_D_ADD_P flag Flag to exit (with postprocessing of fields) if an excessively big values of omega are found
54 param.ajouter_flag("disable_report_on_corrected_values", &disable_report_on_corrected_values_); // X_D_ADD_P flag Flag disable the reports on number of corrected values, which are written to the log files per MPI process. Use to maximize performance if you do not care about these informations. Using this will also diable the two flags exit_on_xxx.
55}
56
62
64{
65 if (!sub_type(Discret_Thyd, discretisation()))
66 {
67 Cerr << " Transport_K_Omega_base::discretiser " << finl;
68 Cerr << "Discretization " << discretisation().que_suis_je() << " not recognized." << finl;
70 }
71
72 Cerr << "K-Omega transport equation (" << que_suis_je() << ") discretization" << finl;
73 Cerr << "K_Omega field discretization" << finl;
74 Noms noms(2);
75 Noms unit(2);
76 noms[0] = "K";
77 noms[1] = "omega";
78 unit[0] = "m2/s2";
79 unit[1] = "1/s1";
80
81 // cAlan : possibilite de mutualiser ca dans Transport_RANS_2eq
82 discretisation().discretiser_champ("temperature", domaine_dis(), multi_scalaire,
83 noms, unit, 2, schema_temps().nb_valeurs_temporelles(),
84 schema_temps().temps_courant(), le_champ_K_Omega);
85 le_champ_K_Omega->nommer("K_Omega");
86 champs_compris_.ajoute_champ(le_champ_K_Omega);
89
91}
92
93/*! @brief Controle le champ inconnue K-Omega en forcant a zero les valeurs du champ
94 *
95 * inferieurs a 1.e-10.
96 *
97 * @return (int) renvoie toujours 1
98 */
100{
101 if (flag_control_k_omega_required_)
102 {
103 DoubleTab& K_Omega = le_champ_K_Omega->valeurs();
104 int size = K_Omega.dimension(0);
105 if (size < 0)
106 {
107 if (!sub_type(Champ_Inc_P0_base, le_champ_K_Omega.valeur()))
108 Process::exit("Unsupported K_Omega field in Transport_K_Omega_base::controler_K_Omega()");
109 size = le_champ_K_Omega->equation().domaine_dis().domaine().nb_elem();
110 }
111
112
113 if (not(disable_report_on_corrected_values_))
114 {
116 }
117
118 // cAlan, le 20/01/2023 : on force les valeurs au min et max comme pour le K_Eps.
119 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
120 const double OMEGA_MIN = modele_turbulence().get_OMEGA_MIN();
121 const double OMEGA_MAX = modele_turbulence().get_OMEGA_MAX();
122 const double K_MIN = modele_turbulence().get_K_MIN();
123
124
125 Debog::verifier("Transport_K_Omega_base::controler_K_Omega K_Omega before", K_Omega);
126
127
128 // Phase 2: Parallel correction of negative k with neighbor averaging
129 // Create a snapshot of original values to ensure consistent neighbor averaging
130 DoubleTabView tab_K_Omega = K_Omega.view_rw();
131 DoubleTrav tab_K_Omega_original(K_Omega);
132 tab_K_Omega_original = K_Omega;
133 CDoubleTabView K_Omega_orig = tab_K_Omega_original.view_ro();
134 const bool vef_algo = sub_type(Domaine_VEF, domaine_vf) && !disable_VEF_mean_value_corrections_;
135 const int nb_faces_elem = domaine_vf.elem_faces().line_size();
136 CIntTabView face_voisins = domaine_vf.face_voisins().view_ro();
137 CIntTabView elem_faces = domaine_vf.elem_faces().view_ro();
138 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size, KOKKOS_LAMBDA(const int n)
139 {
140 double& enerK = tab_K_Omega(n, 0);
141 double& omega = tab_K_Omega(n, 1);
142
143 // correct negative k
144 if (enerK < 0)
145 {
146 enerK = 0;
147 omega = 0;
148 int nenerK = 0;
149 int nomega = 0;
150
151 // in VEF disc, we compute the mean value of neighbours
152 if (vef_algo)
153 {
154 for (int i = 0; i < 2; i++)
155 {
156 int elem = face_voisins(n, i);
157 if (elem != -1)
158 for (int j = 0; j < nb_faces_elem; j++)
159 {
160 int face_j = elem_faces(elem, j);
161 if (face_j != n)
162 {
163 double k_face = K_Omega_orig(face_j, 0);
164 if (k_face > K_MIN)
165 {
166 enerK += k_face;
167 nenerK++;
168 }
169 double o_face = K_Omega_orig(face_j, 1);
170 if (o_face > OMEGA_MIN)
171 {
172 omega += o_face;
173 nomega++;
174 }
175 }
176 }
177 }
178 }
179
180 if (nenerK != 0)
181 enerK /= nenerK;
182 else
183 enerK = K_MIN;
184
185 if (nomega != 0)
186 omega /= nomega;
187 else
188 omega = OMEGA_MIN;
189 }
190
191 //==========================================================
192 // EB: unexplained REQUIRED (in some cases...) second crop
193 // correct big omega (simple correction, no dependencies)
194 //==========================================================
195 if (omega > OMEGA_MAX)
196 {
197 omega = OMEGA_MAX;
198 }
199 // correct small omega (simple correction, no dependencies)
200 if (omega < OMEGA_MIN)
201 {
202 omega = OMEGA_MIN;
203 }
204 if (enerK < K_MIN)
205 {
206 enerK = K_MIN;
207 }
208 });
209 end_gpu_timer(__KERNEL_NAME__);
210 Debog::verifier("Transport_K_Omega_base::controler_K_Omega K_Omega middle", K_Omega);
211 K_Omega.echange_espace_virtuel();
212 Debog::verifier("Transport_K_Omega_base::controler_K_Omega K_Omega after", K_Omega);
213
215 }
216 return 1;
217}
218
219
221{
222 DoubleTab& K_Omega = le_champ_K_Omega->valeurs();
223 int size = K_Omega.dimension(0);
224 if (size < 0)
225 {
226 if (!sub_type(Champ_Inc_P0_base, le_champ_K_Omega.valeur()))
227 Process::exit("Unsupported K_Omega field in Transport_K_Omega_base::controler_K_Omega()");
228 size = le_champ_K_Omega->equation().domaine_dis().domaine().nb_elem();
229 }
230
231 const double OMEGA_MIN = modele_turbulence().get_OMEGA_MIN();
232 const double OMEGA_MAX = modele_turbulence().get_OMEGA_MAX();
233
234 // these will store the amount of problematic values of k or omega found
235 // for reporting at the end
236 int count_negative_k = 0;
237 int count_omega_under_threshold = 0;
238 int count_omega_too_big = 0;
239
240
241 // Two-phase parallel algorithm following Transport_K_Eps_base pattern
242
243 // Phase 1: Parallel detection and simple corrections
244 struct CountValues
245 {
246 int count_negative_k;
247 int count_omega_under_threshold;
248 int count_omega_too_big;
249
250 KOKKOS_INLINE_FUNCTION CountValues() : count_negative_k(0), count_omega_under_threshold(0), count_omega_too_big(0) {}
251 KOKKOS_INLINE_FUNCTION CountValues(const CountValues& rhs) : count_negative_k(rhs.count_negative_k), count_omega_under_threshold(rhs.count_omega_under_threshold), count_omega_too_big(rhs.count_omega_too_big) {}
252 KOKKOS_INLINE_FUNCTION CountValues& operator=(const CountValues&) = default;
253 KOKKOS_INLINE_FUNCTION void operator+=(const CountValues& rhs)
254 {
255 count_negative_k += rhs.count_negative_k;
256 count_omega_under_threshold += rhs.count_omega_under_threshold;
257 count_omega_too_big += rhs.count_omega_too_big;
258 }
259 };
260
261 DoubleTabView tab_K_Omega = K_Omega.view_rw();
262 CountValues result;
263 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), size,
264 KOKKOS_LAMBDA(const int n, CountValues& local_count)
265 {
266 double& enerK = tab_K_Omega(n, 0);
267 double& omega = tab_K_Omega(n, 1);
268
269 if (omega > OMEGA_MAX)
270 {
271 local_count.count_omega_too_big++;
272 }
273 if (omega < OMEGA_MIN)
274 {
275 local_count.count_omega_under_threshold++;
276 }
277
278 // Count negative k (correction will be done in phase 2)
279 if (enerK < 0) local_count.count_negative_k++;
280
281 }, result);
282 end_gpu_timer(__KERNEL_NAME__);
283
284 count_negative_k = result.count_negative_k;
285 count_omega_under_threshold = result.count_omega_under_threshold;
286 count_omega_too_big = result.count_omega_too_big;
287
288 const int lquiet = modele_turbulence().get_lquiet(); // cAlan remonter ce lquiet dans modele_turbu
289 if (schema_temps().limpr() && !lquiet)
290 {
291 if (count_negative_k || count_omega_under_threshold)
292 {
293 const double time = le_champ_K_Omega->temps();
294 Journal() << "Values forced for k and omega because:" << finl;
295 if (count_negative_k)
296 {
297 Journal() << "Negative values found for k on "
298 << count_negative_k << "/" << size << " nodes at time "
299 << time << finl;
300 }
301 if (count_omega_under_threshold)
302 {
303 Journal() << "Negative values found for omega on "
304 << count_omega_under_threshold << "/" << size << " nodes at time "
305 << time << finl;
306 }
307 // Warning if more than 0.01% of nodes are values fixed
308 // cAlan : mettre une variable "experte" dans le jdd pour ajuster ce seuil ?
309 const double ratio_k = 100. * count_negative_k / size;
310 const double ratio_omega = 100. * count_omega_under_threshold / size;
311 if ((ratio_k > 0.01 || ratio_omega > 0.01) && !lquiet)
312 {
313 Journal() << "WARNING: Found high ratio of invalid values for k and/or omega (more that 0.01%) on process" << Process::me() << finl;
314 Journal() << "Check journal log file for more information. These messages can be disabled with the flag 'quiet' in modele_turbulence." << finl;
315 // cAlan : adapter le texte pour omega
316 Journal() << "It is possible your initial and/or boundary conditions on k and/or omega are wrong." << finl;
317 }
318
319 if (exit_on_negative_k_omega_)
320 {
321 Cerr << "The problem is postprocessed in order to find the nodes where K or Omega values go below 0." << finl;
322 probleme().postraiter(1);
324 };
325 }
326 if (count_omega_too_big)
327 {
328 const double time = le_champ_K_Omega->temps();
329 Journal() << "Values forced for omega because:" << finl;
330 Journal() << "Maximum values found for omega on " << count_omega_too_big << "/" << size << " nodes at time " << time << finl;
331
332 if (exit_on_big_omega_)
333 {
334 Cerr << "The problem is postprocessed in order to find the nodes where Omega values too high." << finl;
335 probleme().postraiter(1);
337 };
338
339 }
340 }
341}
342/*! @brief on remet omega et K positifs
343 *
344 */
: class Champ_Inc_P0_base
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
classe Discret_Thyd Cette classe est la classe de base representant une discretisation
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_VEF
Definition Domaine_VEF.h:54
class Domaine_VF
Definition Domaine_VF.h:44
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
void set_calculate_time_derivative(int i)
const Discretisation_base & discretisation() const
Renvoie la discretisation associee a l'equation.
virtual void mettre_a_jour(double temps)
La valeur de l'inconnue sur le pas de temps a ete calculee.
int calculate_time_derivative() const
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
int limpr() const
Demande au schema en temps si il faut effectuer une impression.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
virtual void discretiser()
Discretise l'equation.
Champs_compris champs_compris_
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
const Objet_U & operator=(const Objet_U &)
Operateur= : ne fait rien (on conserve le numero et l'identifiant).
Definition Objet_U.cpp:87
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
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
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
int postraiter(int force=1) override
Si force=1, effectue le postraitement sans tenir compte des frequences de postraitement.
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, ConstView< _TYPE_, _SHAPE_ > > view_ro() const
Definition TRUSTTab.h:261
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_rw()
Definition TRUSTTab.h:291
_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")
Classe Transport_2eq_base Classe de base pour les equations.
void set_param(Param &) const override
const Modele_turbulence_hyd_2_eq_base & modele_turbulence() const
Renvoie le modele de turbulence associe a l'equation.
Classe Transport_K_Omega_base Classe de base pour les equations.
void valider_iteration() override
on remet omega et K positifs
void discretiser() override
Discretise l'equation.
virtual void set_param(Param &) const override
void mettre_a_jour(double temps) override
La valeur de l'inconnue sur le pas de temps a ete calculee.
int controler_K_Omega()
Controle le champ inconnue K-Omega en forcant a zero les valeurs du champ.