TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Traitement_particulier_NS_CEG.cpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, 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 <Traitement_particulier_NS_CEG.h>
17#include <Navier_Stokes_Turbulent.h>
18#include <Domaine_VF.h>
19#include <Probleme_base.h>
20#include <Schema_Temps_base.h>
21#include <sys/stat.h>
22#include <communications.h>
23#include <Param.h>
24#include <Milieu_base.h>
25#include <SFichier.h>
26#include <Domaine.h>
27#include <TRUSTList.h>
28#include <Perf_counters.h>
29#include <Fluide_Incompressible.h>
30#include <Modele_turbulence_hyd_RANS_K_Eps_base.h>
31#include <Pb_Hydraulique_Turbulent.h>
32#include <Champ_P1NC.h>
33#include <Postraitement.h>
34
35Implemente_base_sans_constructeur_ni_destructeur(Traitement_particulier_NS_CEG,"Traitement_particulier_NS_CEG",Traitement_particulier_NS_base);
36
37/*! @brief
38 *
39 * @param (Sortie& is) un flot de sortie
40 * @return (Sortie&) le flot de sortie modifie
41 */
43{
44 return is;
45}
46
47
48/*! @brief
49 *
50 * @param (Entree& is) un flot d'entree
51 * @return (Entree&) le flot d'entree modifie
52 */
54{
55 return is;
56}
57
58inline void error(const Nom& message)
59{
60 Cerr << finl;
61 Cerr << "=========================================================" << finl;
62 Cerr << "Error in the use of Traitement_particulier CEG !" << finl;
63 if (message!="")
64 Cerr << "-> " << message << finl;
65 else
66 Cerr << "-> Case not expected, contact pierre.ledac@c-s.fr" << finl;
68}
69
71{
72 haspi_=0;
73 C_=125.;
78 debug_=1;
79 dt_post_=-1;
80 t_deb_=DMAXFLOAT;
81 t_fin_=DMAXFLOAT;
83 dernier_temps_=-1e9;
84 // Verification gravite
85 if ( !mon_equation->milieu().a_gravite() ||
86 mon_equation->milieu().gravite().valeurs()(0,0)!=0 ||
87 mon_equation->milieu().gravite().valeurs()(0,1)!=0 ||
88 mon_equation->milieu().gravite().valeurs()(0,2)>=0 ) error("Error ! Gravity should be defined and oriented parallel to Z, downwards.");
89 // Verification VEF 3D
90 const DoubleTab& vitesse = mon_equation->inconnue().valeurs();
91 if (vitesse.nb_dim()!=2 || vitesse.dimension(1)!=3) error("Error ! Only works in VEF 3D.");
92
93 // XD traitement_particulier_ceg traitement_particulier_base ceg BRACE Keyword for a CEG ( Gas Entrainment Criteria)
94 // XD_CONT calculation. An objective is deepening gas entrainment on the free surface. Numerical analysis can be
95 // XD_CONT performed to predict the hydraulic and geometric conditions that can handle gas entrainment from the free
96 // XD_CONT surface.
97
98 Param param("lire_ceg");
99 param.ajouter("frontiere",&la_surface_libre_nom_,Param::REQUIRED); // XD_ADD_P chaine
100 // XD_CONT To specify the boundaries conditions representing the free surfaces
101 param.ajouter("t_deb",&t_deb_,Param::REQUIRED); // XD_ADD_P double
102 // XD_CONT value of the CEG's initial calculation time
103 param.ajouter("t_fin",&t_fin_); // XD_ADD_P double
104 // XD_CONT not_set time during which the CEG's calculation was stopped
105 param.ajouter("dt_post",&dt_post_); // XD_ADD_P double
106 // XD_CONT periode refers to the printing period, this value is expressed in seconds
107 param.ajouter("haspi",&haspi_,Param::REQUIRED); // XD_ADD_P double
108 // XD_CONT The suction height required to calculate AREVA's criterion
109 param.ajouter("debug",&debug_); // XD_ADD_P int
110 // XD_CONT not_set
111 Param& param_areva=param.ajouter_param("AREVA"); // XD_ADD_P ceg_areva
112 // XD_CONT AREVA's criterion
113 // 2XD ceg_areva objet_lecture nul INHERITS_BRACE not_set
114 param_areva.ajouter("C",&C_); // 2XD_ADD_P double
115 // 2XD_CONT not_set
116 Param& param_cea_jaea =param.ajouter_param("CEA_JAEA"); // XD_ADD_P ceg_cea_jaea
117 // XD_CONT CEA_JAEA's criterion
118 // 2XD ceg_cea_jaea objet_lecture nul INHERITS_BRACE not_set
119 param_cea_jaea.ajouter("normalise",&critere_cea_jaea_normalise_); // 2XD_ADD_P int
120 // 2XD_CONT renormalize (1) or not (0) values alpha and gamma
121 param_cea_jaea.ajouter("nb_mailles_mini",&nb_mailles_mini_); // 2XD_ADD_P int
122 // 2XD_CONT Sets the minimum number of cells for the detection of a vortex.
123 param_cea_jaea.ajouter("min_critere_Q_sur_max_critere_Q",&min_critere_Q_sur_max_critere_Q_); // 2XD_ADD_P double
124 // 2XD_CONT Is an optional keyword used to correct the minimum values of Q's criterion taken into account in the
125 // 2XD_CONT detection of a vortex
127
128
129 calculer_critere_areva_=(param.get_list_mots_lus().rang("AREVA")!=-1);
130 calculer_critere_cea_jaea_=(param.get_list_mots_lus().rang("CEA_JAEA")!=-1);
131 Motcle mot;
132 is >> mot;
133 if (mot!="}") error("On attendait une }");
134 Cerr << "haspi=" << haspi_ << finl;
135 Cerr << "calculer_critere_areva="<< calculer_critere_areva_ << finl;
136 Cerr << "calculer_critere_cea_jaea="<<calculer_critere_cea_jaea_<<finl;
137 Cerr << "nb_mailles_mini=" << nb_mailles_mini_ << finl;
138 Cerr << "t_deb_=" << t_deb_ << finl;
139 Cerr << "t_fin_=" << t_deb_ << finl;
140 Cerr << "min_critere_Q_sur_max_critere_Q_=" << min_critere_Q_sur_max_critere_Q_ << finl;
141 if (min_critere_Q_sur_max_critere_Q_>0) error("Error ! min_critere_Q_sur_max_critere_Q_ should less or equal to 0.");
142 return is;
143}
144
145
147{
148 // Recherche de la frontiere surface libre:
149 int trouve=0;
150 const Conds_lim& les_cls=mon_equation->domaine_Cl_dis().les_conditions_limites();
151 for (int num_cl=0; num_cl<les_cls.size(); num_cl++)
152 {
153 // Surface libre trouvee
154 if (les_cls[num_cl]->frontiere_dis().le_nom()==la_surface_libre_nom_)
155 {
156 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, mon_equation->inconnue().domaine_dis_base());
157 la_surface_libre_ = ref_cast(Front_VF,les_cls[num_cl]->frontiere_dis());
158 trouve=1;
159 int nb_faces=la_surface_libre_->nb_faces();
160 for (int ind_face=0; ind_face<nb_faces; ind_face++)
161 {
162 int face = la_surface_libre_->num_face(ind_face);
163 if (domaine_VF.face_normales(face,0)!=0 || domaine_VF.face_normales(face,1)) error("The free surface should be normal to Z on all faces.");
164 }
165 }
166 }
167 if (!trouve)
168 {
169 Cerr << "The free surface named " << la_surface_libre_nom_ << " has not been found." << finl;
171 }
172 // KEps si critere AREVA
174 if (!sub_type(Pb_Hydraulique_Turbulent,mon_equation->probleme()) || !sub_type(Modele_turbulence_hyd_RANS_K_Eps_base,ref_cast(Navier_Stokes_Turbulent,ref_cast(Pb_Hydraulique_Turbulent,mon_equation->probleme()).equation(0)).modele_turbulence()))
175 error("AREVA criterion can only be calculated with a RANS K-eps simulation.");
176
177 // Vorticite dans le jeu de donnees si AREVA
179 mon_equation->creer_champ("vorticite");
180 // && !ref_cast(Navier_Stokes_std,mon_equation.valeur()).vorticite().non_nul()) error("The vorticity should be postreated in the datafile for the AREVA criterion.");
181
182 // CritereQ dans le jeu de donnees si CEA_JAEA
184 mon_equation->creer_champ("critere_Q");
185 //&& !ref_cast(Navier_Stokes_std,mon_equation.valeur()).critereQ().non_nul()) error("The Q criterion should be postreated in the datafile for the CEA/JAEA criterion.");
186}
187
189{
190 if (mon_equation->probleme().schema_temps().temps_courant()>=t_deb_ && mon_equation->probleme().schema_temps().temps_courant()<t_fin_)
191 {
192 Cerr << "Beginning calculation of the criteria..." << finl;
193 statistics().create_custom_counter("m1",2,"TrioCFD");
194 statistics().begin_count("m1",statistics().get_last_opened_counter_level()+1);
195 // Calcul des 2 criteres
197 if (debug_) Cout << "CPU AREVA criterion " << statistics().get_time_since_last_open("m1") << " s" << finl << finl;
198 statistics().end_count("m1");
200 dernier_temps_ = mon_equation->probleme().schema_temps().temps_courant();
201 Cerr << "End of the calculation of the criteria." << finl;
202 }
203}
204
206{
207 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, mon_equation->inconnue().domaine_dis_base());
208 const DoubleTab& vitesse = mon_equation->inconnue().valeurs();
209 const DoubleTab& vorticite = mon_equation->get_champ("vorticite").valeurs();
210 const Navier_Stokes_Turbulent& eqn = ref_cast(Navier_Stokes_Turbulent,ref_cast(Pb_Hydraulique_Turbulent,mon_equation->probleme()).equation(0));
211 const DoubleTab& KEps = ref_cast(Modele_turbulence_hyd_RANS_K_Eps_base,eqn.modele_turbulence()).get_unknown().valeurs();
212
213 double gz = mon_equation->milieu().gravite().valeurs()(0,2);
214 double K_max_local=0;
215 ArrOfDouble centre_vortex(3);
216 int nb_face_par_elem = domaine_VF.elem_faces().dimension(1);
217 int nb_faces=la_surface_libre_->nb_faces();
218
219 // On boucle sur les faces reelles
220 for (int ind_face=0; ind_face<nb_faces; ind_face++)
221 {
222 int face = la_surface_libre_->num_face(ind_face);
223 // On recupere chaque maille adjacente
224 int elem = domaine_VF.face_voisins(face,0);
225 if (elem<0) elem = domaine_VF.face_voisins(face,1);
226
227 // Interpolation des champs aux elements:
228 double vz=0;
229 double k=0;
230 double epsilon=0;
231 for (int i=0; i<nb_face_par_elem; i++)
232 {
233 face = domaine_VF.elem_faces(elem,i);
234 vz+=vitesse(face,2);
235 k+=KEps(face,0);
236 epsilon+=KEps(face,1);
237 }
238 vz*=0.25;
239 k*=0.25;
240 epsilon*=0.25;
241
242 // Calcul de K
243 double wz = std::fabs(vorticite(elem,2));
244 double omega;
245 if (epsilon>0)
246 omega = k * wz / epsilon; // Rotation de l'ecoulement
247 else
248 omega = 0;
249 double lambda = std::max(-vz,0.) / sqrt(-gz*haspi_); // Aspiration de l'ecoulement
250 double K = C_ * omega * lambda; // C_ pour une normalisation
251
252 // On cherche le vortex (std::max(K) et son centre)
253 if (K>K_max_local)
254 {
255 K_max_local=K;
256 for (int i=0; i<3; i++) centre_vortex[i] = domaine_VF.xp(elem,i);
257 }
258 }
259 // Parallelisme : Impression par le processeur le plus grand qui possede le vortex
260 double K_max_global=mp_max(K_max_local);
261 int pe=(K_max_global==K_max_local?Process::me():-1);
262 int pe_max=(int)mp_max(pe);
263 if (pe==pe_max) imprimer(K_max_global, "AREVA", centre_vortex, 0);
264 Cerr << "-> AREVA criterion : Biggest vortex at (x,y,z)=(" << centre_vortex[0] << "," << centre_vortex[1] << "," << centre_vortex[2] << ")" << finl;
265}
266
267int Traitement_particulier_NS_CEG::lpost(double temps_courant, double dt_post) const
268{
269 double epsilon = 1.e-8;
270 if (dt_post<=temps_courant - dernier_temps_)
271 return 1;
272 else
273 {
274 // Voir Schema_Temps_base::limpr pour information sur epsilon et modf
275 double i, j;
276 modf(temps_courant/dt_post + epsilon, &i);
277 modf(dernier_temps_/dt_post + epsilon, &j);
278 return ( i>j );
279 }
280}
281
283{
284 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF, mon_equation->inconnue().domaine_dis_base());
285 int nb_faces=la_surface_libre_->nb_faces();
286 int nb_elem=domaine_VF.nb_elem();
287
288 IntVect elements_surface_libre(nb_faces); // Tableau donnant les elements au contact des faces de la surface libre
289 elements_surface_libre=-1;
290 IntVect vortex_potentiel(nb_elem); // Tableau donnant pour chaque element si le vortex a ete evalue
291 vortex_potentiel=0;
292 // On calcule le critereQ
293
294 // GF on laisse faire NS...
295 // DoubleTab critereQ(nb_elem);
296 //ref_cast(Champ_P1NC,mon_equation->inconnue()).calcul_critere_Q(critereQ);
297 const DoubleTab& critereQ = mon_equation->get_champ("critere_Q").valeurs();
298 double t1 = 0. , t2=0. , t3=0.;
299
300 // On boucle sur les faces reelles
301 // ou Q>0 (domaine potentielle de vortex)
302 for (int ind_face=0; ind_face<nb_faces; ind_face++)
303 {
304 int face = la_surface_libre_->num_face(ind_face);
305 // On recupere chaque maille adjacente
306 int elem = domaine_VF.face_voisins(face,0);
307 if (elem<0) elem = domaine_VF.face_voisins(face,1);
308 // On marque:
309 if (critereQ(elem)>0)
310 {
311 elements_surface_libre(ind_face)=elem;
312 vortex_potentiel(elem)=1;
313 }
314 }
315 // Dimensionnement des tableaux recueillant les infos sur les vortexes
316 int nb_vortex=0;
317 double R0=0;
318 using Kokkos::numbers::pi;
319 DoubleTab Critere(nb_vortex,3);
320 DoubleTab Centre(nb_vortex,3);
321 ArrOfDouble Rayon(nb_vortex);
322 ArrOfDouble Max_Critere_Q(nb_vortex);
323 ArrOfInt Taille(nb_vortex);
324 ArrOfDouble centre_vortex(3); // Tableau de travail
325
326 int nb_dtheta=36; // Angle dtheta=10deg
327 double dtheta=2*pi/nb_dtheta;
328 ArrOfInt elements(nb_dtheta);
329 DoubleTab points(nb_dtheta,3);
330 DoubleTab u(nb_dtheta,3);
331 int taille_maxi = 0;
332 // Boucle tant que la liste d'elements n'est pas vide(tous les vortexes seront alors evalues)
333 statistics().create_custom_counter("m1",2,"TrioCFD");
334 while (elements_surface_libre.mp_max_vect()>=0)
335 {
336 statistics().begin_count("m1",statistics().get_last_opened_counter_level()+1);
337 double critereQ_max=0;
338 int ind_face_centre_vortex=-1;
339 // On boucle sur les elements non evalues pour trouver le plus grand critere Q
340 for (int ind_face=0; ind_face<nb_faces; ind_face++)
341 {
342 int elem=elements_surface_libre(ind_face);
343 if (elem>=0 && critereQ(elem)>critereQ_max)
344 {
345 critereQ_max=critereQ(elem);
346 ind_face_centre_vortex=ind_face;
347 }
348 }
349 // Plus grand Q sur l'ensemble des processeurs:
350 double critereQ_mp_max=mp_max(critereQ_max);
351 // On traite le cas ou meme Q (on prend alors le processeur de rang le plus eleve)
352 int pe=(critereQ_mp_max==critereQ_max?Process::me():-1);
353 int pe_mp_max=(int)mp_max(pe);
354 int taille_vortex=0;
355 // Le centre du vortex est le centre de elem_centre_vortex
356 // on le communique a tous les processeurs
357 if (pe==pe_mp_max)
358 {
359 int face_centre_fortex = la_surface_libre_->num_face(ind_face_centre_vortex);
360 int elem_centre_vortex = elements_surface_libre(ind_face_centre_vortex);
361 vortex_potentiel(elem_centre_vortex)=0; // Ne sera plus evalue plus tard
362 taille_vortex=1;
363
364 // On calcule le rayon initial (rayon du cercle inscrit) dans le triangle:
365 // https://fr.wikipedia.org/wiki/Cercles_inscrit_et_exinscrits_d%27un_triangle
366 // Rayon d'un cercle inscrit dans un triangle: R=2*Surface(triangle)/perimetre(triangle)
367 // Calcul du perimetre
368 double surface=domaine_VF.face_surfaces(face_centre_fortex);
369 const DoubleTab& coord=mon_equation->probleme().domaine().coord_sommets();
370 int nb_sommet_face=domaine_VF.face_sommets().dimension(1);
371 double perimetre=0;
372 for (int i=0; i<nb_sommet_face; i++)
373 {
374 int som1 = domaine_VF.face_sommets(face_centre_fortex,i);
375 int som2 = (i!=nb_sommet_face-1 ? domaine_VF.face_sommets(face_centre_fortex,i+1) : domaine_VF.face_sommets(face_centre_fortex,0));
376 double dx=coord(som2,0)-coord(som1,0);
377 double dy=coord(som2,1)-coord(som1,1);
378 perimetre+=sqrt(dx*dx+dy*dy);
379 }
380 // On multiplie par 3/4 par homothetie
381 R0 = 0.6*0.75*(2*surface/perimetre);
382
383 // Centre du vortex
384 for (int i=0; i<3; i++) centre_vortex[i]=domaine_VF.xp(elem_centre_vortex,i);
385 // Envoi des donnees tous les autres processes:
386 for (int p=0; p<nproc(); p++)
387 if (p!=pe_mp_max)
388 {
389 envoyer(centre_vortex,pe_mp_max,p,p);
390 envoyer(R0,pe_mp_max,p,p);
391 }
392 }
393 else
394 {
395 // Receptions des donnees
396 recevoir(centre_vortex,pe_mp_max,me(),me());
397 recevoir(R0,pe_mp_max,me(),me());
398 }
399 /**************************************************************/
400 // Calcul des criteres autour du vortex de centre centre_vortex
401 /**************************************************************/
402 // On va cherche le cercle le plus large pour lequel Q>0 et
403 // ensuite on calcule les circulations
404 // Processus de dichotomie sur R
405 t1 = statistics().get_time_since_last_open("m1");
406 statistics().end_count("m1");
407 double R=R0;
408 double dR=R;
409 int niter=0;
410 int limite_vortex_atteinte=0;
411 int points_trouves=0;
412 statistics().create_custom_counter("m2",2,"TrioCFD");
413 statistics().begin_count("m2",statistics().get_last_opened_counter_level()+1);
414 while (dR>0.01*R0)
415 {
416 double inside_vortex=1;
417 points_trouves=0;
418 for (int i_theta=0; i_theta<nb_dtheta; i_theta++)
419 {
420 double theta=i_theta*dtheta;
421 points(i_theta,0)=centre_vortex[0]+R*cos(theta);
422 points(i_theta,1)=centre_vortex[1]+R*sin(theta);
423 points(i_theta,2)=centre_vortex[2];
424 }
425 // On cherche les elements contenant le point x,y,z:
426 mon_equation->domaine_dis().domaine().chercher_elements(points,elements);
427 for (int i_theta=0; i_theta<nb_dtheta; i_theta++)
428 {
429 int elem=elements[i_theta];
430 // Test pour verifier que le cercle R0 est bien inscrit au tetraedre:
431 if (niter==0 && pe==pe_mp_max)
432 {
433 int elem_centre_vortex=elements_surface_libre(ind_face_centre_vortex);
434 if (elem!=elem_centre_vortex)
435 error("Error, R0 is too large. Algorithm problem, contact pierre.ledac@c-s.fr");
436 }
437 if (elem>=0 && elem<nb_elem)
438 {
439 // Point trouve dans le domaine reel
440 points_trouves++;
441 if (critereQ(elem)<=min_critere_Q_sur_max_critere_Q_*critereQ_mp_max)
442 {
443 // On est en dehors du tourbillon
444 inside_vortex=0;
445 break;
446 }
447 }
448 //Cerr << "elem=" << elem << " Q=" << critereQ(elem) << finl;
449 }
450 inside_vortex=mp_min(inside_vortex);
451 if (inside_vortex)
452 {
453 if (limite_vortex_atteinte) dR*=0.5;
454 //if (debug_) Cerr << "[" << niter << "] R=" << R << " dR=" << dR << finl;
455 R+=dR; // On continue d'avancer
456 // On supprime les elements du vortex actuel de la liste
457 for (int i_theta=0; i_theta<nb_dtheta; i_theta++)
458 {
459 int elem=elements[i_theta];
460 if (elem>=0 && elem<nb_elem)
461 {
462 if (vortex_potentiel(elem)!=0) taille_vortex++;
463 vortex_potentiel(elem)=0; // Ne seront plus evalues plus tard
464 }
465 }
466 }
467 else
468 {
469 limite_vortex_atteinte=1;
470 dR*=0.5;
471 //if (debug_) Cerr << "[" << niter << "] R=" << R << " dR=" << -dR << finl;
472 R-=dR; // On recule
473 }
474 niter++;
475 }
476 R-=dR;
477 t2 = statistics().get_time_since_last_open("m2");
478 statistics().end_count("m2");
479 statistics().create_custom_counter("m3",2,"TrioCFD");
480 statistics().begin_count("m3",statistics().get_last_opened_counter_level()+1);
481 // On ne prend que des vortex superieres a N mailles dont toutes les
482 // mailles sont dans le domaine fluide (points_trouves==nb_dtheta)
483 points_trouves=check_int_overflow(mp_sum(points_trouves));
484 int taille_vortex_mailles=check_int_overflow(mp_sum(taille_vortex));
485 taille_maxi = (taille_vortex_mailles > taille_maxi ? taille_vortex_mailles : taille_maxi);
486 if (points_trouves==nb_dtheta && taille_vortex_mailles>nb_mailles_mini_)
487 {
488 //Cerr << printf("-> Critere CEA_JAEA: Vortex de %d mailles en (x,y,z)=(%.4f,%.4f,%.4f) Rayon=%.2f std::max(critere_Q)=%.2f\n",taille_vortex_mailles,centre_vortex(0),centre_vortex(1),centre_vortex(2),R,critereQ_mp_max);
489 if (debug_)
490 {
491 Cerr << "-> CEA_JAEA criterion : Vortex " << nb_vortex << " de " << taille_vortex_mailles << " elements ";
492 Cerr << "in (x,y,z)=(" << centre_vortex[0] << "," << centre_vortex[1] << "," << centre_vortex[2] << ") ";
493 Cerr << "Radius=" << R << " std::max(critere_Q)=" << critereQ_mp_max;
494 //int e = mon_equation->domaine_dis().domaine().chercher_elements(centre_vortex(0),centre_vortex(1),centre_vortex(2));
495 //if (e>=0) Cerr << "Sur process " << Process::me() << " critere_Q=" << critereQ(e) << finl;
496 }
497 // On evalue la vitesse aux points:
498 mon_equation->inconnue().valeur_aux(points,u);
499 double alpha=0;
500 double gamma=0;
501 // On integre sur le cercle pour calcul alpha et gamma:
502 for (int i_theta=0; i_theta<nb_dtheta; i_theta++)
503 {
504 double theta=i_theta*dtheta;
505 int elem=elements[i_theta];
506 if (elem>=0 && elem<nb_elem)
507 {
508 alpha+=(u(i_theta,0)*cos(theta)+u(i_theta,1)*sin(theta))*R*dtheta; // Integration vitesse normale (dans le plan)
509 gamma+=(u(i_theta,1)*cos(theta)-u(i_theta,0)*sin(theta))*R*dtheta; // Integration vitesse tangentielle
510 }
511 }
512
513 alpha=mp_sum(alpha)/(pi*R*R);
514 gamma=mp_sum(gamma);
515 // On adimensionnalise eventuellement selon jeu de donnees (conseille):
517 {
518 double nu = ref_cast(Fluide_Incompressible,mon_equation->milieu()).viscosite_cinematique().valeurs()(0,0);
519 double gz = mon_equation->milieu().gravite().valeurs()(0,2);
520 alpha*=nu/(gz*haspi_); // alpha*=alpha*nu/(gh)
521 gamma/=nu; // gamma*=gamma/nu
522 }
523 // On redimensionne:
524 Critere.resize(nb_vortex+1,3);
525 Centre.resize(nb_vortex+1,3);
526 Rayon.resize(nb_vortex+1);
527 Max_Critere_Q.resize(nb_vortex+1);
528 Taille.resize(nb_vortex+1);
529 // On remplit
530 Critere(nb_vortex,0)=alpha; // alpha
531 Critere(nb_vortex,1)=Critere(nb_vortex,0)*gamma*gamma; // alpha*gamma^2
532 Critere(nb_vortex,2)=alpha*Critere(nb_vortex,1); // (alpha*gamma)^2
533 Rayon[nb_vortex]=R;
534 Max_Critere_Q[nb_vortex]=critereQ_mp_max;
535 Taille[nb_vortex]=taille_vortex_mailles;
536 for (int i=0; i<3; i++) Centre(nb_vortex,i)=centre_vortex[i];
537 if (debug_) Cerr << " alpha=" << Critere(nb_vortex,0) << " alpha*gamma^2=" << Critere(nb_vortex,1) << " (alpha*gamma)^2=" << Critere(nb_vortex,2) << finl;
538 R+=dR;
539 nb_vortex++;
540 }
541 // Mise a jour de elements_surface_libre par rapport a vortex_potentiel:
542 for (int ind_face=0; ind_face<nb_faces; ind_face++)
543 {
544 int elem=elements_surface_libre(ind_face);
545 if (elem>=0 && vortex_potentiel(elem)==0) elements_surface_libre(ind_face)=-1;
546 }
547 t3 = statistics().get_time_since_last_open("m3");
548 statistics().end_count("m3");
549 if (debug_) Cout << "CPU AREVA criterion m1= " << t1 << " s m2= " << t2 << " s m3= " << t3 << finl;
550 }
551 const Schema_Temps_base& sch=mon_equation->probleme().schema_temps();
552 if (nb_vortex==0)
553 {
554 Cerr << "-> CEA_JAEA criterion : No vortex detected of size larger than " << nb_mailles_mini_ << " elements. A potential vortex was " << taille_maxi << " elements large." << finl;
555 }
556 else
557 {
558 Cerr << "-> CEA_JAEA criterion : we found " << nb_vortex << " vortices near the free surface." << finl;
559 // Recherche du vortex donnant la valeur maximale pour chaque critere:
560 ArrOfDouble Critere_max(3);
561 ArrOfInt Vortex_max(3);
562 Vortex_max=-1;
563 for (int critere=0; critere<3; critere++)
564 for (int vortex=0; vortex<nb_vortex; vortex++)
565 if (Critere(vortex,critere)>Critere_max[critere])
566 {
567 Critere_max[critere]=Critere(vortex,critere);
568 Vortex_max[critere]=vortex;
569 }
570
571 // On prend comme vortex principal celui indique par alpha*gamma^2:
572 int vortex_principal = Vortex_max[1];
573 if (vortex_principal>=0)
574 {
576 {
577 const Postraitement& post = ref_cast(Postraitement,mon_equation->probleme().postraitements()[0].valeur());
578 // Si dt_post pas lu dans le jeu de donnees, on prend celui du postraitement
579 if (dt_post_<0) dt_post_ = post.dt_post();
580 // Impression des criteres
581 Noms Critere_nom(3);
582 Critere_nom[0]="CEA_JAEA_alpha";
583 Critere_nom[1]="CEA_JAEA_alphaXgamma2";
584 Critere_nom[2]="CEA_JAEA_alpha2Xgamma2";
585
586 for (int critere=0; critere<3; critere++)
587 {
588 //int vortex = Vortex_max(critere);
589 for (int i=0; i<3; i++) centre_vortex[i]=Centre(vortex_principal,i);
590 //imprimer(Critere_max(critere), Critere_nom(critere), centre_vortex, Rayon(vortex));
591 imprimer(Critere(vortex_principal,critere), Critere_nom[critere], centre_vortex, Rayon[vortex_principal]);
592
593 // Impression periodique des caracteristiques du vortex pour chaque critere
594 if (lpost(sch.temps_courant(),dt_post_))
595 {
596 Nom filename("Vortex_");
597 filename+=Critere_nom[critere];
598 filename+="_";
599 filename+=Objet_U::nom_du_cas();
600 filename+=".";
601 filename+=(Nom)(sch.temps_courant());
602 filename+=".csv";
603 SFichier file(filename);
604 file << "# " << filename << finl;
605 file << "# Temps";
606 for (int i_theta=0; i_theta<nb_dtheta; i_theta++)
607 {
608 double theta=i_theta*dtheta;
609 double x=centre_vortex[0]+Rayon[vortex_principal]*cos(theta);
610 double y=centre_vortex[1]+Rayon[vortex_principal]*sin(theta);
611 double z=centre_vortex[2]+2*R0;
612 file << " x= " << x << " y= " << y << " z= " << z;
613 }
614 file << finl;
615 file << "# OWN_PTR(Champ_base) CRITERE" << finl;
616 file << "# Type POINTS" << finl;
617 file << sch.temps_courant();
618 //for (int i_theta=0;i_theta<nb_dtheta;i_theta++) file << " " << Critere_max(critere);
619 for (int i_theta=0; i_theta<nb_dtheta; i_theta++) file << " " << Critere(vortex_principal,critere);
620 file << finl;
621 }
622 }
623 // Impression periodique des centres de tous les vortex trouves
624 if (lpost(sch.temps_courant(),dt_post_))
625 {
626 Nom filename("Centres_vortex.");
627 filename+=(Nom)(sch.temps_courant());
628 filename+=".csv";
629 SFichier file(filename);
630 file << "# " << filename << finl;
631 file << "# Temps";
632 for (int vortex=0; vortex<nb_vortex; vortex++) file << " x= " << Centre(vortex,0) << " y= " << Centre(vortex,1) << " z= " << Centre(vortex,2)+2*R0;
633 file << finl;
634 file << "# OWN_PTR(Champ_base) RAYON" << finl;
635 file << "# Type POINTS" << finl;
636 file << sch.temps_courant();
637 for (int vortex=0; vortex<nb_vortex; vortex++) file << " " << Rayon[vortex];
638 file << finl;
639 }
640 }
641 Cerr << "-> CEA_JAEA criterion : The main vortex (largest alpha*gamma^2) was vortex number " << vortex_principal << finl;
642 }
643 }
644}
645
646void Traitement_particulier_NS_CEG::imprimer(const double valeur_critere, const Nom& critere, const ArrOfDouble& centre_vortex, const double rayon_vortex)
647{
648 Nom filename=Objet_U::nom_du_cas();
649 filename+="_";
650 filename+=mon_equation->probleme().le_nom()+"_";
651 filename+=critere;
652 filename+=".csv";
653 SFichier fic;
654 struct stat f;
655 const Schema_Temps_base& sch=mon_equation->probleme().schema_temps();
656 if (stat(filename,&f) || (sch.nb_impr()==0 && !mon_equation->probleme().reprise_effectuee()))
657 {
658 fic.ouvrir(filename);
659 // Ecriture en tete
660 fic << "# Time \tVortex center (x,y,z) \t\t\tVortex radius \t" << critere << " criterion" << finl;
661 }
662 else
663 fic.ouvrir(filename,ios::app);
664 fic.precision(sch.precision_impr());
665 fic.setf(ios::scientific);
666 // Ecriture
667 fic << sch.temps_courant() << " \t" << centre_vortex[0] << " \t" << centre_vortex[1] << " \t" << centre_vortex[2] << " \t" << rayon_vortex << " \t" << valeur_critere << finl;
668 fic.close();
669}
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
int face_sommets(int i, int j) const
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
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
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
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
classe Fluide_Incompressible Cette classe represente un d'un fluide incompressible ainsi que
class Front_VF
Definition Front_VF.h:36
Classe Modele_turbulence_hyd_RANS_K_Eps_base Classe de base des modeles de type RANS_keps.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
classe Navier_Stokes_Turbulent Cette classe represente l'equation de la dynamique pour un fluide
const Modele_turbulence_hyd_base & modele_turbulence() const
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const Nom & le_nom() const override
Renvoie *this;.
Definition Nom.cpp:563
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
friend class Entree
Definition Objet_U.h:76
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
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(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
int lire_avec_accolades_depuis(Entree &is)
Parse the parameter block { ... } from is.
Definition Param.cpp:32
Param & ajouter_param(const char *keyword, Param::Nature nat=Param::OPTIONAL)
Register a nested Param block and return a reference to it so it can be populated in turn.
Definition Param.cpp:401
classe Pb_Hydraulique_Turbulent Cette classe represente un probleme d'hydraulique turbulent dans
classe Postraitement La classe est dotee -d une liste de champs generiques champs_post_complet_ qui c...
Probleme_base & probleme()
double dt_post() const
Postraitements & postraitements()
static double mp_min(double)
Definition Process.cpp:386
static int check_int_overflow(trustIdType)
Definition Process.cpp:428
static double mp_max(double)
Definition Process.cpp:376
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
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
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
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
class Schema_Temps_base
double temps_courant() const
Renvoie le temps courant.
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
void resize(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTArray.h:156
int nb_dim() const
Definition TRUSTTab.h:199
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_TYPE_ mp_max_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:158
int lpost(double temps_courant, double dt_post) const
void imprimer(const double, const Nom &, const ArrOfDouble &, const double)
classe Traitement_particulier_NS_base Derive de Support_Champ_Masse_Volumique: utilisation de rho