TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Couplage_Tubes_IBC.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#include <Couplage_Tubes_IBC.h>
16#include <Param.h>
17#include <Interprete_bloc.h>
18#include <Linear_algebra_tools.h>
19#include <communications.h>
20#include <SFichier.h>
21#include <EFichier.h>
22#include <IJK_Navier_Stokes_tools.h>
23
24Implemente_instanciable(Couplage_Tubes_IBC, "Couplage_Tubes_IBC", Objet_U);
25// Fonction qui permet d'afficher toutes les composantes d'un Vecteur3
26static Sortie& operator<<(Sortie& os, Vecteur3 v)
27{
28 os << "[ " << v[0] << " " << v[1] << " " << v[2] << " ]";
29 return os;
30}
31// Pour ecrire l'objet dans un fichier ou a l'ecran (pour l'instant ne fait rien)
33{
34 return os;
35}
36
37// Lecture de l'objet dans le jeu de donnees
39{
40 Param param(que_suis_je());
41 param.ajouter("vitesse_pour_adim", &vitesse_pour_adim_, Param::REQUIRED);
42 param.ajouter("rho_fluide_pour_adim", &rho_fluide_pour_adim_, Param::REQUIRED);
43 param.ajouter("lissage", &lissage_, Param::REQUIRED);
44 param.dictionnaire("etalement", ETALEMENT); // Attention le dictionnaire s'applique sur le dernier param ajoute !!!!
45 param.dictionnaire("pas_etalement", PAS_ETALEMENT);
46 param.ajouter("epaisseur_lissage", &epaisseur_lissage_, Param::REQUIRED);
47 Nom nomobjet_faisceau_tubes;
48 param.ajouter("faisceau_tubes", &nomobjet_faisceau_tubes);
49 param.ajouter("champ_miroir", &champ_miroir_, Param::REQUIRED);
50 param.dictionnaire("miroir", MIROIR);
51 param.dictionnaire("symetrie_plane", SYMETRIE_PLANE);
52 param.dictionnaire("pas_miroir", PAS_MIROIR);
53 param.ajouter("methode_IBC", &methode_IBC_, Param::REQUIRED);
54 param.dictionnaire("ibc0", IBC0);
55 param.dictionnaire("ibc_diffuse", IBC_DIFFUSE);
56 param.dictionnaire("ibc_localisee", IBC_LOCALISEE);
57 param.dictionnaire("ibc_localisee_qdm", IBC_LOCALISEE_QDM);
58 param.ajouter("solide", &solide_, Param::REQUIRED);
59 param.dictionnaire("cylindre", CYLINDRE);
60 param.dictionnaire("cube", CUBE);
61 param.ajouter("n_P", &n_P_, Param::REQUIRED);
62 param.ajouter("L_cube", &L_cube_, Param::REQUIRED);
63 param.lire_avec_accolades(is);
64
65
66 if (nomobjet_faisceau_tubes != "??")
67 {
68 faisceau_ = ref_cast(Faisceau_Tubes, Interprete_bloc::objet_global(nomobjet_faisceau_tubes));
69 Cout << "On a lu les donnees dans le fichier " << nomobjet_faisceau_tubes << ":" << finl;
70 Cout << faisceau_; // affiche les valeurs contenues dans le tableau donnes_tubes_ pr verifier qu'on a bien copier les valeurs donnees en entre
71 }
72 return is;
73}
74
76{
77 ref_domaine_ = dom; // copie de splitting pour l'utiliser dans la class Couplage_Tubes_IBC
78
79 const int n_tubes_total = faisceau_.size();
80 integrale_force_.resize(n_tubes_total , 3);
81 integrale_force_post_proj_.resize(n_tubes_total , 3);
82 integrale_force_pression_.resize(n_tubes_total , 2);
83 pression_teta_.resize(n_tubes_total , n_P_);
84 d_integrale_force_.resize(n_tubes_total , 3);
85 d_integrale_force_post_proj_.resize(n_tubes_total , 3);
86 integrale_force_N_moins_1_.resize(n_tubes_total , 3);
87 integrale_force_N_moins_1_post_proj_.resize(n_tubes_total , 3);
88 volume_cylindres_.resize(n_tubes_total , 3);
89 masse_fluide_cylindres_.resize(n_tubes_total, 3);
90
91 for (int i = 0; i < n_tubes_total; i++)
92 faisceau_[i]->initialize(dom); // la fonction initialize() appartient a la class Tube_base, on l'appelle ici pour pouvoir accader a splitting dans cette class
93}
94
96{
98 {
99 f << "{\n"
100 << " faisceau_tubes " << faisceau_ << "\n"
101 << " integrale_force_ " << integrale_force_ << "\n"
102 << " integrale_force_N_moins_1_ " << integrale_force_N_moins_1_ << "\n"
103 << "}\n";
104 }
105}
106
108{
109 const int n_tubes_total = faisceau_.size();
110 const double teta = 360./ n_P_;
111 const double Adim_P = 1. / ( 0.5 * rho_fluide_pour_adim_ * vitesse_pour_adim_ * vitesse_pour_adim_);
112 DoubleTab P_teta_Adim = pression_teta_;
113 P_teta_Adim *= Adim_P;
114
116 {
117 f.precision(17);
118 f.setf(std::ios_base::scientific);
119 //f << "P_Pa teta_Rad" << endl;
120 for (int itube = 0; itube < n_tubes_total; itube++)
121 for (int l = 0; l < n_P_; l++)
122 f << P_teta_Adim(itube, l) << " " << 180 - teta * l <<"\n" ;
123 }
124}
125
127{
128 Param param(que_suis_je());
129 param.ajouter("faisceau_tubes", &faisceau_);
130 param.ajouter("integrale_force_", &integrale_force_);
131 param.ajouter("integrale_force_N_moins_1_", &integrale_force_N_moins_1_);
132 param.lire_avec_accolades(fichier);
133}
134
135void Couplage_Tubes_IBC::force_ibc(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
136 const IJK_Field_double& rho_fluide_field,
137 const double timestep, const IJK_Field_double& pressure, double current_time)
138{
139 // ATTENTION update() est appele dans le run() avant force_ibc_velocity()
140 // donc quand on appelle force_ibc_velocity(), le timestep a change, c'est celui d'apres utilise dans update() au pas de temps d'avant
141 // Ex : on demarre au pas de temps n-1, on rentre ds le run(), on appelle d'abord update() donc on utilise timestep=t(n)-t(n-1)
142 // donc quand on entre dans force_ibc() on va calculer F_IBC(N) mais le pas de temps est toujours timestep=t(n)-t(n-1)
143 // ce qui permet de calculer d_integrale_force_ = ( F_IBC(N)-F_IBC(N-1) ) / timestep
144 // ensuite on passe au pas de temps suivant donc au pas de temps n et donc timestep=t(n+1)-t(n)
145 // on entre d'abord dans update() on peut donc calculer F_IBC_extrapole car on stocke d_integrale_force_ precedemment!
146
148
149 switch(champ_miroir_)
150 {
151 case PAS_MIROIR:
152
153 switch(solide_)
154 {
155 case CYLINDRE:
156
157 switch(methode_IBC_)
158 {
159 case IBC_DIFFUSE:
160
162 rho_fluide_field,
166 faisceau_);
167
168 break;
169 case IBC0:
170
171 force_ibc_velocity(vx, vy, vz,
172 rho_fluide_field,
176 faisceau_);
177
178
179 break;
180 default:
181 Cerr << "Erreur dans Couplage_Tubes_IBC::force_ibc: methode_IBC " << methode_IBC_ << " non code" << finl;
183 }
184
185 break;
186 case CUBE:
187
188 switch(methode_IBC_)
189 {
190
191 case IBC0:
192 ibc0_velocity_cube(vx, vy, vz,
193 rho_fluide_field,
197 faisceau_);
198
199
200 break;
201
202 case IBC_DIFFUSE:
203
204 ibc_diffuse_velocity_cube(vx, vy, vz,
205 rho_fluide_field,
209 faisceau_);
210
211
212 break;
213
214 case IBC_LOCALISEE:
216 rho_fluide_field,
220 faisceau_, current_time);
221
222 break;
223
224 case IBC_LOCALISEE_QDM:
226 rho_fluide_field,
230 faisceau_, current_time);
231
232 break;
233
234
235 default:
236 Cerr << "Erreur dans Couplage_Tubes_IBC::force_ibc: methode_IBC " << methode_IBC_ << " non code" << finl;
238 }
239 break;
240 default:
241 Cerr << "Erreur dans Couplage_Tubes_IBC::force_ibc: solide " << solide_ << " non code" << finl;
243 }
244
245 break;
246 case MIROIR:
247 force_ibc_velocity_miroir(vx, vy, vz,
248 rho_fluide_field,
252 faisceau_);
253 break;
254 case SYMETRIE_PLANE:
256 rho_fluide_field,
260 faisceau_);
261 break;
262 default:
263 Cerr << "Erreur dans Couplage_Tubes_IBC::force_ibc: champ_miroir " << champ_miroir_ << " non code" << finl;
265 }
266
267
268 // Calcul des forces de pression
269 //calcul_F_pression(pressure, vx, integrale_force_pression_, pression_teta_, faisceau_);
271
272 double inv_timestep = (1./timestep);
273 integrale_force_ *= inv_timestep;
274 // on calcule : ( F_IBC(N)-F_IBC(N-1) ) / timestep, ou timestep = t(n) - t(n-1)
275 // d_integrale_force_ = (integrale_force_ - integrale_force_N_moins_1_) * inv_timestep; mais si on ecrit comme ca en c++ ca plante
278 d_integrale_force_ *= inv_timestep;
279
280}
281
282
283/////////////////////////////////////////////////
284/// Calcul force ibc post projection
285//////////////////////////////////////////////////
286
287
288void Couplage_Tubes_IBC::calcul_force_post_projection(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
289 const IJK_Field_double& rho_fluide_field,
290 const double timestep, double current_time)
291{
292 // ATTENTION update() est appele dans le run() avant force_ibc_velocity()
293 // donc quand on appelle force_ibc_velocity(), le timestep a change, c'est celui d'apres utilise dans update() au pas de temps d'avant
294 // Ex : on demarre au pas de temps n-1, on rentre ds le run(), on appelle d'abord update() donc on utilise timestep=t(n)-t(n-1)
295 // donc quand on entre dans force_ibc() on va calculer F_IBC(N) mais le pas de temps est toujours timestep=t(n)-t(n-1)
296 // ce qui permet de calculer d_integrale_force_ = ( F_IBC(N)-F_IBC(N-1) ) / timestep
297 // ensuite on passe au pas de temps suivant donc au pas de temps n et donc timestep=t(n+1)-t(n)
298 // on entre d'abord dans update() on peut donc calculer F_IBC_extrapole car on stocke d_integrale_force_ precedemment!
299
301
302 switch(methode_IBC_)
303 {
304
305 case IBC0:
306 ibc0_force_cube(vx, vy, vz,
307 rho_fluide_field,
311 faisceau_);
312
313
314 break;
315
316 case IBC_DIFFUSE:
317
318 ibc_diffuse_force_cube(vx, vy, vz,
319 rho_fluide_field,
323 faisceau_);
324
325
326 break;
327# if 0
328 case IBC_LOCALISEE:
329 ibc_localisee_force_cube(vx, vy, vz,
330 rho_fluide_field,
334 faisceau_, current_time);
335
336 break;
337 case IBC_LOCALISEE_QDM:
339 rho_fluide_field,
343 faisceau_, current_time);
344
345 break;
346
347
348#endif
349 default:
350 Cerr << "Erreur dans Couplage_Tubes_IBC::force_ibc_post_proj: methode_IBC " << methode_IBC_ << " non code" << finl;
352 }
353
354 double inv_timestep = (1./timestep);
355 integrale_force_post_proj_ *= inv_timestep;
356 // on calcule : ( F_IBC(N)-F_IBC(N-1) ) / timestep, ou timestep = t(n) - t(n-1)
357 // d_integrale_force_ = (integrale_force_ - integrale_force_N_moins_1_) * inv_timestep; mais si on ecrit comme ca en c++ ca plante
360 d_integrale_force_post_proj_ *= inv_timestep;
361
362}
363
364
365
366/////////////////////////////
367//// calcul du champ miroir pour permettre de mieux calculer le RHS ensuite
368/////////////////////////////
369
370
371
372void Couplage_Tubes_IBC::champ_miroir(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
373 const IJK_Field_double& rho_fluide_field,
374 const double timestep, const IJK_Field_double& pressure)
375{
376
377 DoubleTab tmp_integrale_force = integrale_force_;
378 force_ibc_velocity_miroir(vx, vy, vz,
379 rho_fluide_field,
382 tmp_integrale_force,
383 faisceau_);
384 // le champ miroir est stocke dans velocity_tmp_
385
386}
387
388
389
390
391/////////////////////////
392//// forcage direct ordre 0
393////////////////////////////////
394
395void Couplage_Tubes_IBC::force_ibc_velocity(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
396 const IJK_Field_double& rho_fluide_field,
397 DoubleTab& masse_fluide_cylindres,
398 DoubleTab& volume_cylindres,
399 DoubleTab& integrale_force,
400 const Faisceau_Tubes& faisceau) const
401{
402 const Domaine_IJK& geom = vx.get_domaine();
403 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
404 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
405 {
406 for (int dir = 0; dir < 3; dir++)
407 {
408 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
409 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
410 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
411 for (int i = 0; i < n; i++)
412 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
413 }
414 }
415 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
416 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
417
418 const int ntubes = faisceau.size();
419 const double epsilon = epaisseur_lissage_ * geom.get_constant_delta(DIRECTION_I); // definition de la demi largeur du domaine d'etalement du terme de forcage comme un nombre de fois la largeur de maille selon la direction x
420
421 // Boucle sur les tubes du faisceau
422 for (int itube = 0; itube < ntubes; itube++)
423 {
424 const Tube_base& tube = faisceau[itube].valeur();
425 const double tube_r = tube.get_rayon();
426 const double omega = tube.get_omega();
427 const double r_tube_min = tube_r - epsilon;
428 const double r_tube_max = tube_r + epsilon; // rayon inf et max du domaine d'etalement du terme de forcage
429 const double r_tube_min_carre = r_tube_min * r_tube_min;
430 const double r_tube_max_carre = r_tube_max * r_tube_max;
431
432 const Vecteur3 position_cylindre = tube.get_current_pos();
433 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
434
435 // Boucle sur les trois composantes de qdm
436 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
437 {
438
439 const int ivoisin = (direction == 0) ? -1 : 0;
440 const int jvoisin = (direction == 1) ? -1 : 0;
441 const int kvoisin = (direction == 2) ? -1 : 0;
442
443 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
444 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
445 int imin = 0;
446 int jmin = 0;
447 int kmin = 0;
448 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
449 int jmax = velocity.nj();
450 int kmax = velocity.nk();
451 {
452 // restreint le domaine ijk balaye au domaine couvert par le cylindre:
453 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
454 const double xmin = position_cylindre[0] - (tube_r + epsilon); // on n'oublie pas que l'on doit chercher dans le domaine courvert par le cylindre + etalement
455 const double xmax = position_cylindre[0] + (tube_r + epsilon);
456 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
457 imin++;
458 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
459 imax--;
460 }
461 {
462 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
463 const double zmin = position_cylindre[2] - (tube_r + epsilon);
464 const double zmax = position_cylindre[2] + (tube_r + epsilon);
465 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
466 kmin++;
467 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
468 kmax--;
469 }
470
471 double delta_qdm_cylindre = 0.;
472 double masse_fluide = 0.; // Masse de fluide dans le cylindre
473 double volume = 0.;
474
475 for (int k = kmin; k < kmax; k++)
476 {
477 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
478 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
479 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
480 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
481 for (int j = jmin; j < jmax; j++)
482 {
483 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
484 for (int i = imin; i < imax; i++)
485 {
486 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
487 const double delta_x = x_coord - position_cylindre[0];
488 const double delta_z = z_coord - position_cylindre[2];
489 const double d2 = delta_x * delta_x + delta_z * delta_z;
490 const double d = sqrt(d2); // distance du point M au centre du tube
491 const double rayon_tube_carre = tube_r * tube_r;
492
493
494 double critere_max_carre, critere_min_carre;
495 switch(lissage_)
496 {
497 case PAS_ETALEMENT:
498 critere_max_carre = rayon_tube_carre;
499 critere_min_carre = rayon_tube_carre;
500 break;
501 case ETALEMENT:
502 critere_max_carre = r_tube_max_carre;
503 critere_min_carre = r_tube_min_carre;
504 break;
505 default:
506 critere_max_carre = rayon_tube_carre; // pour initialiser, pour le compilateur
507 critere_min_carre = rayon_tube_carre;
508 Cerr << "Erreur dans Couplage_Tubes_IBC::update: lissage " << lissage_ << " non code" << finl;
510 }
511
512 if (d2 < critere_max_carre)
513 {
514 Vecteur3 rotation;
515 rotation[0] = omega * (- delta_z);
516 rotation[1] = 0.;
517 rotation[2] = omega * delta_x;
518 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
519 double f_etalement;
520 if (d2 < critere_min_carre)
521 {
522 f_etalement = 1.;
523 }
524 else // si on a pas d2 < r_tube_min_carre alors d2 > r_tube_min_carre
525 {
526 //f_etalement = 0.5 - 0.5 * (d - tube_r) / epsilon - 0.5 / M_PI * sin( M_PI * (d - tube_r)/ epsilon); // pour d= tube_r la derive de f_etalement est de 1
527 f_etalement = 0.5 * ( 1 - tanh(4* (d - tube_r)/ epsilon) ) ; // pour d= tube_r la derive de f_etalement est de 10
528 }
529
530 double delta_v = f_etalement * (extrapolated_v - velocity(i,j,k)); // qdm ds le domaine d'etalement
531
532 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
533 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
534 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
535 velocity(i, j, k) = f_etalement * extrapolated_v + (1-f_etalement) * velocity(i, j, k); // forcage etale dans le domaine d'etalement de largeur 2 * epsilon
536 masse_fluide += volume_maille * rho_fluide;
537 volume += volume_maille;
538 }
539 }
540 }
541 }
542
543 integrale_force(itube, direction) = delta_qdm_cylindre;
544 masse_fluide_cylindres(itube, direction) = masse_fluide;
545 volume_cylindres(itube, direction) = volume;
546 }
547 }
548 mp_sum_for_each_item(integrale_force);
549 mp_sum_for_each_item(masse_fluide_cylindres);
550 mp_sum_for_each_item(volume_cylindres);
551}
552
553
554
555
556
557/////////////////////////
558//// forcage direct cylindre frac vol simplifie
559////////////////////////////////
560
561void Couplage_Tubes_IBC::force_ibc_velocity_frac_vol(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
562 const IJK_Field_double& rho_fluide_field,
563 DoubleTab& masse_fluide_cylindres,
564 DoubleTab& volume_cylindres,
565 DoubleTab& integrale_force,
566 const Faisceau_Tubes& faisceau) const
567{
568 const Domaine_IJK& geom = vx.get_domaine();
569 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
570 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
571 {
572 for (int dir = 0; dir < 3; dir++)
573 {
574 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
575 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
576 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
577 for (int i = 0; i < n; i++)
578 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
579 }
580 }
581 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
582 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
583
584 const int ntubes = faisceau.size();
585
586
587 // Boucle sur les tubes du faisceau
588 for (int itube = 0; itube < ntubes; itube++)
589 {
590 const Tube_base& tube = faisceau[itube].valeur();
591 const double tube_r = tube.get_rayon();
592 const double omega = tube.get_omega();
593
594
595 const Vecteur3 position_cylindre = tube.get_current_pos();
596 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
597
598 // Boucle sur les trois composantes de qdm
599 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
600 {
601
602 const int ivoisin = (direction == 0) ? -1 : 0;
603 const int jvoisin = (direction == 1) ? -1 : 0;
604 const int kvoisin = (direction == 2) ? -1 : 0;
605
606 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
607 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
608 int imin = 0;
609 int jmin = 0;
610 int kmin = 0;
611 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
612 int jmax = velocity.nj();
613 int kmax = velocity.nk();
614 // const double d_x = geom.get_constant_delta(0);
615 const double d_z = geom.get_constant_delta(2);
616 {
617 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
618 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
619 const double xmin = position_cylindre[0] - (tube_r + d_z); // on n'oublie pas que l'on doit chercher dans le domaine courverte par le cylindre + etalement
620 const double xmax = position_cylindre[0] + (tube_r + d_z);
621 //Cout << "xmin : " << xmin << " xmax : " << xmax<<finl;
622 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
623 imin++;
624 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
625 imax--;
626 }
627 {
628 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
629 const double zmin = position_cylindre[2] - (tube_r + d_z);
630 const double zmax = position_cylindre[2] + (tube_r + d_z);
631 //Cout << "zmin : " << zmin << " zmax : " << zmax<<finl;
632 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
633 kmin++;
634 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
635 kmax--;
636 }
637
638 double delta_qdm_cylindre = 0.;
639 double masse_fluide = 0.; // Masse de fluide dans le cylindre
640 double volume = 0.;
641 //Cout << "imin : " << imin << " imax : " << imax << " kmin : " << kmin << " kmax : " << kmax << " x_O : " << position_cylindre[0] << " z_O : " << position_cylindre[2] << finl;
642
643 for (int k = kmin; k <= kmax; k++)
644 {
645 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
646 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
647 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
648 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
649 for (int j = jmin; j < jmax; j++)
650 {
651 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
652 for (int i = imin; i <= imax; i++)
653 {
654 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
655 const double delta_x = x_coord - position_cylindre[0];
656 const double delta_z = z_coord - position_cylindre[2];
657 const double d2 = delta_x * delta_x + delta_z * delta_z;
658 const double d = sqrt(d2); // distance du point M au centre du tube
659
660
661 // attention on suppose que d_x = d_z !!
662 const double Borne_min = tube_r - d_z /2;
663 const double Borne_max = tube_r + d_z /2;
664
665 //Cout << "i : " << i << " j : " << j << " k : " << k << " dir : " << direction << " x_coord : " << x_coord << " z_coord : " ;
666 //Cout << z_coord << " d_OM : " << d << " velocity(i,j,k) : " << velocity(i,j,k) << " Borne_max : " << Borne_max << " Borne_min : " << Borne_min << " d_z/2 : " << d_z/2 << finl;
667
668
669 if (d <= Borne_max)
670 {
671 Vecteur3 rotation;
672 rotation[0] = omega * (- delta_z);
673 rotation[1] = 0.;
674 rotation[2] = omega * delta_x;
675 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
676 double f;
677 const double d_occupe = Borne_max - d;
678 if (d <= Borne_min)
679 f = 1.;
680 else
681 f = d_occupe / d_z ;
682 double delta_v_non_etale = extrapolated_v - velocity(i,j,k);
683 double delta_v = f * delta_v_non_etale; // qdm ds le domaine d'etalement
684 //Cout << " delta_v : " << delta_v << " extrapolated_v : " << extrapolated_v << " velocity(i,j,k) : " << velocity(i,j,k) << " f : " << f << " d_occupe : " << d_occupe << " delta_v_non_etale : " << delta_v_non_etale << finl;
685
686 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
687 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
688 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
689 velocity(i, j, k) = f * extrapolated_v + (1-f) * velocity(i, j, k); // forcage etale dans le domaine d'etalement de largeur 2 * epsilon
690 //Cout << " delta_qdm_cylindre : " << delta_qdm_cylindre << " volume_maille : " << volume_maille << " rho_fluide : " << rho_fluide << " velocity(i, j, k) : " << velocity(i, j, k) << finl;
691 masse_fluide += volume_maille * rho_fluide;
692 volume += volume_maille;
693 }
694 }
695 }
696 }
697
698 integrale_force(itube, direction) = delta_qdm_cylindre;
699 masse_fluide_cylindres(itube, direction) = masse_fluide;
700 volume_cylindres(itube, direction) = volume;
701 //Cout << " integrale_force(itube, direction) " << integrale_force(itube, direction) << " volume_cylindres(itube, direction) : " << volume_cylindres(itube, direction) << finl;
702 }
703 }
704 mp_sum_for_each_item(integrale_force);
705 mp_sum_for_each_item(masse_fluide_cylindres);
706 mp_sum_for_each_item(volume_cylindres);
707}
708
709
710
711
712/////////////////////////////
713//// forcer les mailles qui vont passer solide avt la conv + diff afin de ne pas avoir de saut en vitesse trop violent quand on fera le forcage derriere
714/////////////////////////////
715
716
717
718void Couplage_Tubes_IBC::forcage_anticipe(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
719 const IJK_Field_double& rho_fluide_field,
720 const double timestep, const IJK_Field_double& pressure)
721{
722
723 DoubleTab tmp_integrale_force = integrale_force_;
724 DoubleTab tmp_masse_fluide_cylindres = masse_fluide_cylindres_;
725 DoubleTab tmp_volume_cylindres = volume_cylindres_;
727 rho_fluide_field,
728 tmp_masse_fluide_cylindres,
729 tmp_volume_cylindres,
730 tmp_integrale_force,
731 faisceau_,
732 timestep);
733 // le champ miroir est stocke dans velocity_tmp_
734
735}
736
737//////////////
738/// forcage anticpe dans le cas du cube
739////////////////////
740void Couplage_Tubes_IBC::force_ibc_velocity_anticipe_cube(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
741 const IJK_Field_double& rho_fluide_field,
742 DoubleTab& masse_fluide_cylindres,
743 DoubleTab& volume_cylindres,
744 DoubleTab& integrale_force,
745 const Faisceau_Tubes& faisceau,
746 const double timestep) const
747{
748 Cout << "Fonction_anticipe" << finl;
749 const Domaine_IJK& geom = vx.get_domaine();
750 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
751 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
752 {
753 for (int dir = 0; dir < 3; dir++)
754 {
755 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
756 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
757 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
758 for (int i = 0; i < n; i++)
759 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
760 }
761 }
762 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
763 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
764
765 const int ntubes = faisceau.size();
766
767 // Boucle sur les tubes du faisceau
768 for (int itube = 0; itube < ntubes; itube++)
769 {
770 const Tube_base& tube = faisceau[itube].valeur();
771 const double omega = tube.get_omega();
772
773
774 const Vecteur3 position_cylindre = tube.get_current_pos();
775 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
776
777 // Boucle sur les trois composantes de qdm
778 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
779 {
780
781 const int ivoisin = (direction == 0) ? -1 : 0;
782 const int jvoisin = (direction == 1) ? -1 : 0;
783 const int kvoisin = (direction == 2) ? -1 : 0;
784
785 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
786 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
787 int imin = 0;
788 int jmin = 0;
789 int kmin = 0;
790 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
791 int jmax = velocity.nj();
792 int kmax = velocity.nk();
793 const double delta_x = geom.get_constant_delta(0);
794 const double delta_z = geom.get_constant_delta(2);
795
796 {
797 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
798 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
799 const double xmin = position_cylindre[0] - (L_cube_ + delta_x); // on n'oublie pas que l'on doit chercher dans le domaine courvert par le cylindre + etalement
800 const double xmax = position_cylindre[0] + (L_cube_ + delta_x);
801 Cout << "xmin : " << xmin << " xmax : " << xmax << finl;
802 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
803 imin++;
804 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
805 imax--;
806 }
807 {
808 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
809 const double zmin = position_cylindre[2] - (L_cube_ + delta_x);
810 const double zmax = position_cylindre[2] + (L_cube_ + delta_x);
811 Cout << "zmin : " << zmin << " zmax : " << zmax <<finl;
812 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
813 kmin++;
814 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
815 {
816 //Cout << "kmax : " << kmax << " z_coord[kmax + offset_k - 1] : " << z_coord[kmax + offset_k - 1] <<finl;
817 kmax--;
818 //Cout << "kmax : " << kmax << " z_coord[kmax + offset_k - 1] : " << z_coord[kmax + offset_k - 1] <<finl;
819 }
820 }
821 double delta_qdm_cylindre = 0.;
822 double masse_fluide = 0.; // Masse de fluide dans le cylindre
823 double volume = 0.;
824 Cout << "imin : " << imin << " imax : " << imax << " kmin : " << kmin << " kmax : " << kmax << " x_O : " << position_cylindre[0] << " z_O : " << position_cylindre[2] << finl;
825 for (int k = kmin; k <= kmax; k++)
826 {
827 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
828 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
829 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
830 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
831 for (int j = jmin; j < jmax; j++)
832 {
833 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
834 for (int i = imin; i <= imax; i++)
835 {
836 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
837 const double d_OM_x = x_coord - position_cylindre[0];
838 const double d_OM_z = z_coord - position_cylindre[2];
839 const double ABS_dOM_x = std::fabs(d_OM_x);
840 const double ABS_dOM_z = std::fabs(d_OM_z);
841 Cout << "i : " << i << " j : " << j << " k : " << k << " dir : " << direction << " x_coord : " << x_coord << " z_coord : ";
842 Cout << z_coord << " ABS_d_OM_x : " << ABS_dOM_x << " ABS_d_OM_z : " << ABS_dOM_z << " velocity(i,j,k) : " << velocity(i,j,k) << finl;
843 const double Borne_max = L_cube_;
844 Vecteur3 rotation;
845 rotation[0] = omega * (- delta_z);
846 rotation[1] = 0.;
847 rotation[2] = omega * delta_x;
848 const double vs_z = vitesse_cylindre[2] + rotation[2];
849 if ( vs_z >0)
850 {
851
852 if ((d_OM_z > Borne_max) && (ABS_dOM_x <= Borne_max+1e-10))
853 {
854 Cout << "vs_z > 0" << " i : " << i << " j : " << j << " k : " << k << " dir : " << direction << " x_coord : " << x_coord << " z_coord : " ;
855 Cout << z_coord <<" ABS_d_OM_x : " << ABS_dOM_x << " d_OM_z : " << d_OM_z << " velocity(i,j,k) : " << velocity(i,j,k)<< finl;
856
857 const double d_OM_L = d_OM_z - L_cube_;
858 const double dz = vs_z * timestep;
859 const double ABS_dz = std::fabs(dz);
860 Cout << "d_OM_L : " << d_OM_L << " dz : " << dz << " vs_z : " << vs_z << finl;
861 if ( d_OM_L <= ABS_dz )
862 {
863 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
864 //double extrapolated_v = velocity(i, j, k-1);
865 double delta_v = (extrapolated_v - velocity(i,j,k));
866 Cout << "On force la vitesse en prevision " << " delta_v : " << delta_v << " extrapolated_v : " << extrapolated_v << " velocity(i,j,k) : " << velocity(i,j,k) << finl;
867
868 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
869 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
870 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
871 Cout << " delta_qdm_cylindre : " << delta_qdm_cylindre << " volume_maille : " << volume_maille << finl;
872 velocity(i, j, k) = extrapolated_v; // forcage etale dans le domaine d'etalement de largeur 2 * epsilon
873 masse_fluide += volume_maille * rho_fluide;
874 volume += volume_maille;
875
876 }
877 }
878 }
879
880 if ( vs_z <0)
881 {
882
883 if ((-d_OM_z > Borne_max) && (ABS_dOM_x <= Borne_max+1e-10))
884 {
885 Cout << "vs_z < 0" << " i : " << i << " j : " << j << " k : " << k << " dir : " << direction << " x_coord : " << x_coord << " z_coord : ";
886 Cout<< z_coord <<" ABS_d_OM_x : " << ABS_dOM_x << " d_OM_z : " << d_OM_z << " velocity(i,j,k) : " << velocity(i,j,k) << finl;
887
888 const double d_OM_L = d_OM_z - L_cube_;
889 const double dz = vs_z * timestep;
890 const double ABS_dz = std::fabs(dz);
891 Cout << "d_OM_L : " << d_OM_L << " dz : " << dz << " vs_z : " << vs_z << finl;
892 if ( d_OM_L <= ABS_dz )
893 {
894 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
895 //double extrapolated_v = velocity(i, j, k-1);
896 double delta_v = (extrapolated_v - velocity(i,j,k));
897 Cout << "On force la vitesse en prevision " << " delta_v : " << delta_v << " extrapolated_v : " << extrapolated_v << " velocity(i,j,k) : " << velocity(i,j,k) << finl;
898
899 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
900 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
901 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
902 Cout << " delta_qdm_cylindre : " << delta_qdm_cylindre << " volume_maille : " << volume_maille << finl;
903 velocity(i, j, k) = extrapolated_v; // forcage etale dans le domaine d'etalement de largeur 2 * epsilon
904 masse_fluide += volume_maille * rho_fluide;
905 volume += volume_maille;
906
907 }
908 }
909
910 }
911
912
913 }
914 }
915 }
916
917 integrale_force(itube, direction) = delta_qdm_cylindre;
918 masse_fluide_cylindres(itube, direction) = masse_fluide;
919 volume_cylindres(itube, direction) = volume;
920 Cout << " integrale_force(itube, direction) " << integrale_force(itube, direction) << " volume_cylindres(itube, direction) : " << volume_cylindres(itube, direction) << finl;
921 }
922 }
923 mp_sum_for_each_item(integrale_force);
924 mp_sum_for_each_item(masse_fluide_cylindres);
925 mp_sum_for_each_item(volume_cylindres);
926}
927
928
929
930///////////////////////////////////////////////////////
931//////////////////////////////////////////////////////
932// CUBE
933// CUBE
934// CUBE
935/////////////////////////////////////////////////////
936////////////////////////////////////////////////////
937
938
939
940/////////////////////////
941//// IBC0 cube
942////////////////////////////////
943
944void Couplage_Tubes_IBC::ibc0_velocity_cube(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
945 const IJK_Field_double& rho_fluide_field,
946 DoubleTab& masse_fluide_cylindres,
947 DoubleTab& volume_cylindres,
948 DoubleTab& integrale_force,
949 const Faisceau_Tubes& faisceau) const
950{
951 const Domaine_IJK& geom = vx.get_domaine();
952 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
953 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
954 {
955 for (int dir = 0; dir < 3; dir++)
956 {
957 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
958 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
959 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
960 for (int i = 0; i < n; i++)
961 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
962 }
963 }
964 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
965 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
966
967 const int ntubes = faisceau.size();
968
969 // Boucle sur les tubes du faisceau
970 for (int itube = 0; itube < ntubes; itube++)
971 {
972 const Tube_base& tube = faisceau[itube].valeur();
973 const double omega = tube.get_omega();
974
975
976 const Vecteur3 position_cylindre = tube.get_current_pos();
977 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
978
979
980 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981 // Affichage de la vitesse predite
982 Cout << "v_predite : " << vx(64, 0, 73) << " " << vx(64, 0, 74) << " " <<vx(64, 0, 75) << " " <<vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
983 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984
985
986 // Boucle sur les trois composantes de qdm
987 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
988 {
989
990 const int ivoisin = (direction == 0) ? -1 : 0;
991 const int jvoisin = (direction == 1) ? -1 : 0;
992 const int kvoisin = (direction == 2) ? -1 : 0;
993
994 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
995 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
996 int imin = 0;
997 int jmin = 0;
998 int kmin = 0;
999 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
1000 int jmax = velocity.nj();
1001 int kmax = velocity.nk();
1002 const double delta_x = geom.get_constant_delta(0);
1003 const double delta_z = geom.get_constant_delta(2);
1004 {
1005 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
1006 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
1007 const double xmin = position_cylindre[0] - (L_cube_ + delta_x); // on n'oublie pas que l'on doit chercher dans la zone courverte par le cube
1008 const double xmax = position_cylindre[0] + (L_cube_ + delta_x);
1009
1010 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
1011 imin++;
1012 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
1013 imax--;
1014 }
1015 {
1016 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
1017 const double zmin = position_cylindre[2] - (L_cube_ + delta_z);
1018 const double zmax = position_cylindre[2] + (L_cube_ + delta_z);
1019
1020 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
1021 kmin++;
1022 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
1023 {
1024 kmax--;
1025 }
1026 }
1027 double delta_qdm_cylindre = 0.;
1028 double masse_fluide = 0.; // Masse de fluide dans le cylindre
1029 double volume = 0.;
1030
1031# if 0
1032 Cout << " " << finl;
1033 Cout << "dir : "<< direction << " x_O : " << position_cylindre[0] << " z_O : " << position_cylindre[2] << " V_maille : " << volume_maille << finl;
1034 Cout << " " << finl;
1035# endif
1036 for (int k = kmin; k <= kmax; k++)
1037 {
1038 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
1039 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
1040 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
1041 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
1042 for (int j = jmin; j < jmax; j++)
1043 {
1044 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
1045 for (int i = imin; i <= imax; i++)
1046 {
1047 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
1048 const double dOMx = x_coord - position_cylindre[0]; // distance du centre au point M selon x
1049 const double dOMz = z_coord - position_cylindre[2]; // distance du centre au point M selon z
1050 const double ABS_dOMx = std::fabs(dOMx);
1051 const double ABS_dOMz = std::fabs(dOMz);
1052 const double Borne_z = L_cube_;
1053 const double Borne_x = L_cube_;
1054
1055
1056 if ( (ABS_dOMx <= Borne_x) && (ABS_dOMz <= Borne_z))
1057 {
1058 Vecteur3 rotation;
1059 rotation[0] = omega * (- dOMz);
1060 rotation[1] = 0.;
1061 rotation[2] = omega * dOMx;
1062 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
1063 // on force la vitesse a la vitesse du cylindre car : d_OM <= R
1064 double delta_v = (extrapolated_v - velocity(i,j,k));
1065
1066# if 0
1067 Cout << "Forcage_interieur "<< "i : " << i << " j : " << j << " k : " << k << " x_M : " << x_coord << " z_M : " << z_coord << " v(i,j,k) : " << velocity(i,j,k) << finl;
1068# endif
1069 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
1070 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
1071 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
1072
1073# if 0
1074 Cout << "delta_v : "<< delta_v << " v_S : " << extrapolated_v << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << finl;
1075# endif
1076
1077 //# if 0
1078 // Sortie pour le cas ref de validation : cube de cote 22 mailles a Re10
1079 // evolution de la vitesse et qdm dans deux mailles : une sortante et une entrante
1080 if ( (direction==0) && ((j==0) && (i==64)) && ((k==54)|(k==55)|(k==76)|(k==77)) )
1081 {
1082 Cout << " " << finl;
1083 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1084 Cout << "v_ijk" << i << j << k << " : " << velocity(i,j,k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1085 Cout << " " << finl;
1086 }
1087 //# endif
1088
1089 velocity(i, j, k) = extrapolated_v; // v_F = v_S car on est dans le cube
1090 masse_fluide += volume_maille * rho_fluide;
1091 volume += volume_maille;
1092 }
1093 } // fin de la boucle en i
1094 }
1095 }
1096
1097 integrale_force(itube, direction) = delta_qdm_cylindre;
1098 masse_fluide_cylindres(itube, direction) = masse_fluide;
1099 volume_cylindres(itube, direction) = volume;
1100# if 0
1101 Cout << "integrale_force(itube, direction) " << integrale_force(itube, direction) << " V_S : " << volume_cylindres(itube, direction) << finl;
1102# endif
1103 }
1104
1105 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106 // Affichage de la vitesse imposee
1107 Cout << "v_imposee : " << vx(64, 0, 73) << " " << vx(64, 0, 74) << " " <<vx(64, 0, 75) << " " << vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1108 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109
1110 }
1111 mp_sum_for_each_item(integrale_force);
1112 mp_sum_for_each_item(masse_fluide_cylindres);
1113 mp_sum_for_each_item(volume_cylindres);
1114}
1115
1116//////////////////////////////
1117//// IBC ibc0 FORCE cube
1118///////////////////////////////////
1119
1120
1121
1122void Couplage_Tubes_IBC::ibc0_force_cube(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
1123 const IJK_Field_double& rho_fluide_field,
1124 DoubleTab& masse_fluide_cylindres,
1125 DoubleTab& volume_cylindres,
1126 DoubleTab& integrale_force,
1127 const Faisceau_Tubes& faisceau) const
1128{
1129 const Domaine_IJK& geom = vx.get_domaine();
1130 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
1131 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
1132 {
1133 for (int dir = 0; dir < 3; dir++)
1134 {
1135 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
1136 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
1137 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
1138 for (int i = 0; i < n; i++)
1139 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
1140 }
1141 }
1142 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
1143 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
1144
1145 const int ntubes = faisceau.size();
1146
1147 // Boucle sur les tubes du faisceau
1148 for (int itube = 0; itube < ntubes; itube++)
1149 {
1150 const Tube_base& tube = faisceau[itube].valeur();
1151 const double omega = tube.get_omega();
1152
1153
1154 const Vecteur3 position_cylindre = tube.get_current_pos();
1155 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
1156
1157 // Boucle sur les trois composantes de qdm
1158 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
1159 {
1160
1161 const int ivoisin = (direction == 0) ? -1 : 0;
1162 const int jvoisin = (direction == 1) ? -1 : 0;
1163 const int kvoisin = (direction == 2) ? -1 : 0;
1164
1165 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
1166 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
1167 int imin = 0;
1168 int jmin = 0;
1169 int kmin = 0;
1170 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
1171 int jmax = velocity.nj();
1172 int kmax = velocity.nk();
1173 const double delta_x = geom.get_constant_delta(0);
1174 const double delta_z = geom.get_constant_delta(2);
1175 {
1176 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
1177 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
1178 const double xmin = position_cylindre[0] - (L_cube_ + delta_x); // on n'oublie pas que l'on doit chercher dans la zone courverte par le cube
1179 const double xmax = position_cylindre[0] + (L_cube_ + delta_x);
1180
1181 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
1182 imin++;
1183 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
1184 imax--;
1185 }
1186 {
1187 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
1188 const double zmin = position_cylindre[2] - (L_cube_ + delta_z);
1189 const double zmax = position_cylindre[2] + (L_cube_ + delta_z);
1190
1191 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
1192 kmin++;
1193 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
1194 {
1195 kmax--;
1196 }
1197 }
1198 double delta_qdm_cylindre = 0.;
1199 double masse_fluide = 0.; // Masse de fluide dans le cylindre
1200 double volume = 0.;
1201
1202 for (int k = kmin; k <= kmax; k++)
1203 {
1204 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
1205 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
1206 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
1207 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
1208 for (int j = jmin; j < jmax; j++)
1209 {
1210 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
1211 for (int i = imin; i <= imax; i++)
1212 {
1213 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
1214 const double dOMx = x_coord - position_cylindre[0]; // distance du centre au point M selon x
1215 const double dOMz = z_coord - position_cylindre[2]; // distance du centre au point M selon z
1216 const double ABS_dOMx = std::fabs(dOMx);
1217 const double ABS_dOMz = std::fabs(dOMz);
1218 const double Borne_z = L_cube_;
1219 const double Borne_x = L_cube_;
1220
1221
1222 if ( (ABS_dOMx <= Borne_x) && (ABS_dOMz <= Borne_z))
1223 {
1224 Vecteur3 rotation;
1225 rotation[0] = omega * (- dOMz);
1226 rotation[1] = 0.;
1227 rotation[2] = omega * dOMx;
1228 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
1229 // on force la vitesse a la vitesse du cylindre car : d_OM <= R
1230 double delta_v = (extrapolated_v - velocity(i,j,k));
1231
1232 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
1233 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
1234 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
1235
1236 //# if 0
1237 // Sortie pour le cas ref de validation : cube de cote 22 mailles a Re10
1238 // evolution de la vitesse et qdm dans deux mailles : une sortante et une entrante
1239 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)) )
1240 {
1241 Cout << " " << finl;
1242 Cout << "qdm_ijk_post_proj" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1243 Cout << " " << finl;
1244 }
1245 //# endif
1246
1247 masse_fluide += volume_maille * rho_fluide;
1248 volume += volume_maille;
1249 }
1250 } // fin de la boucle en i
1251 }
1252 }
1253
1254 integrale_force(itube, direction) = delta_qdm_cylindre;
1255 masse_fluide_cylindres(itube, direction) = masse_fluide;
1256 volume_cylindres(itube, direction) = volume;
1257 }
1258 }
1259 mp_sum_for_each_item(integrale_force);
1260 mp_sum_for_each_item(masse_fluide_cylindres);
1261 mp_sum_for_each_item(volume_cylindres);
1262}
1263
1264/////////////////////////
1265//// IBC interface diffuse, une maille, Cube
1266////////////////////////////////
1267
1268void Couplage_Tubes_IBC::ibc_diffuse_velocity_cube(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
1269 const IJK_Field_double& rho_fluide_field,
1270 DoubleTab& masse_fluide_cylindres,
1271 DoubleTab& volume_cylindres,
1272 DoubleTab& integrale_force,
1273 const Faisceau_Tubes& faisceau) const
1274{
1275 const Domaine_IJK& geom = vx.get_domaine();
1276 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
1277 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
1278 {
1279 for (int dir = 0; dir < 3; dir++)
1280 {
1281 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
1282 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
1283 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
1284 for (int i = 0; i < n; i++)
1285 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
1286 }
1287 }
1288 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
1289 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
1290
1291 const int ntubes = faisceau.size();
1292
1293 // Boucle sur les tubes du faisceau
1294 for (int itube = 0; itube < ntubes; itube++)
1295 {
1296 const Tube_base& tube = faisceau[itube].valeur();
1297 const double omega = tube.get_omega();
1298
1299
1300 const Vecteur3 position_cylindre = tube.get_current_pos();
1301 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
1302
1303 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304 // Affichage de la vitesse predite
1305 Cout << "v_predite : " << vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1306 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1307
1308 // Boucle sur les trois composantes de qdm
1309 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
1310 {
1311
1312 const int ivoisin = (direction == 0) ? -1 : 0;
1313 const int jvoisin = (direction == 1) ? -1 : 0;
1314 const int kvoisin = (direction == 2) ? -1 : 0;
1315
1316 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
1317 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
1318 int imin = 0;
1319 int jmin = 0;
1320 int kmin = 0;
1321 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
1322 int jmax = velocity.nj();
1323 int kmax = velocity.nk();
1324 const double delta_x = geom.get_constant_delta(0);
1325 const double delta_z = geom.get_constant_delta(2);
1326 {
1327 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
1328 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
1329 const double xmin = position_cylindre[0] - (L_cube_ + delta_x); // on n'oublie pas que l'on doit chercher dans la zone courverte par le cube + une maille
1330 const double xmax = position_cylindre[0] + (L_cube_ + delta_x);
1331
1332 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
1333 imin++;
1334 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
1335 imax--;
1336 }
1337 {
1338 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
1339 const double zmin = position_cylindre[2] - (L_cube_ + delta_z);
1340 const double zmax = position_cylindre[2] + (L_cube_ + delta_z);
1341
1342 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
1343 kmin++;
1344 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
1345 {
1346 kmax--;
1347 }
1348 }
1349 double delta_qdm_cylindre = 0.;
1350 double masse_fluide = 0.; // Masse de fluide dans le cylindre
1351 double volume = 0.;
1352# if 0
1353 Cout << " " << finl;
1354 Cout << "dir : "<< direction << " x_O : " << position_cylindre[0] << " z_O : " << position_cylindre[2] << " V_maille : " << volume_maille << finl;
1355 Cout << " " << finl;
1356# endif
1357 for (int k = kmin; k <= kmax; k++)
1358 {
1359 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
1360 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
1361 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
1362 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
1363 for (int j = jmin; j < jmax; j++)
1364 {
1365 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
1366 for (int i = imin; i <= imax; i++)
1367 {
1368 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
1369 const double dOMx = x_coord - position_cylindre[0]; // distance du centre au point M selon x
1370 const double dOMz = z_coord - position_cylindre[2]; // distance du centre au point M selon z
1371 const double ABS_dOMx = std::fabs(dOMx);
1372 const double ABS_dOMz = std::fabs(dOMz);
1373 const double Borne_min_z = L_cube_ - delta_z/2;
1374 const double Borne_max_z = L_cube_ + delta_z/2;
1375 const double Borne_min_x = L_cube_ - delta_x/2;
1376 const double Borne_max_x = L_cube_ + delta_x/2;
1377
1378 if ( (ABS_dOMx <= Borne_max_x) && (ABS_dOMz <= Borne_max_z))
1379 {
1380 Vecteur3 rotation;
1381 rotation[0] = omega * (- dOMz);
1382 rotation[1] = 0.;
1383 rotation[2] = omega * dOMx;
1384 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
1385 double f_k;
1386 double f_i;
1387 double f_ik;
1388 const double d_k = Borne_max_z - ABS_dOMz; // distance occupee selon z dans la maille par le cube
1389 const double d_i = Borne_max_x - ABS_dOMx; // distance occupae selon x dans la maille par le cube
1390 if (( ABS_dOMx <= Borne_min_x) && ( ABS_dOMz <= Borne_min_z)) // alors le forcage est total : d_OM <= R - delta_z/2
1391 {
1392 f_i = 1.;
1393 f_k = 1.;
1394 }
1395 else if ( ABS_dOMx <= Borne_min_x) // vol de controle occupe en k
1396 {
1397 f_i = 1.;
1398 f_k = d_k / delta_z; // fraction volumique occupe
1399 }
1400 else if( ABS_dOMz <= Borne_min_z) // vol de controle occupe en i
1401 {
1402 f_i = d_i / delta_x; // fraction volumique occupe
1403 f_k = 1.;
1404 }
1405 else // vol de controle occupe en i et k
1406 {
1407 f_i = d_i / delta_x;
1408 f_k = d_k / delta_z;
1409 }
1410 f_ik = f_i * f_k; // frac volumique occupee
1411
1412# if 0
1413 Cout << "Forcage "<< "i : " << i << " j : " << j << " k : " << k << " x_M : " << x_coord << " z_M : " << z_coord << " v* : " ;
1414 Cout << velocity(i,j,k) << " f_k : " << f_k <<" f_i : " << f_i << " f_ik : " << f_ik << finl;
1415#endif
1416 double delta_v = f_ik * (extrapolated_v - velocity(i,j,k)); // qdm ds la zone d'etalement
1417 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
1418 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
1419 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
1420 //# if 0
1421 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
1422 // evolution de la qdm et dans deux mailles : une sortante et une entrante
1423 if ( (direction==0) && ((j==0) && (i==64)) && ((k==54)|(k==55)|(k==76)|(k==77)) )
1424 {
1425 Cout << " " << finl;
1426 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2] + L_cube_<< " frac_vol : " << f_ik * volume_maille << finl;
1427 Cout << "v_ijk" << i << j << k << " : " << velocity(i,j,k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2] + L_cube_<< finl;
1428 Cout << " " << finl;
1429 }
1430 //# endif
1431# if 0
1432 Cout << "delta_v : "<< delta_v << " v_S : " << extrapolated_v << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << " v_force : " << velocity(i, j, k) << finl;
1433# endif
1434 velocity(i, j, k) = f_ik * extrapolated_v + (1-f_ik) * velocity(i, j, k); // forcage proportionnel au vol de controle occupe
1435 masse_fluide += volume_maille * rho_fluide;
1436 volume += volume_maille;
1437 }
1438 } // fin de la boucle en i
1439 }
1440 }
1441
1442 integrale_force(itube, direction) = delta_qdm_cylindre;
1443 masse_fluide_cylindres(itube, direction) = masse_fluide;
1444 volume_cylindres(itube, direction) = volume;
1445# if 0
1446 Cout << "integrale_force(itube, direction) " << integrale_force(itube, direction) << " V_S : " << volume_cylindres(itube, direction) << finl;
1447# endif
1448 }
1449
1450 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1451 // Affichage de la vitesse imposee
1452 Cout << "v_imposee : " << vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1453 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1454
1455 } // fin boucle sur itube
1456 mp_sum_for_each_item(integrale_force);
1457 mp_sum_for_each_item(masse_fluide_cylindres);
1458 mp_sum_for_each_item(volume_cylindres);
1459}
1460
1461///////////////
1462///// force ibc_diffuse post proj
1463///////////////////////
1464
1465
1466void Couplage_Tubes_IBC::ibc_diffuse_force_cube(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
1467 const IJK_Field_double& rho_fluide_field,
1468 DoubleTab& masse_fluide_cylindres,
1469 DoubleTab& volume_cylindres,
1470 DoubleTab& integrale_force,
1471 const Faisceau_Tubes& faisceau) const
1472{
1473 const Domaine_IJK& geom = vx.get_domaine();
1474 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
1475 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
1476 {
1477 for (int dir = 0; dir < 3; dir++)
1478 {
1479 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
1480 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
1481 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
1482 for (int i = 0; i < n; i++)
1483 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
1484 }
1485 }
1486 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
1487 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
1488
1489 const int ntubes = faisceau.size();
1490
1491 // Boucle sur les tubes du faisceau
1492 for (int itube = 0; itube < ntubes; itube++)
1493 {
1494 const Tube_base& tube = faisceau[itube].valeur();
1495 const double omega = tube.get_omega();
1496
1497
1498 const Vecteur3 position_cylindre = tube.get_current_pos();
1499 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
1500
1501 // Boucle sur les trois composantes de qdm
1502 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
1503 {
1504
1505 const int ivoisin = (direction == 0) ? -1 : 0;
1506 const int jvoisin = (direction == 1) ? -1 : 0;
1507 const int kvoisin = (direction == 2) ? -1 : 0;
1508
1509 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
1510 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
1511 int imin = 0;
1512 int jmin = 0;
1513 int kmin = 0;
1514 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
1515 int jmax = velocity.nj();
1516 int kmax = velocity.nk();
1517 const double delta_x = geom.get_constant_delta(0);
1518 const double delta_z = geom.get_constant_delta(2);
1519 {
1520 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
1521 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
1522 const double xmin = position_cylindre[0] - (L_cube_ + delta_x); // on n'oublie pas que l'on doit chercher dans la zone courverte par le cube + une maille
1523 const double xmax = position_cylindre[0] + (L_cube_ + delta_x);
1524
1525 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
1526 imin++;
1527 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
1528 imax--;
1529 }
1530 {
1531 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
1532 const double zmin = position_cylindre[2] - (L_cube_ + delta_z);
1533 const double zmax = position_cylindre[2] + (L_cube_ + delta_z);
1534
1535 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
1536 kmin++;
1537 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
1538 {
1539 kmax--;
1540 }
1541 }
1542 double delta_qdm_cylindre = 0.;
1543 double masse_fluide = 0.; // Masse de fluide dans le cylindre
1544 double volume = 0.;
1545
1546 for (int k = kmin; k <= kmax; k++)
1547 {
1548 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
1549 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
1550 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
1551 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
1552 for (int j = jmin; j < jmax; j++)
1553 {
1554 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
1555 for (int i = imin; i <= imax; i++)
1556 {
1557 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
1558 const double dOMx = x_coord - position_cylindre[0]; // distance du centre au point M selon x
1559 const double dOMz = z_coord - position_cylindre[2]; // distance du centre au point M selon z
1560 const double ABS_dOMx = std::fabs(dOMx);
1561 const double ABS_dOMz = std::fabs(dOMz);
1562 const double Borne_min_z = L_cube_ - delta_z/2;
1563 const double Borne_max_z = L_cube_ + delta_z/2;
1564 const double Borne_min_x = L_cube_ - delta_x/2;
1565 const double Borne_max_x = L_cube_ + delta_x/2;
1566
1567 if ( (ABS_dOMx <= Borne_max_x) && (ABS_dOMz <= Borne_max_z))
1568 {
1569 Vecteur3 rotation;
1570 rotation[0] = omega * (- dOMz);
1571 rotation[1] = 0.;
1572 rotation[2] = omega * dOMx;
1573 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
1574 double f_k;
1575 double f_i;
1576 double f_ik;
1577 const double d_k = Borne_max_z - ABS_dOMz; // distance occupee selon z dans la maille par le cube
1578 const double d_i = Borne_max_x - ABS_dOMx; // distance occupae selon x dans la maille par le cube
1579 if (( ABS_dOMx <= Borne_min_x) && ( ABS_dOMz <= Borne_min_z)) // alors le forcage est total : d_OM <= R - delta_z/2
1580 {
1581 f_i = 1.;
1582 f_k = 1.;
1583 }
1584 else if ( ABS_dOMx <= Borne_min_x) // vol de controle occupe en k
1585 {
1586 f_i = 1.;
1587 f_k = d_k / delta_z; // fraction volumique occupe
1588 }
1589 else if( ABS_dOMz <= Borne_min_z) // vol de controle occupe en i
1590 {
1591 f_i = d_i / delta_x; // fraction volumique occupe
1592 f_k = 1.;
1593 }
1594 else // vol de controle occupe en i et k
1595 {
1596 f_i = d_i / delta_x;
1597 f_k = d_k / delta_z;
1598 }
1599 f_ik = f_i * f_k; // frac volumique occupee
1600 double delta_v = f_ik * (extrapolated_v - velocity(i,j,k)); // qdm ds la zone d'etalement
1601 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
1602 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
1603 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
1604 //# if 0
1605 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
1606 // evolution de la qdm et dans deux mailles : une sortante et une entrante
1607 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)) )
1608 {
1609 Cout << " " << finl;
1610 Cout << "qdm_ijk_post_proj" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2] + L_cube_<< " frac_vol : " << f_ik * volume_maille << finl;
1611 Cout << " " << finl;
1612 }
1613 //# endif
1614 masse_fluide += volume_maille * rho_fluide;
1615 volume += volume_maille;
1616 }
1617 } // fin de la boucle en i
1618 }
1619 }
1620
1621 integrale_force(itube, direction) = delta_qdm_cylindre;
1622 masse_fluide_cylindres(itube, direction) = masse_fluide;
1623 volume_cylindres(itube, direction) = volume;
1624 }
1625 } // fin boucle sur itube
1626 mp_sum_for_each_item(integrale_force);
1627 mp_sum_for_each_item(masse_fluide_cylindres);
1628 mp_sum_for_each_item(volume_cylindres);
1629}
1630
1631
1632
1633/////////////////////////
1634//// IBC interface localisee,forcage dans la couche limite sur une maille, Cube
1635////////////////////////////////
1636
1637void Couplage_Tubes_IBC::ibc_localisee_velocity_cube(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
1638 const IJK_Field_double& rho_fluide_field,
1639 DoubleTab& masse_fluide_cylindres,
1640 DoubleTab& volume_cylindres,
1641 DoubleTab& integrale_force,
1642 const Faisceau_Tubes& faisceau, double current_time) const
1643{
1644 const Domaine_IJK& geom = vx.get_domaine();
1645 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
1646 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
1647 {
1648 for (int dir = 0; dir < 3; dir++)
1649 {
1650 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
1651 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
1652 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
1653 for (int i = 0; i < n; i++)
1654 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
1655 }
1656 }
1657 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
1658 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
1659
1660 const int ntubes = faisceau.size();
1661
1662 // Boucle sur les tubes du faisceau
1663 for (int itube = 0; itube < ntubes; itube++)
1664 {
1665 const Tube_base& tube = faisceau[itube].valeur();
1666 const double omega = tube.get_omega();
1667
1668
1669 const Vecteur3 position_cylindre = tube.get_current_pos();
1670 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
1671
1672 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1673 // Affichage de la vitesse predite
1674 Cout << "v_predite : " << vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1675 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676
1677 DoubleTab v_predite;
1678
1679 // Boucle sur les trois composantes de qdm
1680 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
1681 {
1682
1683 const int ivoisin = (direction == 0) ? -1 : 0;
1684 const int jvoisin = (direction == 1) ? -1 : 0;
1685 const int kvoisin = (direction == 2) ? -1 : 0;
1686
1687 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
1688 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
1689 int imin = 0;
1690 int jmin = 0;
1691 int kmin = 0;
1692 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
1693 int jmax = velocity.nj();
1694 int kmax = velocity.nk();
1695 const double delta_x = geom.get_constant_delta(0);
1696 const double delta_z = geom.get_constant_delta(2);
1697 //const double d_x = geom.get_constant_delta(0);
1698 //const double d_z = geom.get_constant_delta(2);
1699
1700
1701 {
1702 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
1703 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
1704 const double xmin = position_cylindre[0] - (L_cube_ + 2 * delta_x); // on n'oublie pas que l'on doit chercher dans la zone courverte par le cube + deux mailles car pr le calcul de v ds la couche lim on a besoin de la vitesse au dessus
1705 const double xmax = position_cylindre[0] + (L_cube_ + 2 * delta_x);
1706
1707 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
1708 imin++;
1709 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
1710 imax--;
1711 }
1712 {
1713 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
1714 const double zmin = position_cylindre[2] - (L_cube_ + 2 * delta_z);
1715 const double zmax = position_cylindre[2] + (L_cube_ + 2 * delta_z);
1716
1717 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
1718 kmin++;
1719 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
1720 {
1721 kmax--;
1722 }
1723 }
1724 double delta_qdm_cylindre = 0.;
1725 double masse_fluide = 0.; // Masse de fluide dans le cylindre
1726 double volume = 0.;
1727# if 0
1728 Cout << " " << finl;
1729 Cout << "dir : "<< direction << " x_O : " << position_cylindre[0] << " z_O : " << position_cylindre[2] << " V_maille : " << volume_maille << finl;
1730 Cout << " " << finl;
1731# endif
1732
1733 // Calcul des bornes du tableau contenant les copies de v* dans le domaine ibc
1734 const int N_i = imax - imin + 1; // imin <= i <= imax, donc il y a imax - imin +1 valeurs de la vitesse selon i qu'on veut stocker
1735 const int N_j = jmax; // jmin = 0 <=j < jmax, donc il y a jmax -1 - 0 + 1 = jmax valeurs de la vitesse selon j que l'on veut stocker
1736 const int N_k = kmax - kmin + 1;
1737 v_predite.resize(3, N_i, N_j, N_k);
1738
1739 for (int k = kmin; k <= kmax; k++)
1740 {
1741 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
1742 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
1743 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
1744 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
1745 for (int j = jmin; j < jmax; j++)
1746 {
1747 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
1748 for (int i = imin; i <= imax; i++)
1749 {
1750 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
1751 const double dOMx = x_coord - position_cylindre[0];
1752 const double dOMz = z_coord - position_cylindre[2];
1753 const double ABS_dOMx = std::fabs(dOMx);
1754 const double ABS_dOMz = std::fabs(dOMz);
1755 const double Borne_min_z = L_cube_ - delta_z / 2; // d_OM <= L - delta_z/2 : v~* = v_s , qdm = rho * delta_v * V_maille
1756 const double Borne_intermediaire1_z = L_cube_ ; // L - delta_z/2 <= d_OM <= L : v~* = v_s , qdm = rho * delta_v * V_maille * f_k
1757 const double Borne_intermediaire2_z = L_cube_ + delta_z / 2; // L <= d_OM <= L + delta_z/2 : v~* = v_couche_limite, qdm = rho * delta_v * V_maille * f_k
1758 const double Borne_max_z = L_cube_ + delta_z ; // L + delta_z/2 <= d_OM <= L + delta_z : v~* = v_couche_limite, qdm = 0
1759 const double Borne_max_x = L_cube_;
1760
1761 v_predite(direction, i-imin, j, k-kmin) = velocity(i, j, k); // copie de la vitesse predite
1762
1763 if ( (ABS_dOMx <= Borne_max_x) && (ABS_dOMz <= Borne_max_z))
1764 {
1765 Vecteur3 rotation;
1766 rotation[0] = omega * (- dOMz);
1767 rotation[1] = 0.;
1768 rotation[2] = omega * dOMx;
1769 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
1770 double delta_v = 0.;
1771 double rho_fluide =0.;
1772 double d_k; // distance occupe dans le vol de controle
1773 double f_k; // frac vol occuope ds le vol de controle
1774 double v_k_exterieure; // necessaire au calcul de v_couche_limite
1775 double v_couche_limite;
1776 double d_Cube_M; // distance entre le cube et le point M, necessaire pr le calcul de v_couche_limite
1777
1778 if ( ABS_dOMz <= Borne_min_z) // d_OM <= L - delta_z/2 : v~* = v_s, qdm = rho * delta_v * V_maille
1779 {
1780 delta_v = extrapolated_v - velocity(i,j,k);
1781 rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // Calcul de rho sur la face: moyenne des rho sur les elements voisins (moy des deux cotes)
1782 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
1783
1784# if 0
1785 Cout << "Forcage_complet "<< "i : " << i << " j : " << j << " k : " << k << " x_M : " << x_coord << " z_M : " << z_coord << " v*(i,j,k) : " << velocity(i,j,k) << finl;
1786#endif
1787 //# if 0
1788 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
1789 // evolution de la qdm et de la vitesse dans deux mailles : une sortante et une entrante
1790 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)) )
1791 {
1792 Cout << " " << finl;
1793 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << " forcage_complet " << finl;
1794 Cout << "v_ijk" << i << j << k << " : " << velocity(i,j,k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << " forcage_complet " << finl;
1795 Cout << " " << finl;
1796 }
1797 //# endif
1798
1799 velocity(i, j, k) = extrapolated_v; // v~* = v_S car d_OM <=L
1800 masse_fluide += volume_maille * rho_fluide;
1801 volume += volume_maille;
1802
1803# if 0
1804 Cout << " delta_v : "<< delta_v << " v_S : " << extrapolated_v << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
1805# endif
1806 }
1807 else if ( ABS_dOMz <= Borne_intermediaire1_z) // L - delta_z/2 <= d_OM <= L : v~* = v_s, qdm = rho * delta_v * V_maille * f_k
1808 {
1809 d_k = L_cube_ + delta_z / 2 - ABS_dOMz; // distance occupee selon z dans le vol de controle par le cube
1810 f_k = d_k / delta_z; // fraction volumique occupe selon z, on a : 0.5 <= f_k <=1
1811 delta_v = f_k * (extrapolated_v - velocity(i,j,k)); // qdm prop au vol occupe dans le vol de controle
1812 rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // Calcul de rho sur la face: moyenne des rho sur les elements voisins (moy des deux cotes)
1813 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
1814
1815# if 0
1816 Cout << "Forcage_complet_qdm_partielle "<< "i : " << i << " j : " << j << " k : " << k;
1817 Cout << " x_M : " << x_coord << " z_M : " << z_coord << " v*(i,j,k) : " << velocity(i,j,k) << " f_k : " << f_k << finl;
1818#endif
1819 //# if 0
1820 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
1821 // evolution de la qdm dans deux mailles : une sortante et une entrante
1822 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)) )
1823 {
1824 Cout << " " << finl;
1825 Cout << "Forcage_complet_qdm_partielle "<< " v*(i,j,k) : " << velocity(i,j,k) << " f_k : " << f_k << " v_S : " << extrapolated_v << finl;
1826 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
1827 Cout << "v_ijk" << i << j << k << " : " << velocity(i,j,k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
1828 Cout << " " << finl;
1829 }
1830 //# endif
1831
1832 velocity(i, j, k) = extrapolated_v; // v~* = v_S car d_OM <=L
1833 masse_fluide += volume_maille * rho_fluide;
1834 volume += volume_maille;
1835
1836# if 0
1837 Cout << " delta_v : "<< delta_v << " v_S : " << extrapolated_v << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
1838# endif
1839 }
1840 else if ( ABS_dOMz <= Borne_intermediaire2_z) // L<= d_OM <= L + delta_z/2 : v~* = v_couche_limite, qdm = rho * delta_v * V_maille * f_k
1841 {
1842 d_k = L_cube_ + delta_z / 2 - ABS_dOMz; // distance occupee selon z dans le vol de controle par le cube
1843 f_k = d_k / delta_z; // fraction volumique occupe selon z, on a : 0. <= f_k <= 0.5
1844 double v_k_interieure; // necessaire au calcul de v_predite_interpollee pr le calcul de la qdm
1845 if ( dOMz > 0)
1846 {
1847 v_k_exterieure = velocity(i, j, k+1);
1848 v_k_interieure = v_predite(direction, i-imin, j, k- kmin - 1); // la vitesse predite en k-1 a ete force a v_s precedemment on doit donc prendre la copie stockee dans v_predite, pour i=imin on ne peut pas etre dans ce else if
1849
1850 }
1851 else
1852 {
1853 v_k_exterieure = velocity(i, j, k-1);
1854 v_k_interieure = v_predite(direction, i-imin, j, k- kmin + 1); // pour k=kmax, on ne peut pas se retrouver dans ce else if
1855 }
1856 double v_predite_interpollee_sur_la_frontiere = ((d_k + delta_z / 2) / delta_z) * ( velocity(i,j,k) - v_k_interieure ) + v_k_interieure; // On calcule un v* par interpol lineaire au niveau de la frontiere du cube
1857 delta_v = f_k * (extrapolated_v - v_predite_interpollee_sur_la_frontiere); // qdm prop au vol occupe dans le vol de controle
1858 rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // Calcul de rho sur la face: moyenne des rho sur les elements voisins (moy des deux cotes)
1859 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
1860
1861# if 0
1862 Cout << "Forcage_couche_limite_qdm_partielle "<< "i : " << i << " j : " << j << " k : " << k << " x_M : " << x_coord << " z_M : " << z_coord << " v*_int :" << v_k_interieure << " v*_S : ";
1863 Cout<< v_predite_interpollee_sur_la_frontiere << " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure << " f_k : " << f_k << " d_Cube_M : " << d_Cube_M << finl;
1864#endif
1865 d_Cube_M = ABS_dOMz - L_cube_; // distance entre M et le cube, 0 <= d_Cube_M <= delta_z / 2
1866 v_couche_limite = (d_Cube_M / (d_Cube_M + delta_z )) * ( v_k_exterieure - extrapolated_v ) + extrapolated_v;
1867
1868 //# if 0
1869 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
1870 // evolution de la qdm dans deux mailles : une sortante et une entrante
1871 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)) )
1872 {
1873 Cout << " " << finl;
1874 Cout << "Forcage_couche_limite_qdm_partielle "<< " v*_int :" << v_k_interieure << " v*_S : " << v_predite_interpollee_sur_la_frontiere << " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure;
1875 Cout << " f_k : " << f_k << " v_couche_limite : " << v_couche_limite << " v_S : " << extrapolated_v << " d_Cube_M : " << d_Cube_M << finl;
1876 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
1877 Cout << "v_ijk" << i << j << k << " : " << velocity(i, j, k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
1878 Cout << " " << finl;
1879 }
1880 //# endif
1881
1882 velocity(i, j, k) = v_couche_limite; // v~* = v_couche_limite car L<= d_OM <= L + delta_z/2
1883 masse_fluide += volume_maille * rho_fluide;
1884 volume += volume_maille;
1885
1886# if 0
1887 Cout << " delta_v : "<< delta_v << " v_S : " << extrapolated_v << " v_couche_limite : " << v_couche_limite << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
1888# endif
1889 }
1890
1891 else // L + delta_z/2 <= d_OM <= L + delta_z : v~* = v_couche_limite, qdm = 0
1892 {
1893 d_Cube_M = ABS_dOMz - L_cube_;
1894 if ( dOMz > 0)
1895 {
1896 v_k_exterieure = velocity(i, j, k+1);
1897 }
1898 else
1899 {
1900 v_k_exterieure = velocity(i, j, k-1);
1901 }
1902
1903# if 0
1904 Cout << "Forcage_couche_limite_qdm_0 "<< "i : " << i << " j : " << j << " k : " << k << " x_M : " << x_coord << " z_M : " << z_coord;
1905 Cout << " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure << " d_Cube_M: " << d_Cube_M << finl;
1906#endif
1907 v_couche_limite = (d_Cube_M / (d_Cube_M + delta_z )) * ( v_k_exterieure - extrapolated_v ) + extrapolated_v;
1908
1909 //# if 0
1910 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
1911 // evolution de la qdm dans deux mailles : une sortante et une entrante
1912 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)) )
1913 {
1914 Cout << " " << finl;
1915 Cout << "Forcage_couche_limite_qdm0 "<< " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure << " v_couche_limite : " << v_couche_limite << " v_S : " << extrapolated_v << " d_Cube_M : " << d_Cube_M << finl;
1916 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_O : " << position_cylindre[2] << finl;
1917 Cout << "v_ijk" << i << j << k << " : " << velocity(i, j, k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
1918 Cout << " " << finl;
1919 }
1920 //# endif
1921
1922 velocity(i, j, k) = v_couche_limite; // v~* = v_couche_limite car L + delta_z/2<= d_OM <= L
1923 masse_fluide += volume_maille * rho_fluide;
1924 volume += volume_maille;
1925# if 0
1926 Cout << " v_S : " << extrapolated_v << " v_couche_limite : " << v_couche_limite << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
1927# endif
1928 }
1929 } // fin de la boucle sur les 4 tests
1930 } // fin de la boucle en i
1931 }
1932 }
1933
1934 integrale_force(itube, direction) = delta_qdm_cylindre;
1935 masse_fluide_cylindres(itube, direction) = masse_fluide;
1936 volume_cylindres(itube, direction) = volume;
1937# if 0
1938 Cout << "integrale_force(itube, direction) " << integrale_force(itube, direction) << " V_S : " << volume_cylindres(itube, direction) << finl;
1939# endif
1940 }
1941 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1942 // Affichage de la vitesse imposee
1943 Cout << "v_imposee : " << vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1944 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1945
1946 }
1947 mp_sum_for_each_item(integrale_force);
1948 mp_sum_for_each_item(masse_fluide_cylindres);
1949 mp_sum_for_each_item(volume_cylindres);
1950}
1951
1952// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1953// Variante calcul qdm
1954//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1955
1956/////////////////////////
1957//// IBC interface localisee,forcage dans la couche limite sur une maille, Cube
1958////////////////////////////////
1959
1960void Couplage_Tubes_IBC::ibc_localisee_velocity_cube_qdm(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
1961 const IJK_Field_double& rho_fluide_field,
1962 DoubleTab& masse_fluide_cylindres,
1963 DoubleTab& volume_cylindres,
1964 DoubleTab& integrale_force,
1965 const Faisceau_Tubes& faisceau, double current_time) const
1966{
1967 const Domaine_IJK& geom = vx.get_domaine();
1968 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
1969 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
1970 {
1971 for (int dir = 0; dir < 3; dir++)
1972 {
1973 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
1974 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
1975 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
1976 for (int i = 0; i < n; i++)
1977 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
1978 }
1979 }
1980 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
1981 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
1982
1983 const int ntubes = faisceau.size();
1984
1985 // Boucle sur les tubes du faisceau
1986 for (int itube = 0; itube < ntubes; itube++)
1987 {
1988 const Tube_base& tube = faisceau[itube].valeur();
1989 const double omega = tube.get_omega();
1990
1991
1992 const Vecteur3 position_cylindre = tube.get_current_pos();
1993 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
1994
1995 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1996 // Affichage de la vitesse predite
1997 Cout << "v_predite : " << vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
1998 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1999
2000 DoubleTab v_predite;
2001
2002 // Boucle sur les trois composantes de qdm
2003 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
2004 {
2005
2006 const int ivoisin = (direction == 0) ? -1 : 0;
2007 const int jvoisin = (direction == 1) ? -1 : 0;
2008 const int kvoisin = (direction == 2) ? -1 : 0;
2009
2010 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
2011 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
2012 int imin = 0;
2013 int jmin = 0;
2014 int kmin = 0;
2015 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
2016 int jmax = velocity.nj();
2017 int kmax = velocity.nk();
2018 const double delta_x = geom.get_constant_delta(0);
2019 const double delta_z = geom.get_constant_delta(2);
2020 //const double d_x = geom.get_constant_delta(0);
2021 //const double d_z = geom.get_constant_delta(2);
2022
2023
2024 {
2025 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
2026 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
2027 const double xmin = position_cylindre[0] - (L_cube_ + 2 * delta_x); // on n'oublie pas que l'on doit chercher dans la zone courverte par le cube + deux mailles car pr le calcul de v ds la couche lim on a besoin de la vitesse au dessus
2028 const double xmax = position_cylindre[0] + (L_cube_ + 2 * delta_x);
2029
2030 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
2031 imin++;
2032 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
2033 imax--;
2034 }
2035 {
2036 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
2037 const double zmin = position_cylindre[2] - (L_cube_ + 2 * delta_z);
2038 const double zmax = position_cylindre[2] + (L_cube_ + 2 * delta_z);
2039
2040 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
2041 kmin++;
2042 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
2043 {
2044 kmax--;
2045 }
2046 }
2047 double delta_qdm_cylindre = 0.;
2048 double masse_fluide = 0.; // Masse de fluide dans le cylindre
2049 double volume = 0.;
2050# if 0
2051 Cout << " " << finl;
2052 Cout << "dir : "<< direction << " x_O : " << position_cylindre[0] << " z_O : " << position_cylindre[2] << " V_maille : " << volume_maille << finl;
2053 Cout << " " << finl;
2054# endif
2055
2056 // Calcul des bornes du tableau contenant les copies de v* dans le domaine ibc
2057 const int N_i = imax - imin + 1; // imin <= i <= imax, donc il y a imax - imin +1 valeurs de la vitesse selon i qu'on veut stocker
2058 const int N_j = jmax; // jmin = 0 <=j < jmax, donc il y a jmax -1 - 0 + 1 = jmax valeurs de la vitesse selon j que l'on veut stocker
2059 const int N_k = kmax - kmin + 1;
2060 v_predite.resize(3, N_i, N_j, N_k);
2061
2062
2063 double qdm_76=0;
2064 double qdm_77=0;
2065 double qdm_78=0;
2066 double qdm_tot=0;
2067 for (int k = kmin; k <= kmax; k++)
2068 {
2069 // si direction==DIRECTION_I alors x_ccord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
2070 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
2071 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
2072 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
2073 for (int j = jmin; j < jmax; j++)
2074 {
2075 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
2076 for (int i = imin; i <= imax; i++)
2077 {
2078 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
2079 const double dOMx = x_coord - position_cylindre[0];
2080 const double dOMz = z_coord - position_cylindre[2];
2081 const double ABS_dOMx = std::fabs(dOMx);
2082 const double ABS_dOMz = std::fabs(dOMz);
2083 const double Borne_min_z = L_cube_ - delta_z / 2; // d_OM <= L - delta_z/2 : v~* = v_s , qdm = rho * delta_v * V_maille
2084 const double Borne_intermediaire1_z = L_cube_ ; // L - delta_z/2 <= d_OM <= L : v~* = v_s , qdm = rho * delta_v * V_maille * f_k
2085 const double Borne_intermediaire2_z = L_cube_ + delta_z / 2; // L <= d_OM <= L + delta_z/2 : v~* = v_couche_limite, qdm = rho * delta_v * V_maille * f_k
2086 const double Borne_max_z = L_cube_ + delta_z ; // L + delta_z/2 <= d_OM <= L + delta_z : v~* = v_couche_limite, qdm = 0
2087 const double Borne_max_x = L_cube_;
2088
2089 v_predite(direction, i-imin, j, k-kmin) = velocity(i, j, k); // copie de la vitesse predite
2090
2091 if ( (ABS_dOMx <= Borne_max_x) && (ABS_dOMz <= Borne_max_z))
2092 {
2093 Vecteur3 rotation;
2094 rotation[0] = omega * (- dOMz);
2095 rotation[1] = 0.;
2096 rotation[2] = omega * dOMx;
2097 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
2098 double delta_v = 0.;
2099 double rho_fluide =0.;
2100 double d_k; // distance occupe dans le vol de controle
2101 double f_k; // frac vol occuope ds le vol de controle
2102 double v_k_exterieure; // necessaire au calcul de v_couche_limite
2103 double v_couche_limite;
2104 double d_Cube_M; // distance entre le cube et le point M, necessaire pr le calcul de v_couche_limite
2105
2106 if ( ABS_dOMz <= Borne_min_z) // d_OM <= L - delta_z/2 : v~* = v_s, qdm = rho * delta_v * V_maille
2107 {
2108 delta_v = extrapolated_v - velocity(i,j,k);
2109 rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // Calcul de rho sur la face: moyenne des rho sur les elements voisins (moy des deux cotes)
2110 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
2111
2112# if 0
2113 Cout << "Forcage_complet "<< "i : " << i << " j : " << j << " k : " << k << " x_M : " << x_coord << " z_M : " << z_coord << " v*(i,j,k) : " << velocity(i,j,k) << finl;
2114#endif
2115 //# if 0
2116 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
2117 // evolution de la qdm et de la vitesse dans deux mailles : une sortante et une entrante
2118 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)|(k==77)|(k==78)) )
2119 {
2120 Cout << " " << finl;
2121 if (k==76)
2122 {
2123 qdm_76 = delta_v* volume_maille * rho_fluide;
2124 }
2125 else if (k==77)
2126 {
2127 qdm_77 = delta_v* volume_maille * rho_fluide;
2128 }
2129 else if (k==78)
2130 {
2131 qdm_78 = delta_v* volume_maille * rho_fluide;
2132 }
2133 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << " forcage_complet " << finl;
2134 Cout << "v_ijk" << i << j << k << " : " << velocity(i,j,k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << " forcage_complet " << finl;
2135 Cout << " " << finl;
2136 }
2137 //# endif
2138
2139 velocity(i, j, k) = extrapolated_v; // v~* = v_S car d_OM <=L
2140 masse_fluide += volume_maille * rho_fluide;
2141 volume += volume_maille;
2142
2143# if 0
2144 Cout << " delta_v : "<< delta_v << " v_S : " << extrapolated_v << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
2145# endif
2146 }
2147 else if ( ABS_dOMz <= Borne_intermediaire1_z) // L - delta_z/2 <= d_OM <= L : v~* = v_s, qdm = rho * delta_v * V_maille * f_k
2148 {
2149 d_k = L_cube_ + delta_z / 2 - ABS_dOMz; // distance occupee selon z dans le vol de controle par le cube
2150 f_k = d_k / delta_z; // fraction volumique occupe selon z, on a : 0.5 <= f_k <=1
2151 delta_v = (extrapolated_v - velocity(i,j,k)); // qdm totale
2152 rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // Calcul de rho sur la face: moyenne des rho sur les elements voisins (moy des deux cotes)
2153 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
2154
2155# if 0
2156 Cout << "Forcage_complet_qdm_partielle "<< "i : " << i << " j : " << j << " k : " << k;
2157 Cout << " x_M : " << x_coord << " z_M : " << z_coord << " v*(i,j,k) : " << velocity(i,j,k) << " f_k : " << f_k << finl;
2158#endif
2159 //# if 0
2160 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
2161 // evolution de la qdm dans deux mailles : une sortante et une entrante
2162 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)|(k==77)|(k==78)) )
2163 {
2164 Cout << " " << finl;
2165 if (k==76)
2166 {
2167 qdm_76 = delta_v* volume_maille * rho_fluide;
2168 }
2169 else if (k==77)
2170 {
2171 qdm_77 = delta_v* volume_maille * rho_fluide;
2172 }
2173 else if (k==78)
2174 {
2175 qdm_78 = delta_v* volume_maille * rho_fluide;
2176 }
2177 Cout << "Forcage_complet_qdm_partielle "<< " v*(i,j,k) : " << velocity(i,j,k) << " f_k : " << f_k << " v_S : " << extrapolated_v << finl;
2178 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
2179 Cout << "v_ijk" << i << j << k << " : " << velocity(i,j,k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
2180 Cout << " " << finl;
2181 }
2182 //# endif
2183
2184 velocity(i, j, k) = extrapolated_v; // v~* = v_S car d_OM <=L
2185 masse_fluide += volume_maille * rho_fluide;
2186 volume += volume_maille;
2187
2188# if 0
2189 Cout << " delta_v : "<< delta_v << " v_S : " << extrapolated_v << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
2190# endif
2191 }
2192 else if ( ABS_dOMz <= Borne_intermediaire2_z) // L<= d_OM <= L + delta_z/2 : v~* = v_couche_limite, qdm = rho * delta_v * V_maille * f_k
2193 {
2194 d_k = L_cube_ + delta_z / 2 - ABS_dOMz; // distance occupee selon z dans le vol de controle par le cube
2195 f_k = d_k / delta_z; // fraction volumique occupe selon z, on a : 0. <= f_k <= 0.5
2196
2197 if ( dOMz > 0)
2198 {
2199 v_k_exterieure = velocity(i, j, k+1);
2200 }
2201 else
2202 {
2203 v_k_exterieure = velocity(i, j, k-1);
2204 }
2205# if 0
2206 Cout << "Forcage_couche_limite_qdm_partielle "<< "i : " << i << " j : " << j << " k : " << k << " x_M : " << x_coord << " z_M : " << z_coord << " v*_int :" << v_k_interieure << " v*_S : ";
2207 Cout << v_predite_interpollee_sur_la_frontiere << " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure << " f_k : " << f_k << " d_Cube_M : " << d_Cube_M << finl;
2208#endif
2209 d_Cube_M = ABS_dOMz - L_cube_; // distance entre M et le cube, 0 <= d_Cube_M <= delta_z / 2
2210 v_couche_limite = (d_Cube_M / (d_Cube_M + delta_z )) * ( v_k_exterieure - extrapolated_v ) + extrapolated_v;
2211 delta_v = (v_couche_limite -velocity(i, j, k) ); // qdm totale
2212 rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // Calcul de rho sur la face: moyenne des rho sur les elements voisins (moy des deux cotes)
2213 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
2214
2215 //# if 0
2216 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
2217 // evolution de la qdm dans deux mailles : une sortante et une entrante
2218 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)|(k==77)|(k==78)) )
2219 {
2220 Cout << " " << finl;
2221 if (k==76)
2222 {
2223 qdm_76 = delta_v* volume_maille * rho_fluide;
2224 }
2225 else if (k==77)
2226 {
2227 qdm_77 = delta_v* volume_maille * rho_fluide;
2228 }
2229 else if (k==78)
2230 {
2231 qdm_78 = delta_v* volume_maille * rho_fluide;
2232 }
2233 Cout << "Forcage_couche_limite_qdm_partielle "<< " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure << " f_k : " << f_k << " v_couche_limite : " << v_couche_limite << " v_S : " << extrapolated_v << " d_Cube_M : " << d_Cube_M << finl;
2234 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
2235 Cout << "v_ijk" << i << j << k << " : " << velocity(i, j, k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
2236 Cout << " " << finl;
2237 }
2238 //# endif
2239
2240 velocity(i, j, k) = v_couche_limite; // v~* = v_couche_limite car L<= d_OM <= L + delta_z/2
2241 masse_fluide += volume_maille * rho_fluide;
2242 volume += volume_maille;
2243
2244# if 0
2245 Cout << " delta_v : "<< delta_v << " v_S : " << extrapolated_v << " v_couche_limite : " << v_couche_limite << " qdm : " << delta_v * volume_maille * rho_fluide << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
2246# endif
2247 }
2248
2249 else // L + delta_z/2 <= d_OM <= L + delta_z : v~* = v_couche_limite, qdm = 0
2250 {
2251 d_Cube_M = ABS_dOMz - L_cube_;
2252 if ( dOMz > 0)
2253 {
2254 v_k_exterieure = velocity(i, j, k+1);
2255 }
2256 else
2257 {
2258 v_k_exterieure = velocity(i, j, k-1);
2259 }
2260
2261# if 0
2262 Cout << "Forcage_couche_limite_qdm_0 "<< "i : " << i << " j : " << j << " k : " << k;
2263 Cout << " x_M : " << x_coord << " z_M : " << z_coord << " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure << " d_Cube_M: " << d_Cube_M << finl;
2264#endif
2265 v_couche_limite = (d_Cube_M / (d_Cube_M + delta_z )) * ( v_k_exterieure - extrapolated_v ) + extrapolated_v;
2266 delta_v = (v_couche_limite - velocity(i, j, k)); // qdm totale
2267 rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // Calcul de rho sur la face: moyenne des rho sur les elements voisins (moy des deux cotes)
2268 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
2269
2270 //# if 0
2271 // Sortie pour le cas ref de validation avec translation selon z : cube de cote 22 mailles a Re10
2272 // evolution de la qdm dans deux mailles : une sortante et une entrante
2273 if ( (direction==0) && ((j==0) && (i==64)) && ((k==55)|(k==76)|(k==77)|(k==78)) )
2274 {
2275 Cout << " " << finl;
2276 if (k==76)
2277 {
2278 qdm_76 = delta_v* volume_maille * rho_fluide;
2279 }
2280 else if (k==77)
2281 {
2282 qdm_77 = delta_v* volume_maille * rho_fluide;
2283 }
2284 else if (k==78)
2285 {
2286 qdm_78 = delta_v* volume_maille * rho_fluide;
2287 }
2288 Cout << "Forcage_couche_limite_qdm0 "<< " v*(i,j,k) : " << velocity(i,j,k) << " v*_ext :" << v_k_exterieure << " v_couche_limite : " << v_couche_limite << " v_S : " << extrapolated_v << " d_Cube_M : " << d_Cube_M << finl;
2289 Cout << "qdm_ijk" << i << j << k << " : " << delta_v * volume_maille * rho_fluide << " x_M : " << x_coord << " z_M : " << z_coord << " z_O : " << position_cylindre[2]+L_cube_ << finl;
2290 Cout << "v_ijk" << i << j << k << " : " << velocity(i, j, k) << " x_M : " << x_coord << " z_M : " << z_coord << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
2291 Cout << " " << finl;
2292 }
2293 //# endif
2294
2295 velocity(i, j, k) = v_couche_limite; // v~* = v_couche_limite car L + delta_z/2<= d_OM <= L
2296 masse_fluide += volume_maille * rho_fluide;
2297 volume += volume_maille;
2298# if 0
2299 Cout << " v_S : " << extrapolated_v << " v_couche_limite : " << v_couche_limite << " qdm_cube : " << delta_qdm_cylindre << " v~*(i,j,k) : " << velocity(i, j, k) << finl;
2300# endif
2301 }
2302 } // fin de la boucle sur les 4 tests
2303 } // fin de la boucle en i
2304 }
2305 }
2306 if (direction==0)
2307 {
2308 qdm_tot = qdm_76 + qdm_77 + qdm_78;
2309 Cout << "qdm_tot : " << qdm_tot << " z_interface : " << position_cylindre[2]+L_cube_ << finl;
2310 }
2311 integrale_force(itube, direction) = delta_qdm_cylindre;
2312 masse_fluide_cylindres(itube, direction) = masse_fluide;
2313 volume_cylindres(itube, direction) = volume;
2314# if 0
2315 Cout << "integrale_force(itube, direction) " << integrale_force(itube, direction) << " V_S : " << volume_cylindres(itube, direction) << finl;
2316# endif
2317 }
2318 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2319 // Affichage de la vitesse imposee
2320 Cout << "v_imposee : " << vx(64, 0, 76) << " z_interface : " << position_cylindre[2] + L_cube_ << finl;
2321 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2322
2323 }
2324 mp_sum_for_each_item(integrale_force);
2325 mp_sum_for_each_item(masse_fluide_cylindres);
2326 mp_sum_for_each_item(volume_cylindres);
2327}
2328
2329
2330void interpoler_vitesses_xz(const DoubleTab& coords, DoubleTab& vitesses_interpolees,
2331 const IJK_Field_double& vx,
2332 const IJK_Field_double& vz,
2333 ArrOfDouble& result)
2334{
2335 int i;
2336 const int n = coords.dimension(0);
2337 vitesses_interpolees.resize(n,3);
2338 ijk_interpolate(vx, coords, result);
2339 for (i = 0; i < n; i++)
2340 vitesses_interpolees(i,0)=result[i];
2341 for (i = 0; i < n; i++)
2342 vitesses_interpolees(i,1)=0.;
2343 ijk_interpolate(vz, coords, result);
2344 for (i = 0; i < n; i++)
2345 vitesses_interpolees(i,2)=result[i];
2346}
2347
2348
2349//////////////////////////////////////////////////////////////////////////
2350/// fonction_ibc pour faire le champ miroir
2351//////////////////////////////////////////////////////////////////////////
2352void Couplage_Tubes_IBC::force_ibc_velocity_symetrie_plane(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
2353 const IJK_Field_double& rho_fluide_field,
2354 DoubleTab& masse_fluide_cylindres,
2355 DoubleTab& volume_cylindres,
2356 DoubleTab& integrale_force,
2357 const Faisceau_Tubes& faisceau) const
2358{
2359 const Domaine_IJK& geom = vx.get_domaine();
2360 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
2361 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
2362 {
2363 for (int dir = 0; dir < 3; dir++)
2364 {
2365 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
2366 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
2367 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
2368 for (int i = 0; i < n; i++)
2369 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
2370 }
2371 }
2372 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
2373 const int offset_j = geom.get_offset_local(DIRECTION_J); // donne l'offset selon la direction k
2374 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
2375
2376 const int ntubes = faisceau.size();
2377 const double h_maillage = geom.get_constant_delta(DIRECTION_I);
2378
2379 const double epsilon = epaisseur_lissage_ * h_maillage; // definition de la demi largeur de la zone d'etalement du terme de forcage comme un nombre de fois la largeur de maille selon la direction x
2380
2381 DoubleTab coords(1,3); // tableau temporaire ou on stocke les coordonnees des points ou on veut interpoler la vitesse
2382 DoubleTab vitesses_interpolees(1,3);
2383 ArrOfDouble result(1); // tableau temporaire ou la fonction interpolation stocke le resultat
2384 // Boucle sur les tubes du faisceau
2385 for (int itube = 0; itube < ntubes; itube++)
2386 {
2387 const Tube_base& tube = faisceau[itube].valeur();
2388 const double tube_r = tube.get_rayon();
2389 const double r_tube_min = tube_r - epsilon;
2390 //const double r_tube_min_carre = r_tube_min * r_tube_min;
2391
2392 const Vecteur3 position_cylindre = tube.get_current_pos();
2393 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
2394
2395 // Boucle sur les trois composantes de qdm
2396 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
2397 {
2398
2399 const int ivoisin = (direction == 0) ? -1 : 0;
2400 const int jvoisin = (direction == 1) ? -1 : 0;
2401 const int kvoisin = (direction == 2) ? -1 : 0;
2402 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
2403 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
2404 int imin = 0;
2405 int jmin = 0;
2406 int kmin = 0;
2407 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
2408 int jmax = velocity.nj();
2409 int kmax = velocity.nk();
2410 {
2411 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
2412 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
2413 const double xmin = position_cylindre[0] - (tube_r + epsilon); // on n'oublie pas que l'on doit chercher dans la zone couverte par le cylindre + etalement
2414 const double xmax = position_cylindre[0] + (tube_r + epsilon);
2415 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
2416 imin++;
2417 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
2418 imax--;
2419 }
2420 {
2421 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
2422 const double zmin = position_cylindre[2] - (tube_r + epsilon);
2423 const double zmax = position_cylindre[2] + (tube_r + epsilon);
2424 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
2425 kmin++;
2426 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
2427 kmax--;
2428 }
2429
2430 double delta_qdm_cylindre = 0.;
2431 double masse_fluide = 0.; // Masse de fluide dans le cylindre
2432 double volume = 0.;
2433
2434 for (int k = kmin; k < kmax; k++)
2435 {
2436 // si direction==DIRECTION_I alors x_coord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
2437 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
2438 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
2439 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
2440 for (int j = jmin; j < jmax; j++)
2441 {
2442 const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
2443 for (int i = imin; i < imax; i++)
2444 {
2445 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
2446 const double delta_x = x_coord - position_cylindre[0]; // x_M - x_0
2447 const double delta_z = z_coord - position_cylindre[2]; // z_M - z_0
2448 const double d2 = delta_x * delta_x + delta_z * delta_z;
2449 const double d = sqrt(d2); // distance du point M au centre du tube
2450
2451 // foraage si on est dans le cylindre
2452 if (d < tube_r && d > r_tube_min)
2453 {
2454 // deuxieme essai: vitesse tangentielle egale a la vitesse tangentielle a la surface du cylindre
2455 // vitesse normale nulle a l'interface, extrapolation a l'interieur du cylindre pour que
2456 // div(u) = 0 (en fonction du gradient de vitesse tangentielle)
2457
2458 if (direction == DIRECTION_J)
2459 {
2460 // pas de forcage dans la direction j
2461 }
2462 else
2463 {
2464 //const double beta = tube_r / d;
2465 //const double delta_x_P = beta * delta_x; // x_P - x_0
2466 //const double delta_z_P = beta * delta_z; // z_P _ z_0
2467 Vecteur3 normale;
2468 normale[0] = delta_x / d;
2469 normale[1] = 0.;
2470 normale[2] = delta_z / d;
2471 Vecteur3 tangente;
2472 tangente[0] = - normale[2];
2473 tangente[1] = 0.;
2474 tangente[2] = normale[0];
2475
2476 coords.resize(3,3);
2477 const double rr = tube_r * tube_r / d;
2478 coords(0,0) = position_cylindre[0] + normale[0] * rr;
2479 coords(0,1) = y_coord;
2480 coords(0,2) = position_cylindre[2] + normale[2] * rr;
2481
2482 coords(1,0) = x_coord;
2483 coords(1,1) = y_coord;
2484 coords(1,2) = z_coord;
2485
2486 coords(2,0) = position_cylindre[0] + normale[0] * tube_r;
2487 coords(2,1) = y_coord;
2488 coords(2,2) = position_cylindre[2] + normale[2] * tube_r;
2489
2490 int l, m;
2491 interpoler_vitesses_xz(coords, vitesses_interpolees, vx, vz, result);
2492 for (l = 0; l < 3; l++)
2493 for (m = 0; m < 3; m++)
2494 vitesses_interpolees(l,m) -= vitesse_cylindre[m];
2495
2496 // Composante normale = oppose de la composante normale au symetrique
2497 // Composante tangentielle: on freine, un peu
2498 double compo_normale = 0;
2499 for (l = 0; l < 3; l++)
2500 compo_normale += (- vitesses_interpolees(0,l)*rr/d - vitesses_interpolees(1,l)) * normale[l];
2501 double compo_tan = 0;
2502 for (l = 0; l < 3; l++)
2503 compo_tan += (vitesses_interpolees(2,l) * (1 - 4*(tube_r - d) / tube_r) - vitesses_interpolees(1,l)) * tangente[l];
2504 // Regularisation du terme de forcage:
2505 double facteur = 1;
2506 if (tube_r - d < h_maillage)
2507 facteur = (tube_r - d) / h_maillage;
2508 if (d - r_tube_min < h_maillage)
2509 facteur = (d - r_tube_min) / h_maillage;
2510
2511 velocity(i, j, k) += (compo_normale * normale[direction] + compo_tan * tangente[direction]) * facteur;
2512
2513 }
2514 }
2515 else
2516 {
2517 // pas de champ miroir forcage direct classique
2518 }
2519
2520 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
2521 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
2522 //delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
2523 masse_fluide += volume_maille * rho_fluide;
2524 volume += volume_maille;
2525 }
2526 }
2527 }
2528
2529 integrale_force(itube, direction) = delta_qdm_cylindre;
2530 masse_fluide_cylindres(itube, direction) = masse_fluide;
2531 volume_cylindres(itube, direction) = volume;
2532 }
2533 }
2534 mp_sum_for_each_item(integrale_force);
2535 mp_sum_for_each_item(masse_fluide_cylindres);
2536 mp_sum_for_each_item(volume_cylindres);
2537}
2538
2539void Couplage_Tubes_IBC::force_ibc_velocity_miroir(IJK_Field_double& vx, IJK_Field_double& vy, IJK_Field_double& vz,
2540 const IJK_Field_double& rho_fluide_field,
2541 DoubleTab& masse_fluide_cylindres,
2542 DoubleTab& volume_cylindres,
2543 DoubleTab& integrale_force,
2544 const Faisceau_Tubes& faisceau) const
2545{
2546 const Domaine_IJK& geom = vx.get_domaine();
2547 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
2548 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
2549 {
2550 for (int dir = 0; dir < 3; dir++)
2551 {
2552 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
2553 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
2554 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
2555 for (int i = 0; i < n; i++)
2556 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
2557 }
2558 }
2559 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
2560 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
2561
2562 const int ntubes = faisceau.size();
2563 const double epsilon = epaisseur_lissage_ * geom.get_constant_delta(DIRECTION_I); // definition de la demi largeur de la zone d'etalement du terme de forcage comme un nombre de fois la largeur de maille selon la direction x
2564
2565 // Boucle sur les tubes du faisceau
2566 for (int itube = 0; itube < ntubes; itube++)
2567 {
2568 const Tube_base& tube = faisceau[itube].valeur();
2569 const double tube_r = tube.get_rayon();
2570 const double omega = tube.get_omega();
2571 const double r_tube_min = tube_r - epsilon;
2572 const double r_tube_min_carre = r_tube_min * r_tube_min;
2573
2574 const Vecteur3 position_cylindre = tube.get_current_pos();
2575 const Vecteur3 vitesse_cylindre = tube.get_current_velocity();
2576
2577 // Boucle sur les trois composantes de qdm
2578 for (int direction = 0; direction < 3; direction++) // boucle sur les 3 directions de la vitesse
2579 {
2580
2581 const int ivoisin = (direction == 0) ? -1 : 0;
2582 const int jvoisin = (direction == 1) ? -1 : 0;
2583 const int kvoisin = (direction == 2) ? -1 : 0;
2584
2585 const double volume_maille = geom.get_constant_delta(0) * geom.get_constant_delta(1) * geom.get_constant_delta(2); //donne le volume de la maille
2586 const double inv_delta_x = 1. / geom.get_constant_delta(0); // inverse de la taille de la maille selon x
2587 const double inv_delta_z = 1. / geom.get_constant_delta(2);
2588 IJK_Field_double& velocity = select_dir(direction, vx, vy, vz); // velocity est egale a la vitesse selon la direction 0,1 ou 2
2589 int imin = 0;
2590 int jmin = 0;
2591 int kmin = 0;
2592 int imax = velocity.ni(); // donne le nombre de valeur de la vitesse selon i
2593 int jmax = velocity.nj();
2594 int kmax = velocity.nk();
2595 {
2596 // restreint le domaine ijk balaye a la zone couverte par le cylindre:
2597 const ArrOfDouble& x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I] : elem_pos[DIRECTION_I];
2598 const double xmin = position_cylindre[0] - (tube_r + epsilon); // on n'oublie pas que l'on doit chercher dans la zone couverte par le cylindre + etalement
2599 const double xmax = position_cylindre[0] + (tube_r + epsilon);
2600 while (imin < velocity.ni() && x_coord[imin + offset_i] < xmin)
2601 imin++;
2602 while (imax > 0 && x_coord[imax + offset_i - 1] > xmax)
2603 imax--;
2604 }
2605 {
2606 const ArrOfDouble& z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K] : elem_pos[DIRECTION_K];
2607 const double zmin = position_cylindre[2] - (tube_r + epsilon);
2608 const double zmax = position_cylindre[2] + (tube_r + epsilon);
2609 while (kmin < velocity.nk() && z_coord[kmin + offset_k] < zmin)
2610 kmin++;
2611 while (kmax > 0 && z_coord[kmax + offset_k - 1] > zmax)
2612 kmax--;
2613 }
2614
2615 double delta_qdm_cylindre = 0.;
2616 double masse_fluide = 0.; // Masse de fluide dans le cylindre
2617 double volume = 0.;
2618
2619 for (int k = kmin; k < kmax; k++)
2620 {
2621 // si direction==DIRECTION_I alors x_coord = coordonnee du noeud dans la direction I donc x_noeud et z_coord = z_element
2622 // si direction==DIRECTION_K alors x_coord = x_element et z_coord = z_noeud
2623 // x_coord et z_coord sont les abcisses des vitesse qui sont situee au centre des faces
2624 const double z_coord = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k+offset_k] : elem_pos[DIRECTION_K][k+offset_k];
2625 for (int j = jmin; j < jmax; j++)
2626 {
2627 //const double y_coord = (direction==DIRECTION_J) ? nodes_pos[DIRECTION_J][j+offset_j] : elem_pos[DIRECTION_J][j+offset_j];
2628 for (int i = imin; i < imax; i++)
2629 {
2630 const double x_coord = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i+offset_i] : elem_pos[DIRECTION_I][i+offset_i];
2631 const double delta_x = x_coord - position_cylindre[0]; // x_M - x_0
2632 const double delta_z = z_coord - position_cylindre[2]; // z_M - z_0
2633 const double d2 = delta_x * delta_x + delta_z * delta_z;
2634 const double d = sqrt(d2); // distance du point M au centre du tube
2635 const double rayon_tube_carre = tube_r * tube_r;
2636
2637 // foraage si on est dans le cylindre
2638 if (d2 < rayon_tube_carre)
2639 {
2640 Vecteur3 rotation;
2641 rotation[0] = omega * (- delta_z);
2642 rotation[1] = 0.;
2643 rotation[2] = omega * delta_x;
2644 double extrapolated_v = vitesse_cylindre[direction] + rotation[direction];
2645 double g_etalement;
2646 double delta_v;
2647 if (d2 > r_tube_min_carre ) // champ mirroir si d*d > (R-epsilon)*(R-epsilon)
2648 {
2649 g_etalement = 0.5 + 0.5 * (d - (tube_r - epsilon/2) ) / (epsilon * 0.5) - 0.5 / M_PI * sin( M_PI * (d - (tube_r - epsilon/2) )/ (epsilon*0.5) ); // fonction d'etalement
2650 // on calcule les coordonnees de P qui est le sym de M par rapport a l'interface : OP=beta*OM en notation vectorielle
2651 const double d_interface = tube_r - d; // distance du pt M a l'interface fluide solide
2652 const double beta = (tube_r + d_interface) / (tube_r - d_interface);
2653 const double delta_x_P = beta * delta_x; // x_P - x_0
2654 const double delta_z_P = beta * delta_z; // z_P _ z_0
2655
2656 // determination des indices i_min, i_max, k_min et k_max pour connaitre le cube dans lequel est P afin d'interpoler la vitesse en P
2657 // attention !!! : il s'agit d'indice locaux, ils permettent de se reperer que dans le proc considere
2658 const int i_min = int(floor(i + (delta_x_P - delta_x) * inv_delta_x ));
2659 const int i_max = i_min +1;
2660 const int k_min = int(floor(k + (delta_z_P - delta_z) * inv_delta_z ));
2661 const int k_max = k_min +1;
2662 // a partir des indices locaux on determine les coordonnes globales des vitesses en ces points :
2663 // x_11, z_11 correspond a i_min, k_min ; x_12, z_12 a i_max, k_min ; x_22, z_22 a i_max, k_max et x_21, z_21 a i_min, k_max.
2664
2665 //const double z_11 = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k_min+offset_k] : elem_pos[DIRECTION_K][k_min+offset_k];
2666 //const double x_11 = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i_min+offset_i] : elem_pos[DIRECTION_I][i_min+offset_i];
2667
2668 const double z_12 = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k_max+offset_k] : elem_pos[DIRECTION_K][k_max+offset_k];
2669 //const double x_12 = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i_min+offset_i] : elem_pos[DIRECTION_I][i_min+offset_i];
2670
2671 //const double z_22 = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k_max+offset_k] : elem_pos[DIRECTION_K][k_max+offset_k];
2672 //const double x_22 = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i_max+offset_i] : elem_pos[DIRECTION_I][i_max+offset_i];
2673
2674 //const double z_21 = (direction==DIRECTION_K) ? nodes_pos[DIRECTION_K][k_min+offset_k] : elem_pos[DIRECTION_K][k_min+offset_k];
2675 const double x_21 = (direction==DIRECTION_I) ? nodes_pos[DIRECTION_I][i_max+offset_i] : elem_pos[DIRECTION_I][i_max+offset_i];
2676 // on peut alors calculer alpha et beta pour realiser l'interpolation bilineaire :
2677
2678 const double alpha = (z_12 - ( delta_z_P + position_cylindre[2] ) ) * inv_delta_z;
2679 const double gamma = (x_21 - ( delta_x_P + position_cylindre[0] ) ) * inv_delta_x;
2680 // on fait l'interpolation bilineaire : mais comment on obtient la vitesse dans le repere global dc en i_min + offset_i par ex ????
2681 // j'ai l'impression que velocity(i,j,k) c'est dans le repere local pas ds le global
2682 // pour l'instant je le fais en monoproc il faudra dc mettre i_min + offset_i, j , k_min + offset_k
2683 // Valeur des vitesses aux quatre points du carre ds lequel est P
2684
2685 // Test si on est bien a l'interieur de la zone locale sur ce processeur:
2686 {
2687 const int gh = velocity.ghost();
2688 const int ni = velocity.ni();
2689 const int nk = velocity.nk();
2690 if (i_min < -gh || k_min < -gh || i_max >= ni + gh || k_max >= nk + gh)
2691 {
2692 Cerr << "Erreur, l'epaisseur ghost est insuffisante pour le calcul du champ mirroir ibc" << finl;
2693 Process::exit();
2694 }
2695 }
2696 const double v_11 = velocity(i_min, j, k_min);
2697 const double v_21 = velocity(i_max, j, k_min);
2698 const double v_22 = velocity(i_max, j, k_max);
2699 const double v_12 = velocity(i_min, j, k_max);
2700 // calcule de v_P par interpolation bilineaire
2701 const double v_P = (1-alpha) * (1-gamma) * v_11 + alpha * gamma * v_22 + alpha * (1 - gamma) * v_12 + gamma * (1 - alpha) * v_21;
2702
2703 // On fait une symetrie axial de la vitesse de P en M par rapport a l'interface fluide solide : (v(M) - v(S)) = - (v(P) - v(S))
2704 delta_v = (g_etalement * (-v_P + 2 * extrapolated_v) + (1-g_etalement) * extrapolated_v) - velocity(i, j, k); // qdm
2705 velocity(i, j, k) = g_etalement * (-v_P + 2 * extrapolated_v) + (1-g_etalement) * extrapolated_v; // ne pas oublier de mettre la fonction g_etalement
2706# if 0
2707 Cout << " direction : " << direction << " i : " << i << " j : "<< j << " k : " << k << " x_coord : " << x_coord << " z_coord : " << z_coord << endl;
2708 Cout << " i_min : " << i_min << " i_max : "<< i_max << " k_min : " << k_min << " k_max : " << k_max << " x_P " << delta_x_P + position_cylindre[0] << " z_P " << delta_z_P + position_cylindre[2] << endl;
2709 Cout << " alpha : " << alpha << " gamma : " << gamma << " x_11 " << x_11 << " z_11 " << z_11 << " x_21 " << x_21 ;
2710 Cout << " z_21 " << z_21 << " x_22 " << x_22 << " z_22 " << z_22 << " x_12 " << x_12 << " z_12 " << z_12 <<endl;
2711 Cout << " g_etalement : " << g_etalement << " v_P : " << v_P << " v(i,j,k) : " << velocity(i, j, k) << " v_11 " << v_11 ;
2712 Cout << " v_21 " << v_21 << " v_22 " << v_22 << " v_12 " << v_12 << endl;
2713#endif
2714
2715 }
2716 else // pas de champ miroir forcage direct classique
2717 {
2718 delta_v = extrapolated_v - velocity(i,j,k);
2719 velocity(i, j, k) = extrapolated_v ;
2720 //Cout << " direction : " << direction << " i : " << i << " j : "<< j << " k : " << k << endl;
2721 //Cout << " v(i,j,k) : " << velocity(i, j, k) << endl;
2722 }
2723
2724 // Calcul de rho sur la face: moyenne des rho sur les elements voisins
2725 double rho_fluide = (rho_fluide_field(i,j,k) + rho_fluide_field(i+ivoisin, j+jvoisin, k+kvoisin)) * 0.5; // rho sur la face est la moy des deux cotes
2726 delta_qdm_cylindre += delta_v * volume_maille * rho_fluide;
2727 masse_fluide += volume_maille * rho_fluide;
2728 volume += volume_maille;
2729 }
2730 }
2731 }
2732 }
2733
2734 integrale_force(itube, direction) = delta_qdm_cylindre;
2735 masse_fluide_cylindres(itube, direction) = masse_fluide;
2736 volume_cylindres(itube, direction) = volume;
2737 }
2738 }
2739 mp_sum_for_each_item(integrale_force);
2740 mp_sum_for_each_item(masse_fluide_cylindres);
2741 mp_sum_for_each_item(volume_cylindres);
2742}
2743
2744
2745//////////////////////////////
2746// Calcul des forces de pression par interpolation avec les valeurs de la pression a l interieur ou l exterieur du tube
2747//////////////////////////////
2748void Couplage_Tubes_IBC::calcul_F_pression(const IJK_Field_double& pressure, const IJK_Field_double& vx,
2749 DoubleTab& integrale_force_pression, DoubleTab& pression_teta,
2750 const Faisceau_Tubes& faisceau) const
2751{
2752 const Domaine_IJK& geom = vx.get_domaine();
2753 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
2754 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
2755 {
2756 for (int dir = 0; dir < 3; dir++)
2757 {
2758 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
2759 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
2760 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
2761 for (int i = 0; i < n; i++)
2762 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
2763 }
2764 }
2765 int jmin = 0;
2766 int jmax = pressure.nj();
2767 //const int offset_i = splitting.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
2768 //const int offset_k = splitting.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
2769 const int ntubes = faisceau.size();
2770 DoubleTab Pos_P;
2771 DoubleTab P_l_j;
2772 DoubleTab P_teta; // pression integre selon z pour le tube itube en l
2773 Pos_P.resize(ntubes , n_P_, 2); // tableau contenant pour chaque tube toutes les coordonnees x,z des point situes sur le cercle ou la pression est interpollees
2774 P_l_j.resize(ntubes , n_P_, jmax);
2775 P_teta.resize(ntubes, n_P_);
2776 const double teta = 2 * M_PI / n_P_;
2777 const double delta_x = geom.get_constant_delta(0);
2778 const double delta_z = geom.get_constant_delta(2);
2779 const double inv_delta_x = 1./delta_x;
2780 const double inv_delta_z = 1./delta_z;
2781
2782
2783 for (int itube = 0; itube < ntubes; itube++)
2784 {
2785 const Tube_base& tube = faisceau[itube].valeur();
2786 const double tube_r = tube.get_rayon();
2787 const Vecteur3 position_cylindre = tube.get_current_pos();
2788 double p_surface_cylindre_x = 0.;
2789 double p_surface_cylindre_z = 0.;
2790 const double dS = tube_r * teta * delta_z;
2791
2792 for (int l =0; l < n_P_; l++)
2793 {
2794 P_teta(itube, l) = 0.;
2795 const double teta_l = l * teta;
2796 // coord = 0 correspond a x, coord = 1 correspond a z
2797 // x_P = x_cylindre + R * cos(teta_l); z_P = z_cylindre + R * sin(teta_l)
2798 Pos_P(itube, l, 0) = position_cylindre[0] + tube_r * cos(teta_l);
2799 Pos_P(itube, l, 1) = position_cylindre[2] + tube_r * sin(teta_l);
2800 const double x_P_Delta_x = Pos_P(itube , l, 0) * inv_delta_x;
2801 const double z_P_Delta_z = Pos_P(itube , l, 1) * inv_delta_z;
2802 const double resu_x = x_P_Delta_x - int(floor(x_P_Delta_x));
2803 const double resu_z = z_P_Delta_z - int(floor(z_P_Delta_z));
2804 // Attention ce sont les indices globaux !!!!!
2805 int i_min, i_max, k_min, k_max;
2806 if ( resu_x < 0.5)
2807 {
2808 i_min = int(floor(x_P_Delta_x))-1;
2809 i_max = i_min +1;
2810 }
2811 else
2812 {
2813 i_min = int(floor(x_P_Delta_x));
2814 i_max = i_min +1;
2815 }
2816
2817 if ( resu_z < 0.5)
2818 {
2819 k_min = int(floor(z_P_Delta_z))-1;
2820 k_max = k_min +1;
2821 }
2822 else
2823 {
2824 k_min = int(floor(z_P_Delta_z));
2825 k_max = k_min +1;
2826 }
2827
2828 const double x_21 = elem_pos[DIRECTION_I][i_max];
2829 const double z_12 = elem_pos[DIRECTION_K][k_max];
2830
2831
2832 const double alpha = (z_12 - ( Pos_P(itube , l, 1) ) ) * inv_delta_z;
2833 const double gamma = (x_21 - ( Pos_P(itube , l, 0) ) ) * inv_delta_x;
2834 // on fait l'interpolation bilineaire : mais comment on obtient la vitesse dans le repere global dc en i_min + offset_i par ex ????
2835 // j'ai l'impression que velocity(i,j,k) c'est dans le repere local pas ds le global
2836 // pour l'instant je le fais en monoproc il faudra dc mettre i_min + offset_i, j , k_min + offset_k
2837 // Valeur des vitesses aux quatre points du carre ds lequel est P
2838 for (int j = jmin; j < jmax; j++)
2839 {
2840 const double p_11 = pressure(i_min, j, k_min);
2841 const double p_21 = pressure(i_max, j, k_min);
2842 const double p_22 = pressure(i_max, j, k_max);
2843 const double p_12 = pressure(i_min, j, k_max);
2844
2845 // calcule de la pression P par interpolation bilineaire pour le tube itube au point l,j :
2846 P_l_j(itube, l, j) = (1-alpha) * (1-gamma) * p_11 + alpha * gamma * p_22 + alpha * (1 - gamma) * p_12 + gamma * (1 - alpha) * p_21;
2847 p_surface_cylindre_x += P_l_j(itube, l, j) * cos(teta_l);
2848 p_surface_cylindre_z += P_l_j(itube, l, j) * sin(teta_l);
2849 P_teta(itube, l) += P_l_j(itube, l, j);
2850
2851
2852 }
2853 pression_teta(itube, l) = P_teta(itube, l) / jmax; // moy de la pression en l selon z
2854 }
2855 // Fx = - dS * [ Somme(j= a nj-1) Somme(l=0 a N-1) p(R,teta_l,j) * cos(teta_l) ]
2856 // Fz = - dS * [ Somme(j= a nj-1) Somme(l=0 a N-1) p(R,teta_l,j) * sin(teta_l) ]
2857 integrale_force_pression(itube, 0) = - dS * p_surface_cylindre_x;
2858 integrale_force_pression(itube, 1) = - dS * p_surface_cylindre_z;
2859
2860 }
2861
2862
2863 mp_sum_for_each_item(integrale_force_pression);
2864 mp_sum_for_each_item(pression_teta);
2865
2866
2867}
2868
2869
2870//////////////////////////////
2871// Calcul des forces de pression en ne prenant les valeurs de la pression que si elles sont a l exterieur du tube
2872//////////////////////////////
2873void Couplage_Tubes_IBC::calcul_F_pression2(const IJK_Field_double& pressure, const IJK_Field_double& vx,
2874 DoubleTab& integrale_force_pression, DoubleTab& pression_teta,
2875 const Faisceau_Tubes& faisceau) const
2876{
2877 const Domaine_IJK& geom = vx.get_domaine();
2878 ArrOfDouble nodes_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des nodes
2879 ArrOfDouble elem_pos[3]; //defini un tableau dynamique de 3 lignes pour la position des elements
2880 {
2881 for (int dir = 0; dir < 3; dir++)
2882 {
2883 nodes_pos[dir] = geom.get_node_coordinates(dir); // node=noeud, les noeuds sont a l'intersection des mailles; on ne connait que la position des noeuds
2884 const int n = nodes_pos[dir].size_array()-1; // n= nombre de noeuds-1 = nombre d'elements dans la direction dir; les alements sont au centre des mailles
2885 elem_pos[dir].resize_array(n); // donne la taille du tableau contenant les elements
2886 for (int i = 0; i < n; i++)
2887 elem_pos[dir][i] = (nodes_pos[dir][i] + nodes_pos[dir][i+1]) * 0.5; // la position de l'element selon dir est moyenne de la positions des noeuds de part et d'autre
2888 }
2889 }
2890 int jmin = 0;
2891 int jmax = pressure.nj();
2892 const int offset_i = geom.get_offset_local(DIRECTION_I); // donne l'offset selon la direction i
2893 const int offset_k = geom.get_offset_local(DIRECTION_K); // donne l'offset selon la direction k
2894 const int ntubes = faisceau.size();
2895 DoubleTab Pos_P;
2896 DoubleTab P_l_j;
2897 DoubleTab P_teta; // pression integre selon z pour le tube itube en l
2898 Pos_P.resize(ntubes , n_P_, 2); // tableau contenant pour chaque tube toutes les coordonnees x,z des point situes sur le cercle ou la pression est interpollees
2899 P_l_j.resize(ntubes , n_P_, jmax);
2900 P_teta.resize(ntubes, n_P_);
2901 const double teta = 2 * M_PI / n_P_;
2902 const double delta_x = geom.get_constant_delta(0);
2903 const double delta_y = geom.get_constant_delta(1);
2904 const double delta_z = geom.get_constant_delta(2);
2905 const double inv_delta_x = 1./delta_x;
2906 const double inv_delta_z = 1./delta_z;
2907
2908
2909 for (int itube = 0; itube < ntubes; itube++)
2910 {
2911 const Tube_base& tube = faisceau[itube].valeur();
2912 const double tube_r = tube.get_rayon();
2913 const Vecteur3 position_cylindre = tube.get_current_pos();
2914 double p_surface_cylindre_x = 0.;
2915 double p_surface_cylindre_z = 0.;
2916 const double dS = tube_r * teta * delta_y;
2917 // Cout << "teta : " << teta << " delta_z : " << delta_z << " delta_x : " << delta_x << " delta_y : " << delta_y << finl;
2918
2919 for (int l =0; l < n_P_; l++)
2920 {
2921 P_teta(itube, l) = 0.;
2922 const double teta_l = l * teta;
2923 // coord = 0 correspond a x, coord = 1 correspond a z
2924 // x_P = x_cylindre + R * cos(teta_l); z_P = z_cylindre + R * sin(teta_l)
2925 Pos_P(itube, l, 0) = position_cylindre[0] + tube_r * cos(teta_l);
2926 Pos_P(itube, l, 1) = position_cylindre[2] + tube_r * sin(teta_l);
2927 const double x_P_Delta_x = Pos_P(itube , l, 0) * inv_delta_x;
2928 const double z_P_Delta_z = Pos_P(itube , l, 1) * inv_delta_z;
2929 // maille i,k contenant le point P
2930 // Attention ce sont les indices globaux !!!!!
2931 const int i_M = int(floor(x_P_Delta_x));
2932 const int k_M = int(floor(z_P_Delta_z));
2933 int i_p = 0;
2934 int k_p = 0;
2935 double ratio =0;
2936 ratio =0; // je fais ca ici car j'ai un bug de compilation "ratio defined but not used"
2937 ratio += ratio; // je rajoute ca car ca bug toujours sur fluent
2938 // Retirer ration cree un bug de compilation :
2939 // Couplage_Tubes_IBC.cpp:2854:5: error: 'ratio' was not declared in this scope
2940 // Couplage_Tubes_IBC.cpp:2862:3: error: 'ratio' was not declared in this scope
2941 // commenter la part de code en #IF 0 ne change rien
2942 // a voir du cote des optimisations du compilateur
2943 // determination des coordonnes de l'element M situe au centre de la maille i,k
2944
2945 const double x_M = elem_pos[DIRECTION_I][i_M];
2946 const double z_M = elem_pos[DIRECTION_K][k_M];
2947 const double d_OM2 = (x_M - position_cylindre[0]) * (x_M - position_cylindre[0]) + (z_M - position_cylindre[2]) * (z_M - position_cylindre[2]);
2948 const double R2 = tube_r * tube_r ;
2949
2950 if ( d_OM2 < R2)
2951 {
2952 const double f = (tube_r + sqrt( delta_x * delta_x + delta_z * delta_z ))/tube_r; // on va chercher la valeur de la pression dans une maille situee en dehros du tube a une distance d= f*tube_r
2953 // calcul des coordonnees du point E, qui est situe sur la droite OM a la distance OM+racine(deltax*deltax + deltaz*deltaz).
2954 const double x_E = position_cylindre[0] + f * ( Pos_P(itube, l, 0) - position_cylindre[0] );
2955 const double z_E = position_cylindre[2] + f * ( Pos_P(itube, l, 1) - position_cylindre[2] );
2956 const int i_E = int(floor(x_E * inv_delta_x));
2957 const int k_E = int(floor(z_E * inv_delta_z));
2958 // indice globaux de lelement ou on prend p
2959 i_p = i_E;
2960 k_p = k_E;
2961 ratio = 1. /f ;
2962
2963 //Cout << " x_E : " << x_E << " z_E : " << z_E << " i_p : " << i_p << " k_p : " << k_p << " ratio : " << ratio << endl;
2964 //Cerr << " x_E : " << x_E << " z_E : " << z_E << " i_p : " << i_p << " k_p : " << k_p << " ratio : " << ratio << endl;
2965 }
2966 else
2967 {
2968 i_p = i_M;
2969 k_p = k_M;
2970 ratio = tube_r / sqrt(d_OM2);
2971 //Cout << " i_p : " << i_p << " k_p : " << k_p << " ratio : " << ratio << " sqrt_d_OM2 : " << sqrt(d_OM2) << endl;
2972 //Cerr << " i_p : " << i_p << " k_p : " << k_p << " ratio : " << ratio << " sqrt_d_OM2 : " << sqrt(d_OM2) << endl;
2973 }
2974 // Ajout BM:
2975 //Cout << " offset_i + pressure.ni() : " << offset_i + pressure.ni() << endl;
2976 //Cerr << " offset_i + pressure.ni() : " << offset_i + pressure.ni() << endl;
2977 if (i_p >= offset_i && i_p < offset_i + pressure.ni() && k_p >= offset_k && k_p < offset_k + pressure.nk())
2978 {
2979
2980 for (int j = jmin; j < jmax; j++)
2981 {
2982 // P_l_j(itube, l, j) = ratio * pressure_(i_p, j, k_p);
2983 P_l_j(itube, l, j) = pressure(i_p-offset_i, j, k_p-offset_k);
2984 //Cerr << " i_p-offset_i : " << i_p-offset_i << " i_p-offset_k : "<< k_p-offset_k << endl;
2985 p_surface_cylindre_x += P_l_j(itube, l, j) * cos(teta_l);
2986 p_surface_cylindre_z += P_l_j(itube, l, j) * sin(teta_l);
2987 P_teta(itube, l) += P_l_j(itube, l, j);
2988
2989
2990 }
2991 }
2992 pression_teta(itube, l) = P_teta(itube, l) / jmax; // moy de la pression en l selon z
2993 }
2994 // Fx = - dS * [ Somme(j= a nj-1) Somme(l=0 a N-1) p(R,teta_l,j) * cos(teta_l) ]
2995 // Fz = - dS * [ Somme(j= a nj-1) Somme(l=0 a N-1) p(R,teta_l,j) * sin(teta_l) ]
2996 //Cout << "p_surface_cylindre_x : " << p_surface_cylindre_x << " p_surface_cylindre_z : " << p_surface_cylindre_z << " dS : " << dS << finl;
2997 integrale_force_pression(itube, 0) = - dS * p_surface_cylindre_x;
2998 integrale_force_pression(itube, 1) = - dS * p_surface_cylindre_z;
2999 //Cout << "integrale_force_pression(itube, 0) : " << integrale_force_pression(itube, 0) << " integrale_force_pression(itube, 1) : " << integrale_force_pression(itube, 0) << finl;
3000
3001 }
3002
3003
3004 mp_sum_for_each_item(integrale_force_pression);
3005 mp_sum_for_each_item(pression_teta);
3006
3007
3008}
3009
3010
3011
3012///////////////////////////////////////////////////
3013//
3014//////////////////////////////////////////////////
3015
3016void Couplage_Tubes_IBC::update(double current_time,
3017 double timestep)
3018{
3019 // a modifier plus tard pour les tubes libres:
3020 //Vecteur3 force_appliquee(0,0,0);
3021 Vecteur3 force_appliquee;
3022 Vecteur3 pression;
3023 Vecteur3 volume_cylindre;
3024 Vecteur3 masse_fluide_cylindres;
3025 Vecteur3 F_IBC;
3026 Vecteur3 F_IBC_post_proj;
3027 Vecteur3 m_a;
3028
3029 // faisceau_[i] est un objet de type OWN_PTR(Tube_base)
3030 // pour acceder a l'objet Tube_impose ou Tube_libre ou autre, il faut utiliser
3031 // faisceau_[i].valeur() qui est ici de type Tube_base.
3032 const int ntubes = faisceau_.size();
3033 for (int i = 0; i < ntubes; i++)
3034 {
3035 // calcul de la force appliquee
3036 const Tube_base& tube = faisceau_[i].valeur(); // faisceau_[itube].valeur() est de type Tube_base
3037 Vecteur3 terme_inertiel = tube.get_current_acceleration(); // pour l'instant terme_inertiel = acceleration
3038 Vecteur3 F_ibc_extrapole;
3039 for (int dir = 0; dir < 3; dir++)
3040 {
3041 terme_inertiel[dir] *=masse_fluide_cylindres_(i,dir); // maintenant : terme_inertiel[dir] = acceleration * m_F
3042 // F_ibc_extrapole = F_IBC(n) + [t(n+1) - t(n)] * [F_IBC(n) - F_IBC(n-1)] / [t(n) - t(n-1)] //Calcul d'ordre 1 de la force IBC au temps n+1
3043 F_ibc_extrapole[dir] = integrale_force_(i,dir) + timestep * d_integrale_force_(i,dir);
3044 // F fluide sur solide pour le newmark = - (F_IBC_extrapole - m_F*acceleration_cylindre)
3045 force_appliquee[dir]= -( F_ibc_extrapole[dir] - terme_inertiel[dir]);
3046 volume_cylindre[dir] = volume_cylindres_(i,dir);
3047 masse_fluide_cylindres[dir] = masse_fluide_cylindres_(i,dir);
3048 F_IBC[dir] = integrale_force_(i,dir);
3049 F_IBC_post_proj[dir] = integrale_force_post_proj_(i,dir);
3050 m_a[dir] = terme_inertiel[dir];
3051 }
3052
3053 pression[0] = integrale_force_pression_(i,0);
3054 pression[1] = integrale_force_pression_(i,1);
3055 pression[2] = 0.;
3056 // Affichage des caracteristiques des tubes
3057 const Vecteur3 acceleration = tube.get_current_acceleration();
3058 const Vecteur3 pos = tube.get_current_pos();
3059 const Vecteur3 v = tube.get_current_velocity();
3060
3061 // Calcul de la hauteur du tube
3062 const Domaine_IJK& geom = ref_domaine_.valeur();
3063 ArrOfDouble noeuds_y;
3064 noeuds_y = geom.get_node_coordinates(1); // rentre les coordonnees des noeuds selon y dans le tableau noeuds_y
3065 const int n_element_y = noeuds_y.size_array()-1; // nombre d'elements selon y = nombre de noeuds -1
3066 const double delta_y = geom.get_constant_delta(1);
3067 const double hauteur_cylindre = n_element_y * delta_y;
3068 //
3069 const double tube_r = tube.get_rayon();
3070 // Calcul de Cx, Cy et Cz : C=F/(0.5rho_F*D*U*U*h)
3071 Vecteur3 C = force_appliquee;
3072 const double Adim = 1./(0.5 * rho_fluide_pour_adim_ * vitesse_pour_adim_ * vitesse_pour_adim_ * 2 * tube_r * hauteur_cylindre);
3073 C *=Adim;
3074 Vecteur3 C_IBC = F_IBC;
3075 C_IBC *=Adim;
3076
3077 // Affichage des carac des tubes
3078 Cout << "Caracteristiques du tube " << tube.nom_du_tube() << " de type " << tube.que_suis_je() << finl; // tube est de type nom_, que_suis_je() est une fonction TrioU qui permet de lire ce type
3079 Cout << "Pos : " << pos << " t= " << current_time << finl;
3080 Cout << "V : " << v << " t= " << current_time << finl;
3081 Cout << "A : " << acceleration << " t= " << current_time << finl;
3082 Cout << "C : " << C << " t= " << current_time << finl;
3083 Cout << "F : " << force_appliquee << " t= " << current_time << finl;
3084 Cout << "F_IBC : " << F_IBC << " t= " << current_time << finl;
3085 Cout << "F_IBC_post_proj : " << F_IBC_post_proj << " t= " << current_time << finl;
3086 Cout << "C_IBC : " << C_IBC << " t= " << current_time << finl;
3087 Cout << "F_P_non_adim : " << pression << " t= " << current_time << finl;
3088 pression *=Adim;
3089 Cout << "F_P : " << pression << " t= " << current_time << finl;
3090 Cout << "V_c : " << volume_cylindre << " t= " << current_time << finl;
3091 Cout << "M_F : " << masse_fluide_cylindres << " t= " << current_time << finl;
3092 Cout << "m_a : " << m_a << " t= " << current_time << finl;
3093 Cout << " " << finl;
3094 // Actualisation de la position du tube i
3095 faisceau_[i]->update_vitesse_position(current_time, timestep, force_appliquee);
3096
3097 }
3098}
DoubleTab d_integrale_force_post_proj_
void force_ibc_velocity_miroir(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
void ibc0_velocity_cube(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
void force_ibc_velocity(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
DoubleTab integrale_force_pression_
void reprendre_probleme(Entree &fichier)
void update(double current_time, double timestep)
void ibc_localisee_velocity_cube_qdm(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &, double current_time) const
void sauvegarder_probleme(SFichier &f)
DoubleTab integrale_force_N_moins_1_post_proj_
void calcul_F_pression2(const IJK_Field_double &pressure, const IJK_Field_double &vx, DoubleTab &integrale_force_pression, DoubleTab &pression_teta, const Faisceau_Tubes &) const
void ibc_localisee_force_cube(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &, double current_time) const
void ibc0_force_cube(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
DoubleTab integrale_force_post_proj_
void initialize(const Domaine_IJK &)
void force_ibc_velocity_symetrie_plane(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
fonction_ibc pour faire le champ miroir
void force_ibc_velocity_anticipe_cube(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &, const double timestep) const
forcage anticpe dans le cas du cube
DoubleTab integrale_force_N_moins_1_
void sauvegarder_pression(SFichier &f)
void force_ibc(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, double timestep, const IJK_Field_double &pressure, double current_time)
void ibc_localisee_velocity_cube(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &, double current_time) const
void force_ibc_velocity_frac_vol(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
void ibc_diffuse_velocity_cube(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
void calcul_force_post_projection(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, double timestep, double current_time)
Calcul force ibc post projection.
void champ_miroir(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, double timestep, const IJK_Field_double &pressure)
void ibc_diffuse_force_cube(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, DoubleTab &masse_fluide_cylindres, DoubleTab &volume_cylindres, DoubleTab &integrale_force, const Faisceau_Tubes &) const
void calcul_F_pression(const IJK_Field_double &pressure, const IJK_Field_double &vx, DoubleTab &integrale_force_pression, DoubleTab &pression_teta, const Faisceau_Tubes &) const
void forcage_anticipe(IJK_Field_double &vx, IJK_Field_double &vy, IJK_Field_double &vz, const IJK_Field_double &rho_field, double timestep, const IJK_Field_double &pressure)
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
int get_offset_local(int direction) const
Returns the local offset in requested direction.
double get_constant_delta(int direction) const
Returns the size of cells in a direction.
const ArrOfDouble & get_node_coordinates(int direction) const
Returns an array with the coordinates of all nodes in the mesh in requested direction.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
const Domaine_IJK & get_domaine() const
static Objet_U & objet_global(const Nom &nom)
cherche l'objet demande dans l'Interprete_bloc courant (Interprete_bloc::interprete_courant()) et dan...
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
friend class Entree
Definition Objet_U.h:76
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
int lire_avec_accolades(Entree &is)
Alias of lire_avec_accolades_depuis.
Definition Param.h:577
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
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
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
const Vecteur3 & get_current_pos() const
Definition Tube_base.h:32
double get_omega() const
Definition Tube_base.h:44
const Vecteur3 & get_current_acceleration() const
Definition Tube_base.h:40
double get_rayon() const
Definition Tube_base.h:48
const Nom & nom_du_tube() const
Definition Tube_base.h:56
const Vecteur3 & get_current_velocity() const
Definition Tube_base.h:36