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// XD Transport_K_Omega_base Transport_2eq_base Transport_K_Omega_base BRACE Base equation for RANS k-omega model.
30// XD_CONT Should not be used directly
31
32/*! @brief
33 *
34 * @param (Sortie& is) un flot de sortie
35 * @return (Sortie&) le flot de sortie modifie
36 */
38{ return is << que_suis_je() << "\n"; }
39
40/*! @brief Simple appel a Equation_base::readOn(Entree&)
41 *
42 * @param (Entree& is) un flot d'entree
43 * @return (Entree&) le flot d'entree modifie
44 */
46{
48 return is;
49}
51{
53 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
54 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
55 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.
56}
57
63
65{
66 if (!sub_type(Discret_Thyd, discretisation()))
67 {
68 Cerr << " Transport_K_Omega_base::discretiser " << finl;
69 Cerr << "Discretization " << discretisation().que_suis_je() << " not recognized." << finl;
71 }
72
73 Cerr << "K-Omega transport equation (" << que_suis_je() << ") discretization" << finl;
74 Cerr << "K_Omega field discretization" << finl;
75 Noms noms(2);
76 Noms unit(2);
77 noms[0] = "K";
78 noms[1] = "omega";
79 unit[0] = "m2/s2";
80 unit[1] = "1/s1";
81
82 // cAlan : possibilite de mutualiser ca dans Transport_RANS_2eq
83 discretisation().discretiser_champ("temperature", domaine_dis(), multi_scalaire,
84 noms, unit, 2, schema_temps().nb_valeurs_temporelles(),
85 schema_temps().temps_courant(), le_champ_K_Omega);
86 le_champ_K_Omega->nommer("K_Omega");
87 champs_compris_.ajoute_champ(le_champ_K_Omega);
90
92}
93
94/*! @brief Controle le champ inconnue K-Omega en forcant a zero les valeurs du champ
95 *
96 * inferieurs a 1.e-10.
97 *
98 * @return (int) renvoie toujours 1
99 */
101{
102 if (flag_control_k_omega_required_)
103 {
104 DoubleTab& K_Omega = le_champ_K_Omega->valeurs();
105 int size = K_Omega.dimension(0);
106 if (size < 0)
107 {
108 if (!sub_type(Champ_Inc_P0_base, le_champ_K_Omega.valeur()))
109 Process::exit("Unsupported K_Omega field in Transport_K_Omega_base::controler_K_Omega()");
110 size = le_champ_K_Omega->equation().domaine_dis().domaine().nb_elem();
111 }
112
113
114 if (not(disable_report_on_corrected_values_))
115 {
117 }
118
119 // cAlan, le 20/01/2023 : on force les valeurs au min et max comme pour le K_Eps.
120 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
121 const double OMEGA_MIN = modele_turbulence().get_OMEGA_MIN();
122 const double OMEGA_MAX = modele_turbulence().get_OMEGA_MAX();
123 const double K_MIN = modele_turbulence().get_K_MIN();
124
125
126 Debog::verifier("Transport_K_Omega_base::controler_K_Omega K_Omega before", K_Omega);
127
128
129 // Phase 2: Parallel correction of negative k with neighbor averaging
130 // Create a snapshot of original values to ensure consistent neighbor averaging
131 DoubleTabView tab_K_Omega = K_Omega.view_rw();
132 DoubleTrav tab_K_Omega_original(K_Omega);
133 tab_K_Omega_original = K_Omega;
134 CDoubleTabView K_Omega_orig = tab_K_Omega_original.view_ro();
135 const bool vef_algo = sub_type(Domaine_VEF, domaine_vf) && !disable_VEF_mean_value_corrections_;
136 const int nb_faces_elem = domaine_vf.elem_faces().line_size();
137 CIntTabView face_voisins = domaine_vf.face_voisins().view_ro();
138 CIntTabView elem_faces = domaine_vf.elem_faces().view_ro();
139 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size, KOKKOS_LAMBDA(const int n)
140 {
141 double& enerK = tab_K_Omega(n, 0);
142 double& omega = tab_K_Omega(n, 1);
143
144 // correct negative k
145 if (enerK < 0)
146 {
147 enerK = 0;
148 omega = 0;
149 int nenerK = 0;
150 int nomega = 0;
151
152 // in VEF disc, we compute the mean value of neighbours
153 if (vef_algo)
154 {
155 for (int i = 0; i < 2; i++)
156 {
157 int elem = face_voisins(n, i);
158 if (elem != -1)
159 for (int j = 0; j < nb_faces_elem; j++)
160 {
161 int face_j = elem_faces(elem, j);
162 if (face_j != n)
163 {
164 double k_face = K_Omega_orig(face_j, 0);
165 if (k_face > K_MIN)
166 {
167 enerK += k_face;
168 nenerK++;
169 }
170 double o_face = K_Omega_orig(face_j, 1);
171 if (o_face > OMEGA_MIN)
172 {
173 omega += o_face;
174 nomega++;
175 }
176 }
177 }
178 }
179 }
180
181 if (nenerK != 0)
182 enerK /= nenerK;
183 else
184 enerK = K_MIN;
185
186 if (nomega != 0)
187 omega /= nomega;
188 else
189 omega = OMEGA_MIN;
190 }
191
192 //==========================================================
193 // EB: unexplained REQUIRED (in some cases...) second crop
194 // correct big omega (simple correction, no dependencies)
195 //==========================================================
196 if (omega > OMEGA_MAX)
197 {
198 omega = OMEGA_MAX;
199 }
200 // correct small omega (simple correction, no dependencies)
201 if (omega < OMEGA_MIN)
202 {
203 omega = OMEGA_MIN;
204 }
205 if (enerK < K_MIN)
206 {
207 enerK = K_MIN;
208 }
209 });
210 end_gpu_timer(__KERNEL_NAME__);
211 Debog::verifier("Transport_K_Omega_base::controler_K_Omega K_Omega middle", K_Omega);
212 K_Omega.echange_espace_virtuel();
213 Debog::verifier("Transport_K_Omega_base::controler_K_Omega K_Omega after", K_Omega);
214
216 }
217 return 1;
218}
219
220
222{
223 DoubleTab& K_Omega = le_champ_K_Omega->valeurs();
224 int size = K_Omega.dimension(0);
225 if (size < 0)
226 {
227 if (!sub_type(Champ_Inc_P0_base, le_champ_K_Omega.valeur()))
228 Process::exit("Unsupported K_Omega field in Transport_K_Omega_base::controler_K_Omega()");
229 size = le_champ_K_Omega->equation().domaine_dis().domaine().nb_elem();
230 }
231
232 const double OMEGA_MIN = modele_turbulence().get_OMEGA_MIN();
233 const double OMEGA_MAX = modele_turbulence().get_OMEGA_MAX();
234
235 // these will store the amount of problematic values of k or omega found
236 // for reporting at the end
237 int count_negative_k = 0;
238 int count_omega_under_threshold = 0;
239 int count_omega_too_big = 0;
240
241
242 // Two-phase parallel algorithm following Transport_K_Eps_base pattern
243
244 // Phase 1: Parallel detection and simple corrections
245 struct CountValues
246 {
247 int count_negative_k;
248 int count_omega_under_threshold;
249 int count_omega_too_big;
250
251 KOKKOS_INLINE_FUNCTION CountValues() : count_negative_k(0), count_omega_under_threshold(0), count_omega_too_big(0) {}
252 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) {}
253 KOKKOS_INLINE_FUNCTION CountValues& operator=(const CountValues&) = default;
254 KOKKOS_INLINE_FUNCTION void operator+=(const CountValues& rhs)
255 {
256 count_negative_k += rhs.count_negative_k;
257 count_omega_under_threshold += rhs.count_omega_under_threshold;
258 count_omega_too_big += rhs.count_omega_too_big;
259 }
260 };
261
262 DoubleTabView tab_K_Omega = K_Omega.view_rw();
263 CountValues result;
264 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), size,
265 KOKKOS_LAMBDA(const int n, CountValues& local_count)
266 {
267 double& enerK = tab_K_Omega(n, 0);
268 double& omega = tab_K_Omega(n, 1);
269
270 if (omega > OMEGA_MAX)
271 {
272 local_count.count_omega_too_big++;
273 }
274 if (omega < OMEGA_MIN)
275 {
276 local_count.count_omega_under_threshold++;
277 }
278
279 // Count negative k (correction will be done in phase 2)
280 if (enerK < 0) local_count.count_negative_k++;
281
282 }, result);
283 end_gpu_timer(__KERNEL_NAME__);
284
285 count_negative_k = result.count_negative_k;
286 count_omega_under_threshold = result.count_omega_under_threshold;
287 count_omega_too_big = result.count_omega_too_big;
288
289 const int lquiet = modele_turbulence().get_lquiet(); // cAlan remonter ce lquiet dans modele_turbu
290 if (schema_temps().limpr() && !lquiet)
291 {
292 if (count_negative_k || count_omega_under_threshold)
293 {
294 const double time = le_champ_K_Omega->temps();
295 Journal() << "Values forced for k and omega because:" << finl;
296 if (count_negative_k)
297 {
298 Journal() << "Negative values found for k on "
299 << count_negative_k << "/" << size << " nodes at time "
300 << time << finl;
301 }
302 if (count_omega_under_threshold)
303 {
304 Journal() << "Negative values found for omega on "
305 << count_omega_under_threshold << "/" << size << " nodes at time "
306 << time << finl;
307 }
308 // Warning if more than 0.01% of nodes are values fixed
309 // cAlan : mettre une variable "experte" dans le jdd pour ajuster ce seuil ?
310 const double ratio_k = 100. * count_negative_k / size;
311 const double ratio_omega = 100. * count_omega_under_threshold / size;
312 if ((ratio_k > 0.01 || ratio_omega > 0.01) && !lquiet)
313 {
314 Journal() << "WARNING: Found high ratio of invalid values for k and/or omega (more that 0.01%) on process" << Process::me() << finl;
315 Journal() << "Check journal log file for more information. These messages can be disabled with the flag 'quiet' in modele_turbulence." << finl;
316 // cAlan : adapter le texte pour omega
317 Journal() << "It is possible your initial and/or boundary conditions on k and/or omega are wrong." << finl;
318 }
319
320 if (exit_on_negative_k_omega_)
321 {
322 Cerr << "The problem is postprocessed in order to find the nodes where K or Omega values go below 0." << finl;
323 probleme().postraiter(1);
325 };
326 }
327 if (count_omega_too_big)
328 {
329 const double time = le_champ_K_Omega->temps();
330 Journal() << "Values forced for omega because:" << finl;
331 Journal() << "Maximum values found for omega on " << count_omega_too_big << "/" << size << " nodes at time " << time << finl;
332
333 if (exit_on_big_omega_)
334 {
335 Cerr << "The problem is postprocessed in order to find the nodes where Omega values too high." << finl;
336 probleme().postraiter(1);
338 };
339
340 }
341 }
342}
343/*! @brief on remet omega et K positifs
344 *
345 */
: 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.