TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Random_process.cpp
1/****************************************************************************
2* Copyright (c) 2021, 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 <Random_process.h>
17#include <random>
18#include <math.h>
19#include <fstream>
20
21#include <Domaine_IJK.h> // Pour que la classe de splitting soit connue
22#include <communications.h>
23
24#include <Param.h>
25#include <Interprete_bloc.h>
26#include <EFichier.h>
27#include <SFichier.h>
28#include <IJK_Lata_writer.h>
29#include <IJK_Navier_Stokes_tools.h>
30#include <LecFicDiffuse_JDD.h>
31#include <MaillerParallel.h>
32#include <EChaine.h>
33#include <SChaine.h>
34#include <Probleme_base.h>
35#include <Domaine_VF.h>
36#include <Sonde_IJK.h>
37#include <Ouvrir_fichier.h>
38#include <EcritureLectureSpecial.h>
39
40
41Implemente_instanciable_sans_constructeur_ni_destructeur( Random_process, "Random_process", Objet_U ) ;
42
44{
45
46 // gr-21.07.21 - 23.07.21 :
47 // Je garde une trace de toutes les idees tant que de vraies belles simus ne sont pas passees sur Occigen.
48 // Idee 1 : os << gen << "\n";
49 // -> l'operateur << ne fonctionne pas entre un Sortie et un minstd_rand ni entre un sortie et un minstd_rand
50 // Idee 2 : std::fstream my_os; my_os << gen; os << my_os;
51 // -> l'operateur << ne fonctionne pas entre un Sortie et un std:fstream...
52 // Idee 3 : Stocker les 625 valeur de l'etat de gen dans un DoubleTab (pour un mt19937),
53 // -> je ne sais pas acceder un a un aux 625 elements de gen.
54 // Idee 4 : Ecrire dans un fichier la donnée, la stocker dans un DoubleTab depuis la lecture de ce fichier,
55 // donner ce DoubleTab a la Sortie os.
56 // Idee AK: Passer par un ostringstream puis convertir la string en long avec std::stol
57 //
58 // REMARQUES :
59 // - avec mt19937, gen contient 625 entiers codes sur 32 bits.
60 // l'ecriture dans un fichier ecrit correctement le premier chiffre. ecrit un deuxieme chiffre qui
61 // n'est pas present dans le fichier puis complete avec des zeros. MAUVAIS. (IntTab de long int ?)
62 // - avec minstd_rand alors gen contient un integer code sur 32 bit. A stocker dans un long int
63 // PROBLEMES :
64 // - Passer les variables pour lecture/ecriture en attribut de classe
65 // - Travailler sur l'attribut de classe semi_gen_et_modulo_reprise_ des le printOn.
66
67 // *gen_write_->open(nomFichierReprise_.c_str());
68 // *gen_write_ << gen;
69 // gen_write_->close();
70 /*
71 * TODO: M.G Cela n'a strictement rien à faire dans printOn..., nom_sauvegarde_ n'est pas meme pas initialisé
72 *
73 std::ofstream gen_write(nom_sauvegarde_ + ".gen");
74 // SFichier gen_write;
75 // gen_write.ouvrir(nom_sauvegarde_);
76 gen_write << gen;
77 gen_write.close();
78
79 // IntTab semi_gen_et_modulo_reprise;
80
81 ArrOfInt semi_gen_et_modulo_reprise(2);
82 long long_gen;
83
84 // gen_read_->open(nomFichierReprise_.c_str(), std::eam::out);
85 // *gen_read_ >> long_gen;
86 // gen_read_->close();
87
88 // std::ifstream gen_read(nom_du_cas()+".sauv.gen");
89
90 EFichier gen_read;
91 gen_read.ouvrir(nom_sauvegarde_ + ".gen");
92 gen_read >> long_gen;
93 gen_read.close();
94
95 semi_gen_et_modulo_reprise(0) = (int)(long_gen/2); // 10 (en binaire) : "10 >> 1 = 01"
96 semi_gen_et_modulo_reprise(1) = (int)(long_gen%2);
97
98 */
99
100 // IntTab like_gen;
101 // like_gen.resize(625);
102 // for (int i=0; i<625; i++)
103 // {
104 // gen_read >> like_gen(i);
105 // }
106
107 os << "{\n";
108 os << " semi_gen_et_modulo_reprise " << semi_gen_et_modulo_reprise_ << "\n";
109 os << " process_b " << process_flt << "\n";
110 os << " }\n" ;
111 return os;
112}
113
115{
116 // param.ajouter n'existe pas pour un long int.
117 Param param(que_suis_je());
118 param.ajouter("process_b",&process_flt);
119
120// gen_write_->open(nomFichierReprise_.c_str());
121// *gen_write_ << like_gen;
122// gen_write_->close();
123// gen_read_->open(nomFichierReprise_.c_str());
124// *gen_read_ >> long_gen;
125// gen_read_->close();
126
127// std::ifstream gen_read("reprise_gen.txt");
128// gen_read >> long_gen;
129// gen_read >> gen;
130// gen_read.close();
131
132 param.ajouter("semi_gen_et_modulo_reprise",&semi_gen_et_modulo_reprise_,Param::REQUIRED);
133 //Cout << "hello" << finl;
134 //param.ajouter("distribution",&distribution);
135 param.lire_avec_accolades(is);
136 return is;
137}
138
139
140Random_process::Random_process() : nl(0),nm(0),nn(0),n_lmn(nl*nn*nm),kmin(0),kmax(0),semi_gen_et_modulo_reprise_(2)
141{
142 semi_gen_et_modulo_reprise_[0]=0;
143 semi_gen_et_modulo_reprise_[1]=0;
144}
145
146
151
152
153void Random_process::initialise(double a_eps_etoile, double a_tL,
154 int a_nl, int a_nm, int a_nn, std::string nom_fichier,//, int a_random_fixed_,
155 Nom nom_sauvegarde
156 )
157{
158// int ind,l,m,n;
159 nl = a_nl;
160 nm = a_nm;
161 nn = a_nn;
162 n_lmn = (2*nl+1)*(2*nm+1)*(2*nn+1);
163
164 eps_etoile = a_eps_etoile;
165 tL = a_tL;
166 process = set_dimensions(process,2,3,n_lmn);
167// process_flt.resize(2*3*n_lmn,0.0);
168 process_flt.resize(2*3*n_lmn);
169 semi_gen_et_modulo_reprise_.resize(2);
170 moke_gen_ = semi_gen_et_modulo_reprise_[0] ;
171
172 // Initialisation de la serie aleatoire qui sera tiree.
173 if (moke_gen_ < 0 )
174 {
175 // La valeur de l'etat initial est prise au hasard
176 // (dans le jdd on met semi_gen_et_modulo_reprise_ et process_flt_ a 0, ou on ne les met pas du tout)
177 // comme moke_gen_ est issu d'un flag, il ne doit jamais pouvoir etre <0.
178 std::random_device rd {};
179 std::minstd_rand gen_support(rd());
180 gen = gen_support;
181 }
182 else if (moke_gen_ >= 0)
183 {
184 // L'état initial de la serie est connu mais pas le champ b. Solution simple pour determinisme
185 // (dans le jeu de donnees on renseigne normalement semi_gen_et_modulo_reprise_ et on ne met pas process_flt_)
186 long long_gen(2*semi_gen_et_modulo_reprise_[0] + semi_gen_et_modulo_reprise_[1]);
187 std::minstd_rand gen_support(long_gen);
188 gen = gen_support;
189 }
190 else
191 {
192// // (dans le jdd, semi_gen_et_modulo_reprise_ et process_flt_ sont connus et renseignes)
193// // l'etat initial est connu a partir de semi_gen_et_modulo_reprise_ et le champ b est connu a partir de process_flt
194// long long_gen(2*semi_gen_et_modulo_reprise_[0] + semi_gen_et_modulo_reprise_[1]);
195// std::minstd_rand gen_support(long_gen);
196// gen = gen_support;
197//
198 Cerr << "moke_gen a une valeur anormale" << finl;
199 }
200
201 std::normal_distribution < > dist_support(0.,1.);
202 distribution = dist_support;
203
204// std::ofstream detail_gen(nom_fichier);
205 nom_sauvegarde_ = nom_sauvegarde;
206 nom_fichier_ = nom_fichier;
207 std::ofstream Detail_gen(nom_fichier_.c_str());
208 if(Detail_gen)
209 {
210 Detail_gen << "-------- RANDOM_PROCESS; detail de gen --------" << std::endl;
211// Detail_gen << std::endl << "l,m,n \t : b_x, \tb_y, \tb_z,\t";
212 }
213
214// nomFichierReprise_ = "reprise_gen.sauv";
215// *gen_write_ = nomFichierReprise_.c_str();
216// *gen_read_ = nomFichierReprise_.c_str();
217
218}
219
220
221void Random_process::next_step(double dt, int it)
222{
223 // Ajouter le lien d'ou j'ai pompe
224 // --> Plus bien voir comment FIXER l'etat aleatoire que l'on va parcourir
225 // --> Plus donner la possibilite dans le jdd de jouer sur la serie aleatoire tiree
226 // std::random_device rd;
227 // std::minstd_rand gen(rd());
228 // std::minstd_rand gen(it);
229 // std::normal_distribution<double> distribution(0.0,1.0);
230 double Gaussian[2][3];
231 std::vector< std::vector< std:: vector < double > > > old_process;
232 int cpx, dir, l, m, n, ind;
233
234 old_process = process;
235 for (n=0; n<2*nn+1; n++)
236 for (m=0; m<2*nm+1; m++)
237 // TODO : Distinguer cas pair de cas impair !!! ATTN
238 for (l=nl; l<2*nl+1; l++) // La force sp est a symmetrie Hermitienne, donc le rp aussi. On ne parcourt donc que la moitiee du tout
239 {
240 ind = (n*(2*nm+1) + m) * (2*nl+1) +l;
241 // std::cout << "ind : " << ind << "/" << n_lmn << std::endl;
242 // std::cout << "otr : " << n_lmn-ind << "/" << n_lmn << std::endl;
243 for (dir=0; dir<3; dir++)
244 {
245 for (cpx=0; cpx<2; cpx++)
246 {
247 Gaussian[cpx][dir] = distribution(gen);
248 process[cpx][dir][ind] = old_process[cpx][dir][ind]*(1-dt/tL);
249 process[cpx][dir][ind] += Gaussian[cpx][dir]*sqrt(2*eps_etoile*dt*pow(tL,2));
250 }
251 // Symetrie Hermitienne. Sous nos conventions, -k[ind] = k[n_lmn - ind]
252 // Remarque : on ne se sert meme pas de l'autre moitie.
253 // on la calcule quand meme pour faciliter les ecritures
254 process[0][dir][n_lmn-ind] = process[0][dir][ind];
255 process[1][dir][n_lmn-ind] = - process[1][dir][ind];
256 }
257 }
258}
259
260
261
262void Random_process::next_step2(double dt, int it)
263{
265 {
266 // Si sorties supplementaires est mis a 1, on ecrit les etats valeurs de seed dans un fichier.
267 // --> Utile que pour debuguer/ attester de façon extremement précise que les reprises sont "justes"
268 int sorties_supplementaires(0);
269 std::ofstream Detail_gen(nom_fichier_.c_str(),std::ios_base::app);
270 int n_dir(3);
271 // source : https://en.cppreference.com/w/cpp/numeric/random/normal_distribution
272 // Attention, initialiser de nouvelles graines a chaque fois c'est pas la bonne utilisation
273 double Gaussian[2][3];
274
275 // std:: vector < double > old_process;
276 ArrOfDouble old_process(process_flt);
277 // old_process = process_flt;
278 // process_flt.resize(2*3*n_lmn,0.0);
279 process_flt = 0.;
280
281 for (int n=0; n<2*nn+1; n++)
282 for (int m=0; m<2*nm+1; m++)
283 // TODO : Distinguer cas pair de cas impair !!! ATTN
284 for (int l=0; l<2*nl+1; l++) // La force sp est a symmetrie Hermitienne, donc le rp aussi. On ne parcourt donc que la moitiee du tou
285 {
286 int ind_lmn = (n*(2*nm+1) + m) * (2*nl+1) +l;
287 for (int dir=0; dir<3; dir++)
288 {
289 // double a(distribution(gen));
290 // Gaussian[0][dir] = cos(a);
291 // Gaussian[1][dir] = sin(a);
292 for (int cpx=0; cpx<2; cpx++)
293 {
294 int ind_CDIlmn((cpx*n_dir+dir)*n_lmn+ind_lmn);
295 if (sorties_supplementaires)
296 Detail_gen << gen << " ";
297 Gaussian[cpx][dir] = distribution(gen); // Pour avoir une variance à 1, pas à 2.
298 if (sorties_supplementaires)
299 Detail_gen << gen << std::endl;
300 process_flt[ind_CDIlmn] = old_process[ind_CDIlmn]*(1-dt/tL);
301 process_flt[ind_CDIlmn] += Gaussian[cpx][dir]*sqrt(2.0*eps_etoile*(0.0+dt)/pow(tL,2));
302 }
303 // Symetrie Hermitienne. Sous nos conventions, -k[ind] = k[n_lmn - ind]
304 // Remarque : on ne se sert meme pas de l'autre moitie.
305 // on la calcule quand meme pour faciliter les ecritures
306 // process_flt[(0*n_dir+dir)*n_lmn+(ind_lmn_moins)] = process_flt[(0*n_dir+dir)*n_lmn+(ind_lmn)];
307 // process_flt[(1*n_dir+dir)*n_lmn+(ind_lmn_moins)] = - process_flt[(1*n_dir+dir)*n_lmn+(ind_lmn)];
308 }
309 }
310 if (sorties_supplementaires)
311 Detail_gen.close();
312 }
313 envoyer_broadcast(process_flt,0);
314}
315
316void Random_process::next_step3(ArrOfDouble& advection_velocity, double dt, int it)
317{
318 // On ajoute l'advection du forcage uniquement sur processus aleatoire
319 // On ajoute aussi la condition quon mene une action uniquement si |k| > k_min
321 {
322 std::ofstream Detail_gen(nom_fichier_.c_str(),std::ios_base::app);
323 int n_dir(3);
324 // source : https://en.cppreference.com/w/cpp/numeric/random/normal_distribution
325 // Attention, initialiser de nouvelles graines a chaque fois c'est pas la bonne utilisation
326 double Gaussian[2][3];
327
328 // std:: vector < double > old_process;
329 ArrOfDouble old_process(process_flt);
330 // old_process = process_flt;
331 // process_flt.resize(2*3*n_lmn,0.0);
332 process_flt = 0.;
333 double kappa[3];
334 double coefficient_translation[2*3];
335
336 for (int n=0; n<2*nn+1; n++)
337 for (int m=0; m<2*nm+1; m++)
338 // TODO : Distinguer cas pair de cas impair !!! ATTN
339 for (int l=0; l<2*nl+1; l++) // La force sp est a symmetrie Hermitienne, donc le rp aussi. On ne parcourt donc que la moitiee du tout
340 {
341 int ind_lmn = (n*(2*nm+1) + m) * (2*nl+1) +l;
342 int ind_lmn_moins = (n*(2*nm+1) + m) * (2*nl+1) + (2*nl-l);
343
344 // Position dans l'espace spectral. k_x va de -kmin a +kmin,
345 // d'ou le l-nl
346 kappa[0] = - kmax + (l)*(2*kmax)/(2*nl);
347 kappa[1] = - kmax + (m)*(2*kmax)/(2*nm);
348 kappa[2] = - kmax + (n)*(2*kmax)/(2*nn);
349
350
351 if (!(std::fabs(kappa[0])<kmin && std::fabs(kappa[1])<kmin && std::fabs(kappa[2])<kmin))
352 {
353 for (int dir=0; dir<3; dir++)
354 {
355 // double a(distribution(gen));
356 // Gaussian[0][dir] = cos(a);
357 // Gaussian[1][dir] = sin(a);
358 int ind_RD(0*n_dir+dir);
359 int ind_CD(1*n_dir+dir);
360 int ind_CDIlmn((1*n_dir+dir)*n_lmn+ind_lmn);
361 int ind_RDIlmn((0*n_dir+dir)*n_lmn+ind_lmn);
362
363 // ATTENTION ! On fait ici une translation de u*dt or il faut faire une translation de u*t
364 coefficient_translation[ind_RD] = cos(-1.*kappa[dir]*dt*advection_velocity[dir]);
365 coefficient_translation[ind_CD] = sin(-1.*kappa[dir]*dt*advection_velocity[dir]);
366
367 // Translation de l'etat precedent
368 process_flt[ind_RDIlmn] = old_process[ind_RDIlmn]*coefficient_translation[ind_RD] - old_process[ind_CDIlmn]*coefficient_translation[ind_CD];
369 process_flt[ind_CDIlmn] = old_process[ind_RDIlmn]*coefficient_translation[ind_CD] + old_process[ind_CDIlmn]*coefficient_translation[ind_RD];
370
371 for (int cpx=0; cpx<2; cpx++)
372 {
373 int ind_RCDIlmn((cpx*n_dir+dir)*n_lmn+ind_lmn);
374 Detail_gen << gen << " ";
375 Gaussian[cpx][dir] = distribution(gen);
376 Detail_gen << gen << std::endl;
377 process_flt[ind_RCDIlmn] = process_flt[ind_RCDIlmn]*(1-dt/tL);
378 process_flt[ind_RCDIlmn] += Gaussian[cpx][dir]*sqrt(2*eps_etoile*(0.0+dt)/pow(tL,2));
379 }
380 // Symetrie Hermitienne. Sous nos conventions, -k[ind] = k[n_lmn - ind]
381 // Remarque : on ne se sert meme pas de l'autre moitie.
382 // on la calcule quand meme pour faciliter les ecritures
383 process_flt[(0*n_dir+dir)*n_lmn+(ind_lmn_moins)] = process_flt[(0*n_dir+dir)*n_lmn+(ind_lmn)];
384 process_flt[(1*n_dir+dir)*n_lmn+(ind_lmn_moins)] = - process_flt[(1*n_dir+dir)*n_lmn+(ind_lmn)];
385 }
386 }
387 }
388 Detail_gen.close();
389 }
390 envoyer_broadcast(process_flt,0);
391}
392
393
394void Random_process::write(std::string nom_fichier_sortie, double t)
395{
396 std::ofstream Random_flux(nom_fichier_sortie.c_str(), std::ios::app);
397 if (Random_flux)
398 {
399 // int cpx, dir;
400 int l, m, n, ind;
401
402 Random_flux << std::endl << "time : " << t << std::endl << std::endl;
403 for (n=0; n<2*nn+1; n++)
404 for (m=0; m<2*nm+1; m++)
405 for (l=0; l<2*nl+1; l++)
406 {
407 ind = (n*(2*nm+1) + m) * (2*nl+1) +l;
408 Random_flux << l<<","<<m<<","<<n<<"\t : ";
409 Random_flux << process[0][0][ind] << " + i" << process[1][0][ind]<<", \t";
410 Random_flux << process[0][1][ind] << " + i" << process[1][1][ind]<<", \t";
411 Random_flux << process[0][2][ind] << " + i" << process[1][2][ind]<<", \t";
412 Random_flux << std::endl;
413 }
414 }
415}
416
417void Random_process::write_separate(std::string nom_fichier_sortie, double t)
418{
419 std::ofstream Random_flux(nom_fichier_sortie.c_str());
420 if (Random_flux)
421 {
422 // int cpx, dir;
423 int l, m, n, ind;
424 Random_flux << std::endl << "l,m,n, \t rb_x, \t cb_x, \t\t rb_y, \t cb_y, \t\t rb_z, \t cb_z \t";
425 Random_flux << std::endl;
426
427 // Random_flux << std::endl << "time : " << t << std::endl << std::endl;
428 for (n=0; n<2*nn+1; n++)
429 for (m=0; m<2*nm+1; m++)
430 for (l=0; l<2*nl+1; l++)
431 {
432 ind = (n*(2*nm+1) + m) * (2*nl+1) +l;
433 Random_flux << l<<","<<m<<","<<n<<"\t,";
434 Random_flux << process[0][0][ind] << ",\t" << process[1][0][ind]<<", \t\t";
435 Random_flux << process[0][1][ind] << ",\t" << process[1][1][ind]<<", \t\t";
436 Random_flux << process[0][2][ind] << ",\t" << process[1][2][ind]<<"\t";
437 Random_flux << std::endl;
438 }
439 }
440}
441
442std::vector< std::vector< std:: vector < double >>> Random_process::get_b()
443{
444 return process;
445}
446
447// std:: vector < double > Random_process::get_b_flt()
449{
450 return process_flt;
451}
452
454{
455 return semi_gen_et_modulo_reprise_[0];
456}
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
@ REQUIRED
Definition Param.h:115
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
void next_step2(double dt, int it)
void write(std::string nom_fichier_sortie, double temps)
void write_separate(std::string nom_fichier_sortie, double t)
std::vector< std::vector< std::vector< double > > > get_b()
void next_step3(ArrOfDouble &advection_velocity, double dt, int it)
ArrOfDouble & get_b_flt()
void next_step(double dt, int it)
void initialise(double eps_etoile, double tL, int nl, int nm, int nn, std::string nom_fichier_sortie, Nom nom_sauvegarde)
Classe de base des flux de sortie.
Definition Sortie.h:52