TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Traitement_particulier_NS_THI_VEF.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_THI_VEF.h>
17#include <calcul_spectres.h>
18#include <Domaine_VEF.h>
19#include <Navier_Stokes_std.h>
20#include <Champ_P1NC.h>
21#include <Domaine.h>
22#include <Periodique.h>
23#include <TRUSTTrav.h>
24#include <Pave.h>
25#include <Pb_Hydraulique_Turbulent.h>
26#include <Noms.h>
27#include <Nom.h>
28#include <distances_VEF.h>
29#include <SFichier.h>
30#include <TRUSTVect.h>
31#include <MD_Vector_tools.h>
32
33// appels librairies fonctions calcul FFT (JMFFT)
34extern "C" void fftfax(int ,int* ,double* );
35extern "C" void cftfax(int ,int* ,double* );
36extern "C" void rfftmlt(double*, double*, double*, int*, int, int, int, int, int);
37
38
39
40// Avec cette classe le calcul de spectres en VEF ne depend pas de la
41// discretisation. On peut obtenir :
42// * des spectres 3D en construisant des grilles cartesiennes (les grilles construites dependent de la discretisation),
43// * des spectres 1D, en suivant des lignes et non plus des grilles cartesiennes.
44
45
46Implemente_instanciable(Traitement_particulier_NS_THI_VEF,"Traitement_particulier_NS_THI_VEF",Traitement_particulier_NS_THI);
47
48
49/*! @brief
50 *
51 * @param (Sortie& is) un flot de sortie
52 * @return (Sortie&) le flot de sortie modifie
53 */
55{
56 return is;
57}
58
59
60/*! @brief
61 *
62 * @param (Entree& is) un flot d'entree
63 * @return (Entree&) le flot d'entree modifie
64 */
66{
67 return is;
68}
70{
71 // valeurs par defaut
72 init = 0;
73 fac_init = 0;
74 oui_transf = 0;
76 oui_conservation_Ec = 0;
77 calc_sp_3D = 0;
78 calc_sp_1D = 0;
79 calc_correlations = 0;
80 cle_suppr_vit_moy = 0;
81 nb_champs_scalaires=0;
82 periode_calc_spectre=0;
83 L_BOITE=-1;
84 Ec_init=-1;
85 // FIN valeurs par defaut
86
87 Motcle accouverte = "{" , accfermee = "}" ;
88 Motcle valec="val_Ec";
89 Motcle facon="facon_init";
90 Motcle motbidon, motlu;
91 is >> motbidon ;
92 if (motbidon == accouverte)
93 {
94 Motcles les_mots(14);
95 {
96 les_mots[0] = "init_Ec";
97 les_mots[1] = "periode_calc_spectre";
98 les_mots[2] = "calc_spectre";
99 les_mots[3] = "conservation_Ec";
100 les_mots[4] = "longueur_boite";
101 les_mots[6] = "Spectre_3D";
102 les_mots[7] = "Spectre_1D";
103 les_mots[8] = "suppr_vit_moy";
104 les_mots[9] = "3D";
105 les_mots[10] = "1D";
106 les_mots[12] = "correlations";
107 les_mots[13] = "champs_scalaires";
108 }
109 {
110 is >> motlu;
111 while(motlu != accfermee)
112 {
113 int rang=les_mots.search(motlu);
114 switch(rang)
115 {
116 case 0 :
117 {
118 is >> init;
119 if (init!=0)
120 {
121 is >> motlu;
122 if (motlu==valec)
123 {
124 is >> Ec_init;
125 if (motlu==facon)
126 is >> fac_init; // Sur quelle valeur se base l initialisation??
127 if(je_suis_maitre())
128 {
129 Cerr << "Avec initialisation de l'energie cinetique sur la valeur Ec_init=" << Ec_init << finl;
130 Cerr << "par la methode (fac_init=" << fac_init << ") :";
131 switch(fac_init)
132 {
133 case 0 :
134 {
135 Cerr << " en se basant sur Ec_spatial" << finl;
136 break ;
137 }
138 case 1 :
139 {
140 Cerr << " en se basant sur Ec_spectral_1D" << finl;
141 break ;
142 }
143 case 3 :
144 {
145 Cerr << " en se basant sur Ec_spectral_3D" << finl;
146 break ;
147 }
148 }
149 }
150 }
151 else
152 {
153 if(je_suis_maitre())
154 {
155 Cerr << "Erreur dans la lecture de Traitement_particulier_NS_THI" << finl;
156 Cerr << "Le seul mot cle possible ici est : " << valec << finl;
157 Cerr << "Vous avez lu :" << motlu << finl;
159 }
160 }
161 }
162 break;
163 }
164 case 1 :
165 {
166 is >> periode_calc_spectre;
167 double temps_courant = mon_equation->inconnue().temps();
168 compteur_perio_spectre = (int)(temps_courant / periode_calc_spectre) + 1;
169 if (calc_sp_3D)
170 {
171 if(je_suis_maitre())
172 Cerr << "Calcul des spectres 3D tous les : " << periode_calc_spectre << finl;
173 }
174 if (calc_sp_1D)
175 {
176 if(je_suis_maitre())
177 Cerr << "Calcul des spectres 1D tous les : " << periode_calc_spectre << finl;
178 }
179 break;
180 }
181 case 2 :
182 {
183 is >> oui_calc_spectre;
184 break;
185 }
186 case 3 :
187 {
188 oui_conservation_Ec=1;
189 if(je_suis_maitre())
190 Cerr << "A chaque pas de temps, on multiplie le champ de vitesse par le coefficient permettant d'assurer Ec(n+1)=Ec(n)" << finl;
191 break;
192 }
193 case 4 :
194 {
195 is >> L_BOITE;
196 break;
197 }
198 case 6 :
199 {
200 is >> calc_sp_3D;
201 break;
202 }
203 case 7 :
204 {
205 is >> calc_sp_1D;
206 break;
207 }
208 case 8 :
209 {
210 is >> cle_suppr_vit_moy;
211 break;
212 }
213 case 9 :
214 {
215 Cerr << "Keyword 3D renamed to Spectre_3D in Traitement_particulier_NS_THI" << finl;
217 break;
218 }
219 case 10 :
220 {
221 Cerr << "Keyword 1D renamed to Spectre_1D in Traitement_particulier_NS_THI" << finl;
223 break;
224 }
225 case 12 :
226 {
227 is >> calc_correlations;
228 break;
229 }
230 case 13 :
231 {
232 is >> noms_champs_scalaires;
233 nb_champs_scalaires = noms_champs_scalaires.size();
234 break;
235 }
236 default :
237 {
238 if(je_suis_maitre())
239 {
240 Cerr << "Erreur dans la lecture de Traitement_particulier_NS_THI" << finl;
241 Cerr << "Les mots cles possibles sont :" << finl;
242 Cerr << les_mots;
243 Cerr << "Vous avez lu :" << motlu << finl;
245 }
246 break;
247 }
248 }
249 is >> motlu;
250 }
251 is >> motlu;
252 if (motlu != accfermee)
253 {
254 if(je_suis_maitre())
255 {
256 Cerr << "Erreur dans la lecture de Traitement_particulier_NS_THI" << finl;
257 Cerr << "On attendait une }" << finl;
258 Cerr << "Vous avez lu :" << motlu << finl;
260 }
261 }
262 }
263 }
264 else
265 {
266 if(je_suis_maitre())
267 {
268 Cerr << "Erreur dans la lecture de Traitement_particulier_NS_THI" << finl;
269 Cerr << "On attendait une {" << finl;
270 Cerr << "Vous avez lu :" << motlu << finl;
272 }
273 }
274
275 if (L_BOITE <0)
276 {
277 Cerr << " Vous devez entrer la longueur de la boite (cubique) de calcul avec le mot cle longueur_boite" << finl;
279 }
280 return is;
281}
282
283
285// Appelle les fonctions qui a priori ne doivent etre lancees qu'une fois
286// (sauf si le domaine de calcul change, raffinement, ...)
287{
288 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
289 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
290 const int nb_faces = domaine_VEF.nb_faces();
291 IntTab tab_domaine;
292 DoubleTab coord_domaine(nb_faces,dimension);
293 IntVect nb_coord_domaine(dimension);
294
295 if (cle_suppr_vit_moy)
297
298 if ( (calc_sp_3D || calc_sp_1D) && nproc()==1)
299 determine_tab_fft_VEF_3D(tab_domaine, coord_domaine, nb_coord_domaine, nb_spectres_3D, nb_points_3D);
300
301 if (calc_sp_1D && nproc()==1)
302 determine_tab_fft_VEF_1D(tab_domaine, coord_domaine, nb_coord_domaine, nb_spectres_1D, nb_points_1D);
303
304 cle_premier_pas_dt=0;
305 Ec_tot_old = 0;
306 temps_old = 0;
307
308
309
310 const int nb_elem = domaine_VEF.nb_elem();
311
312 DoubleTab coord_domaine_elem(nb_elem,dimension);
313 IntVect nb_coord_domaine_elem(dimension);
314
315 if ( (calc_sp_3D || calc_sp_1D) && nproc()==1)
316 determine_tab_fft_VEF_3D(tab_domaine, coord_domaine_elem, nb_coord_domaine_elem, nb_spectres_3D_elem, nb_points_3D_elem);
317
318
319
320}
321
322
324{
325 // Ajuste les valeurs du champ de vitesse pour retrouver une energie definie.
326 // La renormalisation peut se faire sur l'energie de l'espace physique ou
327 // sur l'energie de l'espace spectral (3D ou 1D).
328 DoubleTab& vitesse = mon_equation->inconnue().valeurs();
329 double Ec;
330
331 switch (fac_init)
332 {
333 case 0 :
334 {
335 // renormalisation par rapport a la valeur de l'energie "physique"
336 Ec = calcul_Ec_spatial(vitesse, "init");
337 if(je_suis_maitre())
338 Cerr << "Ec (espace physique) = " << Ec << finl;
339 break;
340 }
341 case 1 :
342 {
343 // renormalisation par rapport a la valeur de l'energie "spectrale" 1D
344 calcul_spectre_1D(vitesse, "init", Ec);
345 if(je_suis_maitre())
346 Cerr << "Ec (espace spectral 1D) = " << Ec << finl;
347 break;
348 }
349 // case 2 :
350 // {
351 // // multiplication de tout le champ vitesse par une valeur
352 // multiplier_vitesse(facteur_init);
353 // return;
354 // }
355 case 3 :
356 {
357 // renormalisation par rapport a la valeur de l'energie "spectrale" 3D
358 calcul_spectre_3D(vitesse, "init", Ec);
359 if(je_suis_maitre())
360 Cerr << "Ec (espace spectral 3D) = " << Ec << finl;
361 break;
362 }
363 default :
364 {
365 {
366 Cerr << "Traitement_particulier_NS_THI_VEF::renorm_Ec" << finl;
367 Cerr << "Impossible de trouver la methode demandee pour initialiser l'energie cinetique : fac_init = " << fac_init << finl;
368 assert( 0 );
370 throw;
371 }
372 }
373 }
374
375 double nEc=pow(Ec/Ec_init,0.5);
376 if(je_suis_maitre())
377 Cerr << "Renormalisation pour Ec_init = " << Ec_init << finl;
378 vitesse/=nEc;
379
380}
381
382
383
384
385
386
388{
389 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
390 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
391 const int nb_faces = domaine_VEF.nb_faces();
392 const DoubleTab& vitesse = mon_equation->inconnue().valeurs(); // vitesse aux faces
393 // const Champ_P1NC& champ_vitesse = ref_cast(Champ_P1NC,mon_equation->inconnue());
394 Champ_P1NC& champ_vitesse = ref_cast(Champ_P1NC,mon_equation->inconnue());
395
396
397 DoubleTab vitesse_bar(vitesse);
398 champ_vitesse.filtrer_L2(vitesse_bar);
399
400 DoubleTab vitesse_prm(nb_faces, dimension);
401 for (int num_face=0; num_face<nb_faces; num_face++)
402 {
403 for (int dim=0; dim<dimension; dim++)
404 {
405 vitesse_prm(num_face, dim) = vitesse(num_face, dim) - vitesse_bar(num_face, dim);
406 }
407 }
408
409 Champ_P1NC champ_vitesse_bar(champ_vitesse);
410 champ_vitesse_bar.valeurs().ref(vitesse_bar);
411 Champ_P1NC champ_vitesse_prm(champ_vitesse);
412 champ_vitesse_prm.valeurs().ref(vitesse_prm);
413
414
415
416 double temps = mon_equation->inconnue().temps();
417
418 if(je_suis_maitre())
419 Cerr << finl << "temps = " << temps << finl << finl;
420 temps /= temps_retournement;
421 if(je_suis_maitre())
422 Cerr << finl << "temps (adimensionne) = " << temps << finl << finl;
423
424 calcul_vitesse_moyenne(vitesse, moyenne_vitesse);
425
426
427 // on traite les champs scalaires
428 for (int i=0; i<nb_champs_scalaires; i++)
429 {
430 calcul_moyenne(mon_equation->probleme().get_champ(noms_champs_scalaires[i]).valeurs(), moyennes_scal(i));
431 }
432
434
435 double Ec;
436
437 if (calc_sp_3D && nproc()==1)
438 {
439 calcul_spectre_3D(vitesse, "tot", Ec);
440 calcul_spectre_3D(vitesse_bar, "bar", Ec);
441 calcul_spectre_3D(vitesse_prm, "prm", Ec);
442
443 // on traite les champs scalaires
444 for (int i=0; i<nb_champs_scalaires; i++)
445 {
446 const DoubleTab& scal = mon_equation->probleme().get_champ(noms_champs_scalaires[i]).valeurs();
447 DoubleTab temp;
448 temp.resize(vitesse.dimension(0),dimension);
449 for (int j=0; j<temp.dimension(0); j++)
450 {
451 for (int d=0; d<dimension; d++)
452 temp(j,d) = scal(j);
453 }
454 calcul_spectre_3D(temp, noms_champs_scalaires[i]+"_tot", Ec);
455 }
456
457 if(je_suis_maitre())
458 Cerr << finl;
459 }
460
461
462
463 if (calc_sp_1D && nproc()==1)
464 {
465 calcul_spectre_1D(vitesse, "tot", Ec);
466 calcul_spectre_1D(vitesse_bar, "bar", Ec);
467 calcul_spectre_1D(vitesse_prm, "prm", Ec);
468
469 // Pas de spectres 1d pour les scalaires
470 }
471
472
473}
474
475
476
477
479{
480 // Pour les traitements effectues a chaque pas de temps
481
482 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
483 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
484 const int nb_faces = domaine_VEF.nb_faces();
485 const DoubleTab& vitesse = mon_equation->inconnue().valeurs(); // vitesse aux faces
486 const Champ_P1NC& champ_vitesse = ref_cast(Champ_P1NC,mon_equation->inconnue());
487 double temps = mon_equation->inconnue().temps();
488
489
490 DoubleTab vitesse_bar(vitesse);
491 champ_vitesse.filtrer_L2(vitesse_bar);
492
493 DoubleTab vitesse_prm(nb_faces, dimension);
494 for (int num_face=0; num_face<nb_faces; num_face++)
495 {
496 for (int dim=0; dim<dimension; dim++)
497 {
498 vitesse_prm(num_face, dim) = vitesse(num_face, dim) - vitesse_bar(num_face, dim);
499 }
500 }
501
502 double Ec_tot;
503 Ec_tot = calcul_Ec_spatial(vitesse, "tot");
504 if (je_suis_maitre() && cle_premier_pas_dt)
505 {
506 Nom fichier = Nom("Sorties_diff_tot");
507 SFichier fic (fichier,ios::app);
508 Nom fichier_eps = Nom("Sorties_epsilon_-2_3");
509 SFichier fic_eps (fichier_eps,ios::app);
510 Nom fichier_eps_ret = Nom("Sorties_epsilon_-2_3_ret");
511 SFichier fic_eps_ret (fichier_eps_ret,ios::app);
512 fic.precision(8);
513 double epsilon = (Ec_tot_old - Ec_tot) / (temps - temps_old);
514 fic << temps_old << " " << epsilon << finl;
515 double temps_old_ret = temps_old/temps_retournement;
516 if ( epsilon > 1.e-12 )
517 {
518 fic_eps << temps_old << " " << pow(epsilon,-2./3.) << finl;
519 fic_eps_ret << temps_old_ret << " " << pow(epsilon,-2./3.) << finl;
520 }
521 else
522 {
523 fic_eps << temps_old << " " << (int)0 << finl;
524 fic_eps_ret << temps_old_ret << " " << (int)0 << finl;
525 }
526
527 }
528 Ec_tot_old = Ec_tot;
529 temps_old = temps;
530
531 calcul_Ec_spatial(vitesse_bar, "bar");
532 calcul_Ec_spatial(vitesse_prm, "prm");
533
534 if(je_suis_maitre())
535 Cerr << finl << "temps = " << temps << finl << finl;
536 temps /= temps_retournement;
537 if(je_suis_maitre())
538 Cerr << finl << "temps (adimensionne) = " << temps << finl << finl;
539
540 double Df;
542
543 DoubleTab Sk(dimension);
544 calcul_Sk(Sk);
545
546 calcul_nu_t();
547
548 if ( calc_correlations==1 ) calcul_correlations(vitesse);
549
550
551 // Les scalaires :
552 // Pour les traitements effectues a chaque pas de temps
553
554 for (int iscal=0; iscal<nb_champs_scalaires; iscal++)
555 {
556 const DoubleTab& scal = mon_equation->probleme().get_champ(noms_champs_scalaires[iscal]).valeurs();
557 DoubleTab temp;
558 temp.resize(scal.dimension(0),1);
559 for (int j=0; j<temp.dimension(0); j++)
560 temp(j,0) = scal(j);
561 calcul_Ec_spatial(temp, noms_champs_scalaires[iscal]+"_tot");
562 }
563
564
565
566}
567
568
569
570
571void Traitement_particulier_NS_THI_VEF::determine_tab_fft_VEF_3D(IntTab& tab_domaine, DoubleTab& coord_domaine, IntVect& nb_coord_domaine, int& nb_spectres, int& nb_points)
572// Remplit le tableau tab_calc_fft_3D contenant les centres de faces
573// reparties sur tout le domaine, ordonnes pour le calcul de spectre par FFT.
574// On ne peut pas utiliser tous les points pour un seul spectre (ils ne
575// forment pas un maillage cartesien, generalement), mais on peut calculer
576// plusieurs spectres (moins bons a priori qu'un spectre unique) a partir de
577// plusieurs sous-ensembles de points et en faire la moyenne.
578// A faire tourner une fois au debut, et a chaque fois que le domaine change.
579
580// Preconditions : le domaine s'etend de 0 a 2*Pi dans chaque direction
581
582// Sorties : int nb_points; nombre de points dans une direction pour chaque sous-ensemble de points
583// int nb_spectres; nombre de sous-ensemble de points
584
585// Effet de bord : remplit le tableau tab_calc_fft_3D
586
587{
588 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
589 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
590 const int nb_faces = domaine_VEF.nb_faces();
591 const DoubleTab& coord_centre = domaine_VEF.xv();
592 const double epsilon = 1.e-8;
593
594
595
596 if(je_suis_maitre())
597 {
598 Cerr << "Preparation pour le calcul en FFT." << finl;
599 Cerr << " (table de correspondance : coordonnees de centre de la face / index de face). " ;
600 }
601
602
603
604
605 int nb_coord_domaine_max = 0;
606
607 // recuperer les differentes coordonnees trouvees dans le domaine
608 for (int dim=0; dim<dimension; dim++)
609 {
610
611 for (int num_face=0; num_face<nb_faces; num_face++)
612 {
613 double coord = coord_centre(num_face,dim);
614 int trouve_coord = 0; // booleen
615
616 for (int jj=0; jj<nb_coord_domaine(dim); jj++)
617 {
618 if (std::fabs(coord - coord_domaine(jj,dim)) < epsilon)
619 {
620 // cette valeur de "coord" a deja ete trouvee dans le domaine
621 trouve_coord = 1;
622 }
623 }
624
625 if ( !trouve_coord )
626 {
627 // ajouter dans le tableau coord_domaine
628 int jj=nb_coord_domaine(dim)-1;
629
630 while ( (jj > -1) && (coord_domaine(jj,dim) > coord) )
631 {
632 // decalage vers la droite des valeurs plus grandes
633 coord_domaine(jj+1,dim) = coord_domaine(jj,dim);
634 jj--;
635 }
636
637 // insertion a la position voulue
638 coord_domaine(jj+1,dim) = coord;
639 nb_coord_domaine(dim)++;
640
641 } // endif ( !trouve_coord )
642
643 } // fin boucle sur les faces
644
645 if ( nb_coord_domaine(dim) > nb_coord_domaine_max )
646 {
647 nb_coord_domaine_max = nb_coord_domaine(dim) ;
648 }
649
650 } // fin boucle sur dim
651
652 coord_domaine.resize(nb_coord_domaine_max,dimension);
653
654
655 // remplir un tableau pour toutes les faces du domaine ordonnes selon leurs coordonnees, avec des vides a -1
656 tab_domaine.resize(nb_coord_domaine(0),nb_coord_domaine(1),nb_coord_domaine(2));
657 tab_domaine = -1;
658 IntVect index(3);
659 for (int num_face=0; num_face<nb_faces; num_face++)
660 {
661 index = -1;
662 for (int dim=0; dim<dimension; dim++)
663 {
664 for (int ii=0; ii<nb_coord_domaine(dim); ii++)
665 {
666 if ( std::fabs(coord_centre(num_face,dim) - coord_domaine(ii,dim)) < epsilon )
667 {
668 index(dim) = ii;
669 break ;
670 }
671 }
672 }
673
674 tab_domaine(index(0),index(1),index(2)) = num_face;
675 }
676
677 if(je_suis_maitre())
678 {
679 Cerr << "OK." << finl;
680
681 Cerr << "Remplissage de la table pour le calcul en FFT, spectres 3D." << finl;
682 Cerr << " (faces ordonnees en grilles cartesiennes, selon les coordonnees de leur centre). " ;
683 }
684
685
686
687 // rechercher dans chaque direction l'ecart minimum, et l'ecart minimum global
688 DoubleVect ecart_min_dir(dimension); // ecart minimum dans chaque direction
689 ecart_min_dir = 100;
690 double ecart_min = 100; // ecart minimum global
691
692 for (int dim=0; dim<dimension; dim++)
693 {
694 for (int ii=0; ii<nb_coord_domaine(dim)-1; ii++)
695 {
696 double ecart = coord_domaine(ii+1,dim) - coord_domaine(ii,dim);
697 if ( ecart < ecart_min_dir(dim) )
698 {
699 ecart_min_dir(dim) = ecart ;
700 }
701 }
702 if ( ecart_min_dir(dim) < ecart_min )
703 {
704 ecart_min = ecart_min_dir(dim) ;
705 }
706 }
707
708 IntVect ecart_min_dir_int(3);
709
710 for (int dim=0; dim<dimension; dim++)
711 {
712 ecart_min_dir_int(dim) = (int)( ecart_min_dir(dim) / ecart_min + 0.5 );
713 }
714 // on a besoin du plus petit commun multiple des 3 ints pour avoir une chance de construire une grille cartesienne
715 int ecart_base_int = ppcm(ecart_min_dir_int(0),
716 ppcm(ecart_min_dir_int(1),
717 ecart_min_dir_int(2)));
718
719
720 double pas_base = ecart_base_int * ecart_min;
721 double pas = pas_base;
722
723
724
725 IntVect hexa(nb_faces); // correspondance indice des faces dans domaine - dans hexa
726 IntTab rempli(3);
727 int fini = 0; // booleen
728 nb_spectres = 0; // nombre de spectres qui vont etre calcules et donc nombre de sous-ensembles de points qui sont ici releves
729 int num_spectre = 0;
730
731 while ( !fini && ( pas < L_BOITE/2. ) )
732 {
733 // prendre un hexa-reference, de cote "pas", a l'origine
734 int nb_dans_hexa = 0;
735 for (int num_face=0; num_face<nb_faces; num_face++)
736 {
737 int dans_hexa = 0;
738 for (int dim=0; dim<dimension; dim++)
739 {
740 if ( coord_centre(num_face,dim) + epsilon < pas )
741 {
742 dans_hexa++ ;
743 }
744 }
745 if ( dans_hexa == dimension )
746 {
747 hexa(nb_dans_hexa) = num_face;
748 nb_dans_hexa++;
749 }
750 }
751
752 nb_points = (int)(L_BOITE/pas + 0.5);
753
754 tab_calc_fft_3D.resize(nb_dans_hexa, nb_points+1,nb_points+1,nb_points+1); // tableau avec les centres des faces ordonnees pour le calcul de spectre par FFT
755 tab_calc_fft_3D = -1;
756
757 IntTab coord_domaine_ok(nb_coord_domaine_max, dimension);
758
759 // parcourir les faces contenues dans l'hexa-reference et tenter de construire des grilles cartesiennes
760 for (int num_face=0; num_face<nb_dans_hexa; num_face++)
761 {
762 // chercher les coordonnees qui vont bien avec la face de l'hexa-reference pour construire une grille cartesienne avec le pas, en evitant les dernieres coordonnees, qui sont sur des faces periodiques
763
764 coord_domaine_ok = 0;
765
766 for (int dim=0; dim<dimension; dim++)
767 {
768 for (int ii=0; ii<nb_coord_domaine(dim)-1; ii++)
769 {
770 double ratio_double =
771 ( coord_domaine(ii,dim)-coord_centre(hexa(num_face),dim) ) / pas;
772 int ratio_int = (int)(ratio_double + 0.5);
773 if ( std::fabs(ratio_double - ratio_int) < epsilon )
774 {
775 coord_domaine_ok(ii,dim) = 1;
776 }
777 }
778
779 } // endfor coordonnees qui vont bien
780
781 int valide = 1; // booleen
782
783 // prendre les faces qui ont les 3 coordonnees qui vont bien pour construire la grille, en evitant les dernieres coordonnees, qui sont sur des faces periodiques (ainsi chaque grille de tab_calc_fft_3D est de taille nb_points*nb_points*nb_points exactement)
784 // (et non pas nb_points*nb_points*nb_points pour une grille et nb_points+1*nb_points*nb_points pour une autre grille, et pour d'autres grilles nb_points*nb_points+1*nb_points ou nb_points+1*nb_points+1*nb_points ou ... )
785
786 int ix = 0;
787 for (int ii=0; ii<nb_coord_domaine(0)-1; ii++)
788 {
789 rempli(0) = 0;
790 int iy = 0;
791 for (int jj=0; jj<nb_coord_domaine(1)-1; jj++)
792 {
793 rempli(1) = 0;
794 int iz = 0;
795 for (int kk=0; kk<nb_coord_domaine(2)-1; kk++)
796 {
797 rempli(2) = 0;
798
799 if ( coord_domaine_ok(ii,0) == 1
800 && coord_domaine_ok(jj,1) == 1
801 && coord_domaine_ok(kk,2) == 1 )
802 {
803 // a cette position devrait se trouver une face
804 if ( tab_domaine(ii,jj,kk) != -1 )
805 // la face "tab_domaine(ii,jj,kk)" existe et est sur la grille qui s'appuie sur la face "hexa(num_face)" contenue dans l'hexa-reference.
806 {
807 tab_calc_fft_3D(num_spectre,ix,iy,iz) = tab_domaine(ii,jj,kk);
808 rempli = 1;
809 }
810 else
811 // on ne trouve pas de face a la position requise : la grille en construction n'est pas valide
812 {
813 valide = 0;
814 break;
815 }
816
817 } // endif bonnes coordonnees
818
819 if ( !valide ) break ;
820 if ( rempli(2) ) iz++;
821
822 } // endfor kk
823
824 if ( !valide ) break ;
825 if ( rempli(1) ) iy++;
826
827 } // endfor jj
828
829 if ( !valide ) break ;
830 if ( rempli(0) ) ix++;
831
832 } // endfor ii
833
834 if ( valide )
835 {
836 // on a reussi a construire une grille complete
837 assert( ix == nb_points );
838
839 // On passe de nb_points a nb_points+1 dans chaque direction, en creant par periodicite les points de coordonees superieure a 2*Pi (il est necessaire, pour le bon fonctionnement des routines de FFT utilisees, d'avoir le premier et le dernier point a la meme valeur).
840
841 for (int jj=0; jj<nb_points; jj++)
842 for (int kk=0; kk<nb_points; kk++)
843 {
844 tab_calc_fft_3D(num_spectre, nb_points, jj, kk) =
845 tab_calc_fft_3D(num_spectre, 0 , jj, kk);
846 }
847
848 for (int ii=0; ii<nb_points+1; ii++)
849 for (int kk=0; kk<nb_points; kk++)
850 {
851 tab_calc_fft_3D(num_spectre, ii, nb_points, kk) =
852 tab_calc_fft_3D(num_spectre, ii, 0 , kk);
853 }
854
855 for (int ii=0; ii<nb_points+1; ii++)
856 for (int jj=0; jj<nb_points+1; jj++)
857 {
858 tab_calc_fft_3D(num_spectre, ii, jj, nb_points) =
859 tab_calc_fft_3D(num_spectre, ii, jj, 0 );
860 }
861
862 num_spectre++;
863 }
864
865 } // endfor essai de toutes les faces de l'hexa-reference
866
867 if ( num_spectre )
868 {
869 // on a au moins une grille valable
870 nb_spectres = num_spectre;
871 fini = 1;
872 }
873 else
874 {
875 pas += pas_base; // et on essaie avec un autre pas plus grand et un nouvel hexa-reference
876 }
877
878 } // endwhile
879
880 if(je_suis_maitre())
881 if ( !nb_spectres )
882 {
883 Cerr << finl << "Erreur dans Traitement_particulier_NS_THI_VEF::determine_tab_fft_VEF_3D" << finl;
884 Cerr << "La fonction n'est pas capable de trouver une ou des grilles cartesiennes 3D" << finl;
885 Cerr << "pour le calcul de spectres en FFT." << finl;
886 assert(0);
888 }
889
890
891
892
893
894
895 if(je_suis_maitre())
896 {
897
898 Cerr << "OK." << finl;
899
900 Cerr << nb_spectres << " grilles de " << nb_points << " points par cote seront utilisees pour calculer les spectres 3D." << finl << finl;
901
902 }
903
904
905
906}
907
908
909void Traitement_particulier_NS_THI_VEF::determine_tab_fft_VEF_1D(const IntTab& tab_domaine, const DoubleTab& coord_domaine, const IntVect& nb_coord_domaine, IntVect& nb_spectres, IntVect& nb_points)
910
911// limitation : en cherchant les lignes les plus longues pour porter les spectres,
912// la methode ne verifie pas si les points sont regulierement espaces
913// (ce qui est necessaire pour une FFT mais pas pour une DFT).
914
915
916{
917
918 if(je_suis_maitre())
919 {
920 Cerr << "Remplissage de la table pour le calcul en FFT, spectres 1D." << finl;
921 Cerr << " (faces ordonnees en lignes droites, selon les coordonnees de leur centre). " ;
922 }
923
924
925 IntVect nb_coord_domaine_tri(nb_coord_domaine) ;
926 // tri
927 for (int ii=dimension ; ii>0; ii--)
928 {
929 for (int jj=1; jj<ii; jj++)
930 {
931 if ( nb_coord_domaine_tri(jj-1) > nb_coord_domaine_tri(jj) )
932 {
933 int temp = nb_coord_domaine_tri(jj-1);
934 nb_coord_domaine_tri(jj-1) = nb_coord_domaine_tri(jj);
935 nb_coord_domaine_tri(jj) = temp;
936 }
937 }
938 }
939
940
941 int nb_coord_domaine_max = nb_coord_domaine_tri(2) ;
942 int nb_spectres_max = nb_coord_domaine_tri(2) * nb_coord_domaine_tri(1) ;
943
944
945 tab_calc_fft_1D.resize(dimension, nb_spectres_max, nb_coord_domaine_max) ;
946 tab_calc_fft_1D = -1 ;
947
948 tab_coord_1D.resize(dimension, nb_spectres_max, nb_coord_domaine_max) ;
949
950 IntVect num_spectre(dimension);
951 nb_spectres.resize(dimension);
952 nb_points.resize(dimension);
953 nb_spectres = 0 ;
954 num_spectre = 0 ;
955 nb_points = 0 ;
956
957 // pour chaque point, on cherche les points sur la meme ligne selon x
958 for (int jj=0; jj<nb_coord_domaine(1)-1; jj++)
959 for (int kk=0; kk<nb_coord_domaine(2)-1; kk++)
960 {
961 int ix = 0 ;
962 for (int ii=0; ii<nb_coord_domaine(0)-1; ii++)
963 {
964 int num_face = tab_domaine(ii, jj, kk);
965 if ( num_face != -1 )
966 {
967 tab_calc_fft_1D(0, num_spectre(0), ix) = num_face;
968 tab_coord_1D (0, num_spectre(0), ix) = coord_domaine(ii, 0);
969 ix++;
970 }
971 }
972 if ( ix == nb_points(0) )
973 {
974 num_spectre(0)++;
975 }
976 else if ( ix > nb_points(0) )
977 {
978 // on ne garde que les lignes les plus longues
979 nb_points(0) = ix ;
980 for (int index=0; index<ix; index++)
981 {
982 tab_calc_fft_1D(0, 0 , index) =
983 tab_calc_fft_1D(0, num_spectre(0), index) ;
984 tab_coord_1D (0, 0 , index) =
985 tab_coord_1D (0, num_spectre(0), index) ;
986 }
987 num_spectre(0) = 1 ;
988 }
989 nb_spectres(0) = num_spectre(0);
990 }
991
992 // pour chaque point, on cherche les points sur la meme ligne selon y
993 for (int ii=0; ii<nb_coord_domaine(0)-1; ii++)
994 for (int kk=0; kk<nb_coord_domaine(2)-1; kk++)
995 {
996 int iy = 0 ;
997 for (int jj=0; jj<nb_coord_domaine(1)-1; jj++)
998 {
999 int num_face = tab_domaine(ii, jj, kk);
1000 if ( num_face != -1 )
1001 {
1002 tab_calc_fft_1D(1, num_spectre(1), iy) = num_face;
1003 tab_coord_1D (1, num_spectre(1), iy) = coord_domaine(jj, 1);
1004 iy++;
1005 }
1006 }
1007 if ( iy == nb_points(1) )
1008 {
1009 num_spectre(1)++;
1010 }
1011 else if ( iy > nb_points(1) )
1012 {
1013 // on ne garde que les lignes les plus longues
1014 nb_points(1) = iy ;
1015 for (int index=0; index<iy; index++)
1016 {
1017 tab_calc_fft_1D(1, 0 , index) =
1018 tab_calc_fft_1D(1, num_spectre(1), index) ;
1019 tab_coord_1D (1, 0 , index) =
1020 tab_coord_1D (1, num_spectre(1), index) ;
1021 }
1022 num_spectre(1) = 1 ;
1023 }
1024 nb_spectres(1) = num_spectre(1);
1025 }
1026
1027 // pour chaque point, on cherche les points sur la meme ligne selon z
1028 for (int jj=0; jj<nb_coord_domaine(1)-1; jj++)
1029 for (int ii=0; ii<nb_coord_domaine(0)-1; ii++)
1030 {
1031 int iz = 0 ;
1032 for (int kk=0; kk<nb_coord_domaine(2)-1; kk++)
1033 {
1034 int num_face = tab_domaine(ii, jj, kk);
1035 if ( num_face != -1 )
1036 {
1037 tab_calc_fft_1D(2, num_spectre(2), iz) = num_face;
1038 tab_coord_1D (2, num_spectre(2), iz) = coord_domaine(kk, 2);
1039 iz++;
1040 }
1041 }
1042 if ( iz == nb_points(2) )
1043 {
1044 num_spectre(2)++;
1045 }
1046 else if ( iz > nb_points(2) )
1047 {
1048 // on ne garde que les lignes les plus longues
1049 nb_points(2) = iz ;
1050 for (int index=0; index<iz; index++)
1051 {
1052 tab_calc_fft_1D(2, 0 , index) =
1053 tab_calc_fft_1D(2, num_spectre(2), index) ;
1054 tab_coord_1D (2, 0 , index) =
1055 tab_coord_1D (2, num_spectre(2), index) ;
1056 }
1057 num_spectre(2) = 1 ;
1058 }
1059 nb_spectres(2) = num_spectre(2);
1060 }
1061
1062 if(je_suis_maitre())
1063 {
1064 Cerr << "OK." << finl;
1065
1066 Cerr << "Seront utilisees pour calculer les spectres 1D :" << finl;
1067 Cerr << "selon x, " << nb_spectres(0) << " lignes de " << nb_points(0) << " points," << finl;
1068 Cerr << "selon y, " << nb_spectres(1) << " lignes de " << nb_points(1) << " points," << finl;
1069 Cerr << "selon z, " << nb_spectres(2) << " lignes de " << nb_points(2) << " points." << finl << finl;
1070
1071
1072 }
1073
1074}
1075
1076
1077
1078
1079
1080void Traitement_particulier_NS_THI_VEF::ch_pour_fft_VEF_3D(const DoubleTab& tab_global, DoubleTab& tab_u, DoubleTab& tab_v, DoubleTab& tab_w, int num_spectre) const
1081// Remplit les tableaux (tab_u, tab_v et tab_w) avec les valeurs a envoyer
1082// dans les routines FFT, en utilisant les valeurs du tableau tab_global
1083// et en tenant compte du tableau de relation tab_calc_fft_3D.
1084// A faire tourner a chaque calcul de spectre 3D.
1085{
1086 // Cerr << "Remplissage des tableaux de vitesse (calcul en FFT). " ;
1087
1088 // Remplissage des tableaux
1089 for (int ii=0; ii<nb_points_3D+1; ii++)
1090 for (int jj=0; jj<nb_points_3D+1; jj++)
1091 for (int kk=0; kk<nb_points_3D+1; kk++)
1092 {
1093 int num_face = tab_calc_fft_3D(num_spectre, ii, jj, kk);
1094 tab_u(ii, jj, kk) = tab_global(num_face, 0);
1095 tab_v(ii, jj, kk) = tab_global(num_face, 1);
1096 tab_w(ii, jj, kk) = tab_global(num_face, 2);
1097 }
1098
1099}
1100
1101
1102
1103
1104
1105
1106void Traitement_particulier_NS_THI_VEF::ch_pour_fft_VEF_1D(const DoubleTab& tab_global, DoubleVect& vect_u, DoubleVect& vect_v, DoubleVect& vect_w, int dir, int num_spectre ) const
1107// Remplit les vecteurs (vect_u, vect_v et vect_w) avec les valeurs a envoyer
1108// dans les routines FFT, en utilisant les valeurs du tableau tab_domaine
1109// et en tenant compte du tableau de relation tab_calc_fft_1D.
1110// A faire tourner a chaque calcul de spectre 1D.
1111{
1112 // Remplissage des vecteurs
1113 for (int ii=0; ii<nb_points_1D(dir); ii++)
1114 {
1115 int num_face = tab_calc_fft_1D(dir, num_spectre, ii);
1116 vect_u(ii) = tab_global( num_face, 0 );
1117 vect_v(ii) = tab_global( num_face, 1 );
1118 vect_w(ii) = tab_global( num_face, 2 );
1119 }
1120
1121}
1122
1123
1124
1125void Traitement_particulier_NS_THI_VEF::calcul_spectre_3D(const DoubleTab& vitesse, Nom ext, double& Ec_spectre)
1126{
1127 double temps = mon_equation->inconnue().temps();
1128 temps /= temps_retournement;
1129
1130 // Cerr << "Spectre d'energie en 3D." << finl; ;
1131
1132 DoubleVect Ec(nb_points_3D); // energie par bande spectrale
1133 DoubleVect Ec_min(nb_points_3D);
1134 DoubleVect Ec_max(nb_points_3D);
1135 DoubleVect Ec_moy(nb_points_3D);
1136 Ec_min = 1.e+20;
1137 Ec_max = 0;
1138 Nom fichier = Nom("spectre_3D_") + ext + Nom("_") + Nom(temps);
1139 Nom fichier_k = Nom("spectre_k_3D_") + ext + Nom("_") + Nom(temps);
1140
1141 for (int num_spectre=0; num_spectre<nb_spectres_3D; num_spectre++)
1142 {
1143 // Cerr << "spectre #" << num_spectre+1 << "/" << nb_spectres_3D << finl;
1144
1145 DoubleTab vit_u(nb_points_3D+1,nb_points_3D+1,nb_points_3D+1),
1146 vit_v(nb_points_3D+1,nb_points_3D+1,nb_points_3D+1),
1147 vit_w(nb_points_3D+1,nb_points_3D+1,nb_points_3D+1);
1148 // tableaux de vitesse a envoyer dans les routines FFT 3D
1149
1150 ch_pour_fft_VEF_3D(vitesse, vit_u, vit_v, vit_w, num_spectre);
1151
1152 calc_sp_operateur(vit_u, vit_v, vit_w, nb_points_3D, temps, 0,0, Ec);
1153
1154 for (int ii=0; ii<nb_points_3D; ii++)
1155 {
1156 if ( Ec(ii) < Ec_min(ii) )
1157 {
1158 Ec_min(ii) = Ec(ii);
1159 }
1160 if ( Ec(ii) > Ec_max(ii) )
1161 {
1162 Ec_max(ii) = Ec(ii);
1163 }
1164 Ec_moy(ii) += Ec(ii)/nb_spectres_3D;
1165 }
1166 }
1167
1168 int kc = nb_points_3D/2 ; // nombre d'onde de coupure
1169
1170 // ecriture des spectres moy, max et min dans un fichier
1171 SFichier fic_spectre (fichier);
1172 SFichier fic_spectre_k (fichier_k);
1173 for (int ii=1; ii<kc; ii++)
1174 {
1175 fic_spectre << ii << " " << Ec_moy(ii-1) << " " << Ec_max(ii-1) << " " << Ec_min(ii-1) << finl;
1176 fic_spectre_k << ii << " " << Ec_moy(ii-1) * pow(ii,5./3.) << " " << Ec_max(ii-1) * pow(ii,5./3.) << " " << Ec_min(ii-1) * pow(ii,5./3.) << finl;
1177 }
1178
1179 // mise en evidence de la frequence de coupure
1180 fic_spectre << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1181 fic_spectre << kc << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1182 fic_spectre_k << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1183 fic_spectre_k << kc << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1184
1185 for (int ii=kc; ii<nb_points_3D+1; ii++)
1186 {
1187 fic_spectre << ii << " " << Ec_moy(ii-1) << " " << Ec_max(ii-1) << " " << Ec_min(ii-1) << finl;
1188 fic_spectre_k << ii << " " << Ec_moy(ii-1) * pow(ii,5./3.) << " " << Ec_max(ii-1) * pow(ii,5./3.) << " " << Ec_min(ii-1) * pow(ii,5./3.) << finl;
1189 }
1190
1191 // calcul de l'energie cinetique par integration sur le spectre jusqu a kc
1192 calc_Ec(Ec_moy, kc, Ec_spectre);
1193
1194 // calcul de l'enstrophie par integration sur le spectre jusqu a kc
1195 DoubleVect Df(nb_points_3D); // enstrophie par bande spectrale
1196 for (int ii=0; ii<nb_points_3D; ii++)
1197 {
1198 Df(ii) = (ii+1)*(ii+1)*Ec_moy(ii);
1199 }
1200 double Df_spectre;
1201 calc_Ec(Df, kc, Df_spectre);
1202
1203 // ecriture de l'energie (en spectral) dans un fichier
1204 Nom fichier_Ec_spectral = Nom("Sorties_Ec_") + ext + Nom("_spectral_3D") ;
1205 SFichier fic_Ec_spectral (fichier_Ec_spectral, ios::app);
1206 fic_Ec_spectral << temps << " " << Ec_spectre << finl;
1207
1208 // ecriture de l'enstrophie (en spectral) dans un fichier
1209 Nom fichier_Df_spectral = Nom("Sorties_Df_") + ext + Nom("_spectral_3D") ;
1210 SFichier fic_Df_spectral (fichier_Df_spectral, ios::app);
1211 fic_Df_spectral << temps << " " << Df_spectre << finl;
1212
1213
1214
1215}
1216
1217
1218
1219
1220
1221
1222
1223void Traitement_particulier_NS_THI_VEF::calcul_spectre_1D(const DoubleTab& vitesse, Nom ext, double& Ec_spectre)
1224{
1225
1226 double temps = mon_equation->inconnue().temps();
1227 temps /= temps_retournement;
1228 // Nom fichier_data = Nom("data_spectre_1D_") + ext + Nom("_") + Nom(temps) + Nom("_");
1229 Nom fichier_spectre = Nom("spectre_1D_") + ext + Nom("_") + Nom(temps) + Nom("_");
1230 Nom fichier_k_spectre = Nom("spectre_k_1D_") + ext + Nom("_") + Nom(temps) + Nom("_");
1231
1232 Ec_spectre = 0;
1233 double Df_spectre = 0;
1234
1235 //int nb_points_1D_max = local_max_vect(nb_points_1D);
1236
1237 /* DoubleVect Ec_moy(nb_points_1D_max),
1238 Ec_moy_u(nb_points_1D_max),
1239 Ec_moy_v(nb_points_1D_max),
1240 Ec_moy_w(nb_points_1D_max); */
1241
1242 for (int dir=0; dir<dimension; dir++)
1243 {
1244 Nom direction;
1245 switch(dir)
1246 {
1247 case 0:
1248 {
1249 direction = Nom("x");
1250 break;
1251 }
1252 case 1:
1253 {
1254 direction = Nom("y");
1255 break;
1256 }
1257 case 2:
1258 {
1259 direction = Nom("z");
1260 break;
1261 }
1262 }
1263 // Nom fichier_data_direction = fichier_data + direction + Nom("_");
1264 Nom fichier_spectre_direction = fichier_spectre + direction + Nom("_");
1265 Nom fichier_k_spectre_direction = fichier_k_spectre + direction + Nom("_");
1266
1267 // SFichier fic_data_direction (fichier_data_direction);
1268 // fic_data_direction << "# coordonnee selon la direction" << dim << " ; vit_u ; vit_v ; vit_w" << finl;
1269
1270
1271 //DoubleTab Ec_comp(nb_points_1D(dir), dimension); // energie par composante (u,v,w) par bande spectrale
1272 DoubleTab Ec_comp_min(nb_points_1D(dir), dimension);
1273 DoubleTab Ec_comp_max(nb_points_1D(dir), dimension);
1274 DoubleTab Ec_comp_moy(nb_points_1D(dir), dimension);
1275
1276 Ec_comp_min = 1.e+20;
1277 Ec_comp_max = 0;
1278
1279 int n = nb_points_1D(dir);
1280 DoubleVect trig(2*n);
1281 IntVect ifax(19);
1282
1283 // preparer JMFFT
1284 cftfax(n,ifax.addr(),trig.addr());
1285
1286 int lot=1;
1287 DoubleVect work(2*n*lot);
1288 int inc=1;
1289 int jump=inc*(n+2);
1290 int isign=-1; // -1 pour FFT, +1 pour FFT inverse
1291
1292 int kc = nb_points_1D(dir)/2 ; // nombre d'onde de coupure
1293
1294 for (int num_spectre=0; num_spectre<nb_spectres_1D(dir); num_spectre++)
1295 {
1296 // Cerr << "spectres #" << num_spectre+1 << "/" << nb_spectres_1D(dim) << " selon direction " << dim << finl;
1297
1298 DoubleVect vect_u(nb_points_1D(dir)+2),
1299 vect_v(nb_points_1D(dir)+2),
1300 vect_w(nb_points_1D(dir)+2);
1301 // vecteurs de vitesse a envoyer dans les routines FFT 1D
1302
1303 ch_pour_fft_VEF_1D(vitesse, vect_u, vect_v, vect_w, dir, num_spectre);
1304
1305
1306
1307 // calcul des spectres 1D
1308 // calcul du spectre de la composante u selon la direction (dir)
1309 rfftmlt(vect_u.addr(),work.addr(),trig.addr(),ifax.addr(),inc,jump,n,lot,isign);
1310 // maintenant vect_u contient le resultat de la FFT
1311
1312 for (int ii=0; ii<kc; ii++)
1313 {
1314 double Ec_temp = vect_u(2*ii)*vect_u(2*ii)+vect_u(2*ii+1)*vect_u(2*ii+1);
1315
1316 Ec_temp *= 4;
1317
1318 if ( Ec_temp < Ec_comp_min(ii,0) )
1319 {
1320 Ec_comp_min(ii,0) = Ec_temp;
1321 }
1322 if ( Ec_temp > Ec_comp_max(ii,0) )
1323 {
1324 Ec_comp_max(ii,0) = Ec_temp;
1325 }
1326 Ec_comp_moy(ii,0) += Ec_temp/nb_spectres_1D(dir);
1327 }
1328
1329 // calcul du spectre de la composante v selon la direction (dir)
1330 rfftmlt(vect_v.addr(),work.addr(),trig.addr(),ifax.addr(),inc,jump,n,lot,isign);
1331 // maintenant vect_v contient le resultat de la FFT
1332 for (int ii=0; ii<kc; ii++)
1333 {
1334 double Ec_temp = vect_v(2*ii)*vect_v(2*ii)+vect_v(2*ii+1)*vect_v(2*ii+1);
1335
1336 Ec_temp *= 4;
1337
1338 if ( Ec_temp < Ec_comp_min(ii,1) )
1339 {
1340 Ec_comp_min(ii,1) = Ec_temp;
1341 }
1342 if ( Ec_temp > Ec_comp_max(ii,1) )
1343 {
1344 Ec_comp_max(ii,1) = Ec_temp;
1345 }
1346 Ec_comp_moy(ii,1) += Ec_temp/nb_spectres_1D(dir);
1347 }
1348
1349 // calcul du spectre de la composante w selon la direction (dir)
1350 rfftmlt(vect_w.addr(),work.addr(),trig.addr(),ifax.addr(),inc,jump,n,lot,isign);
1351 // maintenant vect_w contient le resultat de la FFT
1352 for (int ii=0; ii<kc; ii++)
1353 {
1354 double Ec_temp = vect_w(2*ii)*vect_w(2*ii)+vect_w(2*ii+1)*vect_w(2*ii+1);
1355
1356 Ec_temp *= 4;
1357
1358 if ( Ec_temp < Ec_comp_min(ii,2) )
1359 {
1360 Ec_comp_min(ii,2) = Ec_temp;
1361 }
1362 if ( Ec_temp > Ec_comp_max(ii,2) )
1363 {
1364 Ec_comp_max(ii,2) = Ec_temp;
1365 }
1366 Ec_comp_moy(ii,2) += Ec_temp/nb_spectres_1D(dir);
1367 }
1368
1369 }
1370
1371
1372
1373 // ecriture des spectres moy, max et min dans 1 direction dans un fichier
1374 SFichier fic_spectre_u (fichier_spectre_direction + Nom("u") );
1375 SFichier fic_spectre_k_u (fichier_k_spectre_direction + Nom("u") );
1376 SFichier fic_spectre_v (fichier_spectre_direction + Nom("v") );
1377 SFichier fic_spectre_k_v (fichier_k_spectre_direction + Nom("v") );
1378 SFichier fic_spectre_w (fichier_spectre_direction + Nom("w") );
1379 SFichier fic_spectre_k_w (fichier_k_spectre_direction + Nom("w") );
1380 SFichier fic_spectre_e (fichier_spectre_direction + Nom("e") );
1381 SFichier fic_spectre_k_e (fichier_k_spectre_direction + Nom("e") );
1382
1383 DoubleVect Ec_comp_moy_e(nb_points_1D(dir));
1384
1385 for (int ii=1; ii<kc; ii++)
1386 {
1387 Ec_comp_moy_e(ii) = Ec_comp_moy(ii,0) + Ec_comp_moy(ii,1) + Ec_comp_moy(ii,2);
1388
1389 fic_spectre_u << ii << " " << Ec_comp_moy(ii,0) << " " << Ec_comp_max(ii,0) << " " << Ec_comp_min(ii,0) << finl;
1390 fic_spectre_k_u << ii << " " << Ec_comp_moy(ii,0) * pow(ii,5./3.) << " " << Ec_comp_max(ii,0) * pow(ii,5./3.) << " " << Ec_comp_min(ii,0) * pow(ii,5./3.) << finl;
1391 fic_spectre_v << ii << " " << Ec_comp_moy(ii,1) << " " << Ec_comp_max(ii,1) << " " << Ec_comp_min(ii,1) << finl;
1392 fic_spectre_k_v << ii << " " << Ec_comp_moy(ii,1) * pow(ii,5./3.) << " " << Ec_comp_max(ii,1) * pow(ii,5./3.) << " " << Ec_comp_min(ii,1) * pow(ii,5./3.) << finl;
1393 fic_spectre_w << ii << " " << Ec_comp_moy(ii,2) << " " << Ec_comp_max(ii,2) << " " << Ec_comp_min(ii,2) << finl;
1394 fic_spectre_k_w << ii << " " << Ec_comp_moy(ii,2) * pow(ii,5./3.) << " " << Ec_comp_max(ii,2) * pow(ii,5./3.) << " " << Ec_comp_min(ii,2) * pow(ii,5./3.) << finl;
1395 fic_spectre_e << ii << " " << Ec_comp_moy_e(ii) << finl;
1396 fic_spectre_k_e << ii << " " << Ec_comp_moy_e(ii) * pow(ii,5./3.) << finl;
1397 }
1398
1399 // mise en evidence de la frequence de coupure
1400 fic_spectre_u << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1401 fic_spectre_k_u << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1402 fic_spectre_v << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1403 fic_spectre_k_v << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1404 fic_spectre_w << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1405 fic_spectre_k_w << kc-1 << " " << (int)0 << " " << (int)0 << " " << (int)0 << finl;
1406
1407
1408 // calcul de l'energie et l'enstrophie par integration sur le spectre jusqu a kc
1409 DoubleVect Ec_comp_moy_u(nb_points_1D(dir));
1410 DoubleVect Ec_comp_moy_v(nb_points_1D(dir));
1411 DoubleVect Ec_comp_moy_w(nb_points_1D(dir));
1412 DoubleVect Df_comp_moy_u(nb_points_1D(dir));
1413 DoubleVect Df_comp_moy_v(nb_points_1D(dir));
1414 DoubleVect Df_comp_moy_w(nb_points_1D(dir));
1415 for (int ii=0; ii<kc; ii++)
1416 {
1417 Ec_comp_moy_u(ii) = Ec_comp_moy(ii+1,0);
1418 Ec_comp_moy_v(ii) = Ec_comp_moy(ii+1,1);
1419 Ec_comp_moy_w(ii) = Ec_comp_moy(ii+1,2);
1420 Df_comp_moy_u(ii) = (ii+1)*(ii+1)*Ec_comp_moy(ii+1,0);
1421 Df_comp_moy_v(ii) = (ii+1)*(ii+1)*Ec_comp_moy(ii+1,1);
1422 Df_comp_moy_w(ii) = (ii+1)*(ii+1)*Ec_comp_moy(ii+1,2);
1423 }
1424 double Ec_spectre_u, Ec_spectre_v, Ec_spectre_w, Df_spectre_u, Df_spectre_v, Df_spectre_w;
1425 calc_Ec(Ec_comp_moy_u, kc, Ec_spectre_u);
1426 calc_Ec(Ec_comp_moy_v, kc, Ec_spectre_v);
1427 calc_Ec(Ec_comp_moy_w, kc, Ec_spectre_w);
1428 calc_Ec(Df_comp_moy_u, kc, Df_spectre_u);
1429 calc_Ec(Df_comp_moy_v, kc, Df_spectre_v);
1430 calc_Ec(Df_comp_moy_w, kc, Df_spectre_w);
1431 double Ec_spectre_e = Ec_spectre_u + Ec_spectre_v + Ec_spectre_w;
1432 double Df_spectre_e = Df_spectre_u + Df_spectre_v + Df_spectre_w;
1433
1434 // ecriture de l'energie (en spectral) dans un fichier
1435 Nom fichier_Ec_spectral_direction = Nom("Sorties_Ec_") + ext + Nom("_spectral_1D_") + direction ;
1436 SFichier fic_Ec_spectral_u (fichier_Ec_spectral_direction + Nom("_u"), ios::app );
1437 SFichier fic_Ec_spectral_v (fichier_Ec_spectral_direction + Nom("_v"), ios::app );
1438 SFichier fic_Ec_spectral_w (fichier_Ec_spectral_direction + Nom("_w"), ios::app );
1439 SFichier fic_Ec_spectral_e (fichier_Ec_spectral_direction + Nom("_e"), ios::app );
1440 fic_Ec_spectral_u << temps << " " << Ec_spectre_u << finl;
1441 fic_Ec_spectral_v << temps << " " << Ec_spectre_v << finl;
1442 fic_Ec_spectral_w << temps << " " << Ec_spectre_w << finl;
1443 fic_Ec_spectral_e << temps << " " << Ec_spectre_e << finl;
1444
1445 // ecriture de l'enstrophie (en spectral) dans un fichier
1446 Nom fichier_Df_spectral_direction = Nom("Sorties_Df_") + ext + Nom("_spectral_1D_") + direction ;
1447 SFichier fic_Df_spectral_u (fichier_Df_spectral_direction + Nom("_u"), ios::app );
1448 SFichier fic_Df_spectral_v (fichier_Df_spectral_direction + Nom("_v"), ios::app );
1449 SFichier fic_Df_spectral_w (fichier_Df_spectral_direction + Nom("_w"), ios::app );
1450 SFichier fic_Df_spectral_e (fichier_Df_spectral_direction + Nom("_e"), ios::app );
1451 fic_Df_spectral_u << temps << " " << Df_spectre_u << finl;
1452 fic_Df_spectral_v << temps << " " << Df_spectre_v << finl;
1453 fic_Df_spectral_w << temps << " " << Df_spectre_w << finl;
1454 fic_Df_spectral_e << temps << " " << Df_spectre_e << finl;
1455
1456
1457 Ec_spectre += Ec_spectre_e ;
1458 Df_spectre += Df_spectre_e ;
1459
1460 }
1461
1462
1463 // Cerr << "Spectre d'energie en 1D. Fin des calculs" << finl; ;
1464
1465 Nom fichier_Ec_spectral = Nom("Sorties_Ec_") + ext + Nom("_spectral_1D") ;
1466 SFichier fic_Ec_spectral (fichier_Ec_spectral, ios::app );
1467 fic_Ec_spectral << temps << " " << Ec_spectre << finl;
1468
1469 Nom fichier_Df_spectral = Nom("Sorties_Df_") + ext + Nom("_spectral_1D") ;
1470 SFichier fic_Df_spectral (fichier_Df_spectral, ios::app );
1471 fic_Df_spectral << temps << " " << Df_spectre << finl;
1472
1473 // Cerr << "Ec_" << ext << "_spectre_1D=" << Ec_spectre << " Df_" << ext << "_spectre_1D=" << Df_spectre << finl;
1474
1475}
1476
1477
1478
1479
1480
1482
1483{
1484 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
1485 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
1486 const int nb_faces = domaine_VEF.nb_faces();
1487 const Champ_P1NC& champ_vitesse = ref_cast(Champ_P1NC,mon_equation->inconnue());
1488
1489 DoubleTab vitesse_bar(vitesse);
1490 champ_vitesse.filtrer_L2(vitesse_bar);
1491
1492 DoubleTab vitesse_prm(nb_faces, dimension);
1493 for (int num_face=0; num_face<nb_faces; num_face++)
1494 {
1495 for (int dim=0; dim<dimension; dim++)
1496 {
1497 vitesse_prm(num_face, dim) = vitesse(num_face, dim) - vitesse_bar(num_face, dim);
1498 }
1499 }
1500
1501 if (nproc()==1)
1502 {
1503 isotropie(vitesse, "tot");
1504 isotropie(vitesse_bar, "bar");
1505 isotropie(vitesse_prm, "prm");
1506 }
1507}
1508
1509
1510
1511
1512void Traitement_particulier_NS_THI_VEF::isotropie(const DoubleTab& vitesse, Nom ext)
1513
1514{
1515 // Cerr << "Isotropie." << finl; ;
1516
1517 if (nproc()==1)
1518 {
1519 Nom fichier = "isotropie_";
1520 fichier += ext;
1521
1522 DoubleTab isotrop(6), isotrop_moy(6), isotrop_max(6), isotrop_min(6);
1523 isotrop_moy = 0 ;
1524 isotrop_max = 0 ;
1525 isotrop_min = 1e+20 ;
1526
1527 for (int num_spectre=0; num_spectre<nb_spectres_3D; num_spectre++)
1528 {
1529 // Cerr << "spectre #" << num_spectre+1 << "/" << nb_spectres_3D << finl;
1530
1531 // Etude de l'isotropie on calcule la moyenne de uu,vv,ww,uv,uw et vw
1532 isotrop = 0 ;
1533
1534 for(int ii=0; ii<nb_points_3D; ii++)
1535 for(int jj=0; jj<nb_points_3D; jj++)
1536 for(int kk=0; kk<nb_points_3D; kk++)
1537 {
1538 int num_face = tab_calc_fft_3D(num_spectre,ii,jj,kk);
1539 double u = vitesse(num_face,0) - moyenne_vitesse(0);
1540 double v = vitesse(num_face,1) - moyenne_vitesse(1);
1541 double w = vitesse(num_face,2) - moyenne_vitesse(2);
1542
1543 isotrop(0) += u * u ;
1544 isotrop(1) += v * v ;
1545 isotrop(2) += w * w ;
1546 isotrop(3) += u * v ;
1547 isotrop(4) += u * w ;
1548 isotrop(5) += v * w ;
1549 }
1550 int nb_points = nb_points_3D * nb_points_3D * nb_points_3D ;
1551 isotrop /= nb_points;
1552
1553 for (int ii=0; ii<6; ii++)
1554 {
1555 if ( isotrop(ii) < isotrop_min(ii) )
1556 {
1557 isotrop_min(ii) = isotrop(ii);
1558 }
1559 if ( isotrop(ii) > isotrop_max(ii) )
1560 {
1561 isotrop_max(ii) = isotrop(ii);
1562 }
1563 isotrop_moy(ii) += isotrop(ii)/nb_spectres_3D;
1564 }
1565 }
1566
1567 // ecriture des donnees moy, max et min dans un fichier
1568
1569 if (je_suis_maitre())
1570 {
1571 double temps = mon_equation->inconnue().temps();
1572 temps /= temps_retournement;
1573 Nom fichier_uu = fichier + Nom("_uu");
1574 SFichier fic_uu (fichier_uu, ios::app);
1575 fic_uu << temps << " " << isotrop_moy(0) << " " << isotrop_max(0) << " " << isotrop_min(0) << finl ;
1576
1577 Nom fichier_vv = fichier + Nom("_vv");
1578 SFichier fic_vv (fichier_vv, ios::app);
1579 fic_vv << temps << " " << isotrop_moy(1) << " " << isotrop_max(1) << " " << isotrop_min(1) << finl ;
1580
1581 Nom fichier_ww = fichier + Nom("_ww");
1582 SFichier fic_ww (fichier_ww, ios::app);
1583 fic_ww << temps << " " << isotrop_moy(2) << " " << isotrop_max(2) << " " << isotrop_min(2) << finl ;
1584
1585 Nom fichier_uv = fichier + Nom("_uv");
1586 SFichier fic_uv (fichier_uv, ios::app);
1587 fic_uv << temps << " " << isotrop_moy(3) << " " << isotrop_max(3) << " " << isotrop_min(3) << finl ;
1588
1589 Nom fichier_uw = fichier + Nom("_uw");
1590 SFichier fic_uw (fichier_uw, ios::app);
1591 fic_uw << temps << " " << isotrop_moy(4) << " " << isotrop_max(4) << " " << isotrop_min(4) << finl ;
1592
1593 Nom fichier_vw = fichier + Nom("_vw");
1594 SFichier fic_vw (fichier_vw, ios::app);
1595 fic_vw << temps << " " << isotrop_moy(5) << " " << isotrop_max(5) << " " << isotrop_min(5) << finl ;
1596
1597 }
1598 }
1599 else
1600 {
1601 if(je_suis_maitre())
1602 Cerr << "Traitement_particulier_NS_THI_VEF::isotropie n'est pas parallelise" << finl;
1603 }
1604
1605}
1606
1607
1608
1610{
1611 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF,mon_equation->domaine_Cl_dis());
1612 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
1613 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
1614 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
1615 const int nb_faces = domaine_VEF.nb_faces();
1616 // const int nb_faces_tot = domaine_VF.nb_faces_tot();
1617 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
1618 int nb_cl=les_cl.size();
1619 const int nb_comp=vitesse.line_size();
1620 double Ec = 0;
1621 double Ec_min = 1e+20;
1622 double Ec_max = 0;
1623
1624 DoubleVect ec_face_vect;
1625 domaine_VEF.creer_tableau_faces(ec_face_vect);
1626
1627 // calcul de la moyenne, recherche du minimum et du maximum
1628 for (int num_cl=0; num_cl<nb_cl; num_cl++)
1629 {
1630 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(num_cl);
1631 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1632 int nb_faces_bord=le_bord.nb_faces();
1633 int num1 = le_bord.num_premiere_face();
1634 int num2 = num1 + nb_faces_bord;
1635
1636 if (sub_type(Periodique,la_cl.valeur()))
1637 {
1638 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
1639 IntVect fait(nb_faces_bord);
1640 fait = 0;
1641 for (int num_face=num1; num_face<num2; num_face++)
1642 {
1643 int face_associee=la_cl_perio.face_associee(num_face-num1);
1644 if (fait(num_face-num1) == 0)
1645 {
1646 ec_face_vect(num_face)=0;
1647 for (int dim=0; dim<nb_comp; dim++)
1648 {
1649 ec_face_vect(num_face) += vitesse(num_face,dim) * vitesse(num_face,dim);
1650 }
1651 // Ec += ec_face * volumes_entrelaces(num_face);
1652
1653 fait(num_face-num1) = 1;
1654 fait(face_associee) = 1;
1655
1656
1657 }
1658 }
1659 } // fin du cas periodique
1660
1661 else // pour les autres conditions aux limites
1662 {
1663 for (int num_face=num1; num_face<num2; num_face++)
1664 {
1665 for (int dim=0; dim<nb_comp; dim++)
1666 {
1667 ec_face_vect(num_face) += vitesse(num_face,dim) * vitesse(num_face,dim);
1668 }
1669
1670 }
1671 }
1672 } // fin du traitement des conditions limites
1673
1674 // for (int num_face=domaine_VEF.premiere_face_int(); num_face<nb_faces; num_face++)
1675 for (int num_face=domaine_VEF.premiere_face_int(); num_face<nb_faces; num_face++)
1676 {
1677 for (int dim=0; dim<nb_comp; dim++)
1678 {
1679 ec_face_vect(num_face) += vitesse(num_face,dim) * vitesse(num_face,dim);
1680 }
1681
1682
1683 } // fin de la boucle pour les faces internes, incluant les domaines de joints
1684
1685 Ec_min = ec_face_vect.mp_min_vect();
1686 Ec_max = ec_face_vect.mp_max_vect();
1687
1688 for (int i=0; i<nb_faces; i++)
1689 ec_face_vect(i) *= volumes_entrelaces(i);
1690 Ec = mp_somme_vect(ec_face_vect);
1691
1692 Ec /= 2*volume_total;
1693
1694 Ec_min /= 2.;
1695
1696 Ec_max /= 2.;
1697
1698
1699 if (je_suis_maitre())
1700 {
1701 Nom fichier = Nom("Sorties_Ec_") + ext + Nom("_spatial");
1702 SFichier fic (fichier,ios::app);
1703 fic.precision(8);
1704 double temps = mon_equation->inconnue().temps();
1705 temps /= temps_retournement;
1706 fic << temps << " " << Ec << " " << Ec_max << " " << Ec_min << finl;
1707
1708 }
1709
1710 return Ec;
1711
1712}
1713
1714
1716{
1717 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
1718 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
1719 const DoubleVect& volumes = domaine_VEF.volumes();
1720 const int nb_elem = domaine_VEF.nb_elem();
1721 const Champ_P1NC& champ_vitesse = ref_cast(Champ_P1NC,mon_equation->inconnue());
1722
1723 DoubleTab vorticite(nb_elem,dimension);
1724 champ_vitesse.cal_rot_ordre1(vorticite);
1725
1726 Df = 0;
1727 double Df_min = 1e+20;
1728 double Df_max = 0;
1729
1730 // calcul de la moyenne, recherche du minimum et du maximum
1731 for(int num_elem=0; num_elem<nb_elem; num_elem++)
1732 {
1733
1734 double df_elem = 0;
1735
1736 for (int dim=0; dim<dimension; dim++)
1737 {
1738 df_elem += vorticite(num_elem,dim) * vorticite(num_elem,dim);
1739 }
1740
1741 Df += df_elem * volumes(num_elem);
1742
1743 if ( df_elem < Df_min )
1744 {
1745 Df_min = df_elem ;
1746 }
1747 if ( df_elem > Df_max )
1748 {
1749 Df_max = df_elem ;
1750 }
1751
1752 }
1753
1754 Df = mp_sum(Df);
1755 Df /= 2*volume_total;
1756
1757 Df_min = mp_min(Df_min);
1758 Df_min /= 2.;
1759
1760 Df_max = mp_max(Df_max);
1761 Df_max /= 2.;
1762
1763 // calcul de l'ecart-type
1764 double Df_ecart_type = 0;
1765 for(int num_elem=0; num_elem<nb_elem; num_elem++)
1766 {
1767 double df_elem = 0;
1768 for (int dim=0; dim<dimension; dim++)
1769 {
1770 df_elem += vorticite(num_elem,dim) * vorticite(num_elem,dim);
1771 }
1772 Df_ecart_type += ( df_elem - Df ) * ( df_elem - Df );
1773 }
1774 Df_ecart_type /= nb_elem;
1775 Df_ecart_type = sqrt(Df_ecart_type);
1776
1777 if (je_suis_maitre())
1778 {
1779 Nom fichier = Nom("Sorties_Df_tot_spatial");
1780 SFichier fic (fichier,ios::app);
1781 fic.precision(8);
1782 double temps = mon_equation->inconnue().temps();
1783 temps /= temps_retournement;
1784 fic << temps << " " << Df << " " << Df_max << " " << Df_min << " " << Df+Df_ecart_type << " " << Df-Df_ecart_type << finl;
1785
1786 // Cerr << "Df_tot=" << Df << finl;
1787 // Cerr << "Df_tot_max=" << Df_max << " Df_tot_min=" << Df_min << finl;
1788 // Cerr << "Df_tot_ecart_type=" << Df_ecart_type << finl << finl;
1789 }
1790}
1791
1792
1794{
1795 // calcul du facteur de dissymetrie (skewness)
1796 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
1797 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
1798 const DoubleVect& volumes = domaine_VEF.volumes();
1799 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
1800 const int nb_elem = domaine_VEF.nb_elem();
1801 const Champ_P1NC& champ_vitesse = ref_cast(Champ_P1NC,mon_equation->inconnue());
1802
1803 DoubleTab gradient(nb_elem_tot,dimension,dimension);
1804 gradient=0.;
1805 champ_vitesse.gradient(gradient);
1806
1807 Sk = 0;
1808
1809 DoubleTab grad_carre(dimension);
1810 grad_carre = 0;
1811
1812 DoubleTab grad_cube(dimension);
1813 grad_cube = 0;
1814
1815 for (int dim=0; dim<dimension; dim++)
1816 {
1817 // calcul du numerateur et du denominateur
1818 for(int num_elem=0; num_elem<nb_elem; num_elem++)
1819 {
1820 grad_carre(dim) += gradient(num_elem,dim,dim) * gradient(num_elem,dim,dim) * volumes(num_elem);
1821 grad_cube(dim) += gradient(num_elem,dim,dim) * gradient(num_elem,dim,dim) * gradient(num_elem,dim,dim) * volumes(num_elem);
1822 }
1823 grad_carre(dim) = mp_sum(grad_carre(dim));
1824 grad_carre(dim) /= volume_total;
1825
1826 grad_cube(dim) = mp_sum(grad_cube(dim));
1827 grad_cube(dim) /= volume_total;
1828
1829 if (grad_carre(dim) < 1.e-20 )
1830 {
1831 if (grad_cube(dim) < 1.e-20 )
1832 {
1833 Sk = 0;
1834 }
1835 else
1836 {
1837 Sk = 1e20;
1838 }
1839 }
1840 else
1841 {
1842 Sk(dim) = - grad_cube(dim) / pow(grad_carre(dim),1.5);
1843 }
1844
1845 }
1846
1847 if (je_suis_maitre())
1848 {
1849 Nom fichier = Nom("Sorties_Sk_tot_spatial");
1850 SFichier fic (fichier,ios::app);
1851 fic.precision(8);
1852 double temps = mon_equation->inconnue().temps();
1853 temps /= temps_retournement;
1854 fic << temps ;
1855 for (int dim=0; dim<dimension; dim++)
1856 {
1857 fic << " " << Sk(dim) ;
1858 }
1859 fic << finl;
1860 }
1861}
1862
1863
1864
1866{
1867 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
1868 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
1869 const DoubleVect& volumes = domaine_VEF.volumes();
1870 const int nb_elem = domaine_VEF.nb_elem();
1871 const Navier_Stokes_Turbulent& N_S_Turb = ref_cast(Navier_Stokes_Turbulent,mon_equation.valeur());
1872 const DoubleTab& visc_turb = N_S_Turb.viscosite_turbulente().valeurs();
1873
1874 double nu_t = 0;
1875 double nu_t_min = 1e+20;
1876 double nu_t_max = 0;
1877
1878 // calcul de la moyenne, recherche du minimum et du maximum
1879 for(int num_elem=0; num_elem<nb_elem; num_elem++)
1880 {
1881
1882 double nu_t_elem = visc_turb(num_elem);
1883
1884 nu_t += nu_t_elem * volumes(num_elem);
1885
1886 if ( nu_t_elem < nu_t_min )
1887 {
1888 nu_t_min = nu_t_elem ;
1889 }
1890 if ( nu_t_elem > nu_t_max )
1891 {
1892 nu_t_max = nu_t_elem ;
1893 }
1894
1895 }
1896
1897 nu_t = mp_sum(nu_t);
1898 nu_t /= volume_total;
1899
1900 nu_t_min = mp_min(nu_t_min);
1901 nu_t_max = mp_max(nu_t_max);
1902
1903 // calcul de l'ecart-type
1904 double nu_t_ecart_type = 0;
1905 for(int num_elem=0; num_elem<nb_elem; num_elem++)
1906 {
1907 double nu_t_elem = visc_turb(num_elem);
1908
1909 nu_t_ecart_type += (nu_t_elem - nu_t) * (nu_t_elem - nu_t) ;
1910 }
1911 nu_t_ecart_type /= nb_elem;
1912 nu_t_ecart_type = sqrt(nu_t_ecart_type);
1913
1914 if (je_suis_maitre())
1915 {
1916 Nom fichier = Nom("Sorties_nu_t") ;
1917 SFichier fic (fichier,ios::app);
1918 fic.precision(8);
1919 double temps = mon_equation->inconnue().temps();
1920 temps /= temps_retournement;
1921 fic << temps << " " << nu_t << " " << nu_t_max << " " << nu_t_min << " " << nu_t+nu_t_ecart_type << " " << nu_t-nu_t_ecart_type << finl;
1922
1923 }
1924
1925}
1926
1927
1928void Traitement_particulier_NS_THI_VEF::calcul_vitesse_moyenne(const DoubleTab& tab_global , DoubleVect& moyenne)
1929{
1930 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF,mon_equation->domaine_Cl_dis());
1931 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
1932 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
1933 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
1934 // const DoubleTab& vitesse = mon_equation->inconnue().valeurs();
1935 const int nb_faces = domaine_VEF.nb_faces();
1936 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
1937 int nb_cl=les_cl.size();
1938
1939 ArrOfInt flags;
1940 tab_global.get_md_vector()->get_sequential_items_flags(flags);
1941
1942 moyenne = 0;
1943 const int nb_comp = tab_global.line_size();
1944
1945 // calcul de la moyenne, recherche du minimum et du maximum
1946 for (int num_cl=0; num_cl<nb_cl; num_cl++)
1947 {
1948 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(num_cl);
1949 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
1950 int nb_faces_bord=le_bord.nb_faces();
1951 int num1 = le_bord.num_premiere_face();
1952 int num2 = num1 + nb_faces_bord;
1953
1954 if (sub_type(Periodique,la_cl.valeur()))
1955 {
1956 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
1957 IntVect fait(nb_faces_bord);
1958 fait = 0;
1959 for (int num_face=num1; num_face<num2; num_face++)
1960 {
1961 int face_associee=la_cl_perio.face_associee(num_face-num1);
1962 if (fait(num_face-num1) == 0)
1963 {
1964 if (flags[num_face])
1965 {
1966 for (int dim=0; dim<nb_comp; dim++)
1967 moyenne(dim) += tab_global(num_face,dim) * volumes_entrelaces(num_face);
1968 }
1969 fait(num_face-num1) = 1;
1970 fait(face_associee) = 1;
1971 }
1972 }
1973 } // fin du cas periodique
1974
1975 else // pour les autres conditions aux limites
1976 {
1977 for (int num_face=num1; num_face<num2; num_face++)
1978 {
1979 if (flags[num_face])
1980 {
1981 for (int dim=0; dim<nb_comp; dim++)
1982 {
1983 moyenne(dim) += tab_global(num_face,dim) * volumes_entrelaces(num_face);
1984 }
1985 }
1986 }
1987 }
1988 } // fin du traitement des conditions limites
1989
1990 for (int num_face=domaine_VEF.premiere_face_int(); num_face<nb_faces; num_face++)
1991 {
1992 if (flags[num_face])
1993 {
1994 for (int dim=0; dim<nb_comp; dim++)
1995 moyenne(dim) += tab_global(num_face,dim) * volumes_entrelaces(num_face);
1996 }
1997 } // fin de la boucle pour les faces internes
1998
1999
2000 for (int dim=0; dim<nb_comp; dim++)
2001 moyenne(dim) = Process::mp_sum(moyenne(dim));
2002
2003 moyenne /= volume_total;
2004
2005}
2006
2007
2008void Traitement_particulier_NS_THI_VEF::calcul_moyenne(const DoubleTab& tab_global , double& moyenne)
2009{
2010 const Domaine_Cl_VEF& domaine_Cl_VEF = ref_cast(Domaine_Cl_VEF,mon_equation->domaine_Cl_dis());
2011 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
2012 const Domaine_VEF& domaine_VEF=ref_cast(Domaine_VEF, zdisbase);
2013 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
2014 // const DoubleTab& vitesse = mon_equation->inconnue().valeurs();
2015 const int nb_faces = domaine_VEF.nb_faces();
2016 const Conds_lim& les_cl = domaine_Cl_VEF.les_conditions_limites();
2017 int nb_cl=les_cl.size();
2018
2019 DoubleVect moyenne_vect;
2020 domaine_VEF.creer_tableau_faces(moyenne_vect);
2021 moyenne = 0;
2022
2023 // calcul de la moyenne, recherche du minimum et du maximum
2024 for (int num_cl=0; num_cl<nb_cl; num_cl++)
2025 {
2026 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(num_cl);
2027 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
2028 int nb_faces_bord=le_bord.nb_faces();
2029 int num1 = le_bord.num_premiere_face();
2030 int num2 = num1 + nb_faces_bord;
2031
2032 if (sub_type(Periodique,la_cl.valeur()))
2033 {
2034 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
2035 IntVect fait(nb_faces_bord);
2036 fait = 0;
2037 for (int num_face=num1; num_face<num2; num_face++)
2038 {
2039 int face_associee=la_cl_perio.face_associee(num_face-num1);
2040 if (fait(num_face-num1) == 0)
2041 {
2042 moyenne_vect(num_face) = tab_global(num_face) * volumes_entrelaces(num_face);
2043
2044 fait(num_face-num1) = 1;
2045 fait(face_associee) = 1;
2046 }
2047 }
2048 } // fin du cas periodique
2049
2050 else // pour les autres conditions aux limites
2051 {
2052 for (int num_face=num1; num_face<num2; num_face++)
2053 {
2054 moyenne_vect(num_face) = tab_global(num_face) * volumes_entrelaces(num_face);
2055 }
2056 }
2057 } // fin du traitement des conditions limites
2058
2059 for (int num_face=domaine_VEF.premiere_face_int(); num_face<nb_faces; num_face++)
2060 {
2061 moyenne_vect(num_face) = tab_global(num_face) * volumes_entrelaces(num_face);
2062
2063 } // fin de la boucle pour les faces internes
2064
2065
2066
2067 moyenne=mp_somme_vect(moyenne_vect);
2068
2069
2070
2071 moyenne /= volume_total;
2072
2073}
2074
2076{
2077 if (je_suis_maitre())
2078 {
2079 Nom fichier = Nom("Sorties_vitesse_moyenne") ;
2080 SFichier fic (fichier,ios::app);
2081 fic.precision(8);
2082 double temps = mon_equation->inconnue().temps();
2083 temps /= temps_retournement;
2084 fic << temps;
2085 for (int dim=0; dim<dimension; dim ++)
2086 fic << " " << moyenne_vitesse(dim);
2087 fic << finl;
2088
2089 // Les champs scalaires
2090 for (int i=0; i<nb_champs_scalaires; i++)
2091 {
2092 Nom fichier2 = Nom("Sorties_");
2093 fichier2+=noms_champs_scalaires[i];
2094 fichier2+="_moyenne";
2095 SFichier fic2 (fichier2,ios::app);
2096 fic2.precision(8);
2097 fic2 << temps;
2098 fic2 << " " << moyennes_scal(i);
2099 fic2 << finl;
2100 }
2101 }
2102
2103}
2104
2105
2107// Supprime la composante moyenne de la vitesse dans chaque direction,
2108// travaille avec les vitesses aux faces
2109{
2110 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
2111 const Domaine_VF& domaine_VF=ref_cast(Domaine_VF, zdisbase);
2112 DoubleTab& vitesse = mon_equation->inconnue().valeurs();
2113 const int nb_faces = domaine_VF.nb_faces();
2114
2115
2116 if (je_suis_maitre())
2117 Cerr << "Suppression de la vitesse moyenne. " ;
2118
2119 for (int num_face=0; num_face<nb_faces; num_face++)
2120 {
2121 for (int dim=0; dim<dimension; dim ++)
2122 {
2123 vitesse(num_face,dim) -= moyenne_vitesse(dim);
2124 }
2125 }
2126
2127 if (je_suis_maitre())
2128 Cerr << "OK." << finl;
2129
2130 calcul_vitesse_moyenne(vitesse, moyenne_vitesse);
2132}
2133
2134
2136// force la conservation de l'energie cinetique (THI forcee
2137// par opposition a THI en decroissance libre)
2138{
2139 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
2140 const Domaine_VF& domaine_VF=ref_cast(Domaine_VF, zdisbase);
2141 DoubleTab& vitesse = mon_equation->inconnue().valeurs();
2142 const int nb_faces = domaine_VF.nb_faces();
2143
2144
2145 if (je_suis_maitre())
2146 Cerr << "Suppression de la vitesse moyenne. " ;
2147
2148 for (int num_face=0; num_face<nb_faces; num_face++)
2149 {
2150 for (int dim=0; dim<dimension; dim ++)
2151 {
2152 vitesse(num_face,dim) -= moyenne_vitesse(dim);
2153 }
2154 }
2155
2156 if (je_suis_maitre())
2157 Cerr << "OK." << finl;
2158
2159
2160 double Ec;
2161 Ec = calcul_Ec_spatial(vitesse, "force");
2162
2163 double nE=pow(Ec/Ec_init,0.5);
2164 Cerr << "Ec = " << Ec << ", on divise la vitesse par : " << nE << finl;
2165 vitesse/=nE;
2166
2167}
2168
2169
2170
2171
2173// renvoie le plus petit commun multiple de a et b
2174{
2175 return a * b / pgcd(a,b);
2176}
2177
2179// renvoie le plus grand commun diviseur de a et b
2180{
2181 while ( b )
2182 {
2183 int c = a%b;
2184 a = b;
2185 b = c;
2186 }
2187 return abs(a);
2188}
2189
2190
2192{
2193 double temps_courant = mon_equation->inconnue().temps();
2194 const DoubleTab& vitesse = mon_equation->inconnue().valeurs();
2195
2196 moyennes_scal.resize(nb_champs_scalaires); //les scalaires : moyenne = 1 double par scalaire
2197 moyenne_vitesse.resize(dimension);
2198
2199 volume_total = calcul_volume_elem();
2200 Cerr << "Volume total = " << volume_total << finl;
2201 if (init==0)
2202 {
2203 temps_retournement=1;
2204 Ec_init = calcul_Ec_spatial(vitesse, "init");
2205 Cout << "Calcul Ec_init = " << Ec_init << finl;
2206 }
2207 if (Ec_init > 0.)
2208 {
2209 temps_retournement = (L_BOITE) / sqrt(2*Ec_init);
2210 if(je_suis_maitre())
2211 Cerr << "temps de retournement base sur une longueur de "<< L_BOITE << " et une energie cinetique de Ec_init=" << Ec_init << " : " << temps_retournement << finl;
2212 }
2213 else
2214 {
2215 temps_retournement = 1;
2216 }
2217 calcul_vitesse_moyenne(vitesse, moyenne_vitesse);
2219 if (init==1) renorm_Ec();
2220
2221 if ( (oui_calc_spectre != 0) && (temps_courant == 0) )
2222 {
2224 if ( (oui_calc_spectre != 0)
2225 && (temps_courant > compteur_perio_spectre*periode_calc_spectre) )
2226 {
2228 compteur_perio_spectre ++;
2229 }
2230 }
2231
2233}
2234
2236{
2237 double temps_courant = mon_equation->inconnue().temps();
2238 const DoubleTab& vitesse = mon_equation->inconnue().valeurs();
2239
2240 calcul_vitesse_moyenne(vitesse, moyenne_vitesse);
2241
2242 if (oui_conservation_Ec==1) conservation_Ec();
2243 if ( (oui_calc_spectre != 0) && (temps_courant > compteur_perio_spectre*periode_calc_spectre) )
2244 {
2246 compteur_perio_spectre ++;
2247 }
2249}
2250
2252{
2253 const Domaine_dis_base& zdisbase=mon_equation->inconnue().domaine_dis_base();
2254 const Domaine_VF& domaine_VF=ref_cast(Domaine_VF, zdisbase);
2255 const DoubleVect& volumes = domaine_VF.volumes();
2256 const int nb_elem = domaine_VF.nb_elem();
2257
2258 double volume = 0;
2259
2260 for(int num_elem=0; num_elem<nb_elem; num_elem++)
2261 {
2262 volume += volumes(num_elem);
2263 }
2264
2265 volume = mp_sum(volume);
2266
2267 return volume;
2268
2269}
2270
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
void cal_rot_ordre1(DoubleTab &) const
void gradient(DoubleTab &) const
void filtrer_L2(DoubleTab &x) const
Definition Champ_P1NC.h:127
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
double volumes(int i) const
Definition Domaine_VF.h:113
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_elem_tot() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
int get_sequential_items_flags(ArrOfBit &flags, int line_size=1) const
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:321
classe Navier_Stokes_Turbulent Cette classe represente l'equation de la dynamique pour un fluide
const Champ_Fonc_base & viscosite_turbulente() const
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
friend class Entree
Definition Objet_U.h:76
static int dimension
Definition Objet_U.h:99
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
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static double mp_min(double)
Definition Process.cpp:386
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 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
void precision(int pre) override
Classe de base des flux de sortie.
Definition Sortie.h:52
_TYPE_ * addr()
virtual void ref(const TRUSTTab &)
Definition TRUSTTab.tpp:308
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
_TYPE_ mp_max_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:158
_TYPE_ mp_min_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:159
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123
classe Traitement_particulier_NS_THI_VEF Cette classe permet de faire les traitements particuliers
void calcul_vitesse_moyenne(const DoubleTab &, DoubleVect &)
void calcul_spectre_3D(const DoubleTab &, Nom, double &)
void determine_tab_fft_VEF_3D(IntTab &, DoubleTab &, IntVect &, int &, int &)
void ch_pour_fft_VEF_1D(const DoubleTab &, DoubleVect &, DoubleVect &, DoubleVect &, int, int) const
void calcul_spectre_1D(const DoubleTab &, Nom, double &)
void determine_tab_fft_VEF_1D(const IntTab &, const DoubleTab &, const IntVect &, IntVect &, IntVect &)
void ch_pour_fft_VEF_3D(const DoubleTab &, DoubleTab &, DoubleTab &, DoubleTab &, int) const
classe Traitement_particulier_THI Cette classe permet de faire les traitements particuliers