TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Transport_Interfaces_FT_Disc.cpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Transport_Interfaces_FT_Disc.h>
17#include <Probleme_FT_Disc_gen.h>
18#include <Operateur.h>
19#include <Motcle.h>
20#include <EcritureLectureSpecial.h>
21#include <Discret_Thyd.h>
22#include <Schema_Temps_base.h>
23#include <Parser.h>
24#include <Domaine_VF.h>
25#include <Domaine_VDF.h>
26#include <Sous_Domaine.h>
27#include <Champ_Face_VDF.h>
28#include <Champ_P1NC.h>
29#include <Champ_Fonc_P1NC.h>
30#include <Fluide_Diphasique.h>
31#include <Fluide_Incompressible.h>
32#include <Perf_counters.h>
33#include <Paroi_FT_disc.h>
34#include <Champ_Fonc_Face_VDF.h>
35#include <Scatter.h>
36#include <LecFicDiffuse.h>
37#include <Sauvegarde_Reprise_Maillage_FT.h>
38#include <SFichier.h>
39#include <Debog.h>
40#include <Format_Post_Lata.h>
41#include <Connex_components.h>
42#include <Connex_components_FT.h>
43#include <Loi_horaire.h>
44#include <Transport_Marqueur_FT.h>
45#include <communications.h>
46#include <Convection_Diffusion_Temperature_FT_Disc.h>
47
48#include <Champ_Fonc_P0_base.h>
49#include <EFichierBin.h>
50#include <Param.h>
51#include <sys/stat.h>
52#include <TRUSTList.h>
53#include <Domaine.h>
54#include <TRUSTTrav.h>
55#include <Dirichlet_paroi_fixe.h>
56#include <Dirichlet_paroi_defilante.h>
57#include <Echange_contact_VDF_FT_Disc.h>
58#include <TRUST_2_PDI.h>
59#include <Avanc.h>
60
61
62Implemente_instanciable_sans_constructeur_ni_destructeur(Transport_Interfaces_FT_Disc,"Transport_Interfaces_FT_Disc",Transport_Interfaces_base);
63
64/*! @brief Classe outil ou on stocke tout le bazar qui sert au fonctionnement de l'equation de transport.
65 *
66 * Permet de sauvegarder/reprendre les donnees d'interface
67 * (probleme des reprises avec pas de temps multiples),
68 * et de reduire les dependances en n'incluant presque rien dans Transport_Interfaces_FT_Disc.h
69 *
70 */
71static void eval_vitesse(double x, double y, double z, double t,
72 Parser& px, Parser& py, Parser& pz,
73 double& vx, double& vy, double& vz)
74{
75 int i0=0, i1=1, i2=2, i3=3;
76 px.setVar(i0,x);
77 px.setVar(i1,y);
78 px.setVar(i2,z);
79 px.setVar(i3,t);
80
81 vx = px.eval();
82 py.setVar(i0,x);
83 py.setVar(i1,y);
84 py.setVar(i2,z);
85 py.setVar(i3,t);
86
87 vy = py.eval();
88 pz.setVar(i0,x);
89 pz.setVar(i1,y);
90 pz.setVar(i2,z);
91 pz.setVar(i3,t);
92 vz = pz.eval();
93}
94static void integrer_vitesse_imposee(
95 Parser& parser_vx, Parser& parser_vy, Parser& parser_vz,
96 double temps, double dt, double& x, double& y, double& z)
97{
98 // Runge Kutta ordre 3:
99 double vx, vy, vz;
100 eval_vitesse(x,
101 y,
102 z,
103 temps,
104 parser_vx,parser_vy,parser_vz,vx,vy,vz);
105 double vx1,vy1,vz1;
106 eval_vitesse(x + vx * dt * 0.5,
107 y + vy * dt * 0.5,
108 z + vz * dt * 0.5,
109 temps + dt * 0.5,
110 parser_vx,parser_vy,parser_vz,vx1,vy1,vz1);
111 double vx2,vy2,vz2;
112 eval_vitesse(x + vx1 * dt * 0.5,
113 y + vy1 * dt * 0.5,
114 z + vz1 * dt * 0.5,
115 temps + dt * 0.5,
116 parser_vx,parser_vy,parser_vz,vx2,vy2,vz2);
117 double vx3,vy3,vz3;
118 eval_vitesse(x + vx2 * dt,
119 y + vy2 * dt,
120 z + vz2 * dt,
121 temps + dt,
122 parser_vx,parser_vy,parser_vz,vx3,vy3,vz3);
123
124 x += (vx + 2.*vx1 + 2.*vx2 + vx3) / 6. * dt;
125 y += (vy + 2.*vy1 + 2.*vy2 + vy3) / 6. * dt;
126 z += (vz + 2.*vz1 + 2.*vz2 + vz3) / 6. * dt;
127}
128
129/*! @brief calcul du vecteur normal a l'interface, aux sommets du maillage d'interface.
130 *
131 * Le tableau "normale" est efface et resize.
132 * La normale est la moyenne des normales des facettes voisines, ponderees par
133 * la surface de la facette.
134 * La norme du vecteur normal n'est pas unitaire !
135 * L'espace virtuel n'est pas a jour !
136 *
137 */
138static void calculer_normale_sommets_interface(const Maillage_FT_Disc& maillage,
139 DoubleTab& normale)
140{
141 const int nsom = maillage.nb_sommets();
142 const int nfaces = maillage.nb_facettes();
143 const int dim = maillage.sommets().line_size();
144 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
145 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
146 const IntTab& facettes = maillage.facettes();
147 const int nsommets_faces = facettes.line_size();
148
149 normale.resize(nsom, dim);
150 normale = 0.;
151 double n[3]= {0,0,0};
152
153 for (int i = 0; i < nfaces; i++)
154 {
155
156 // Somme pour les faces reelles:
157 if (maillage.facette_virtuelle(i))
158 continue;
159
160 const double surface = surface_facettes[i];
161 for (int k = 0; k < dim; k++)
162 n[k] = normale_facettes(i,k) * surface;
163
164 for (int j = 0; j < nsommets_faces; j++)
165 {
166 const int sommet = facettes(i,j);
167 for (int k = 0; k < dim; k++)
168 normale(sommet, k) += n[k];
169 }
170 }
171
172 // Sommer les contributions pour les sommets partages par plusieurs processeurs:
174}
175
176Implemente_instanciable_sans_constructeur_ni_destructeur(Transport_Interfaces_FT_Disc_interne,"Transport_Interfaces_FT_Disc_interne",Objet_U);
177
179{
180 assert(0);
181 return is;
182}
184{
185 assert(0);
186 return os;
187}
188
190{
191 const Nom& fullname = restart ? restart_fname_ : checkpoint_fname_;
192 int index = fullname.find(".");
193 std::string fname = index ==-1 ? fullname.getString() : fullname.getString().substr(0, index); //removing file extension
194 Nom nom_fich_xyz(fname);
195 nom_fich_xyz += Nom("_") + pb_name_;
196 nom_fich_xyz += Nom("_") + ident_;
197 nom_fich_xyz += "_maillage_interface";
198 nom_fich_xyz += ".xyz";
199 return nom_fich_xyz;
200}
201
203{
204 if (fic_front_sauv_)
205 {
206 Cerr << "Transport_Interfaces_FT_Disc::init_save_file Backup file for the FT mesh has already been initialized!" << finl;
208 }
209 else
210 {
211 const Nom& nom_fich_xyz = maillage_interface_xyz_filename(0 /*save mode*/);
212 fic_front_sauv_.typer(EcritureLectureSpecial::get_Output());
213 fic_front_sauv_->ouvrir(nom_fich_xyz);
214 }
215
216}
217
219{
220 if (!fic_front_sauv_)
221 {
222 Cerr << "Transport_Interfaces_FT_Disc::close_save_file Backup file for the FT mesh has not been initialized!" << finl;
224 }
225 else
226 {
228 fic_front_sauv_.valeur() << Nom("fin");
229 (fic_front_sauv_.valeur()).flush();
230 (fic_front_sauv_.valeur()).syncfile();
231 }
232}
233
234/*! @brief for PDI IO: retrieve name and type and dimensions of the indicatrice tag
235 *
236 */
238{
239 std::vector<YAML_data> data = indicatrice_cache->data_a_sauvegarder();
240
241 // the indicatrice cache tag
242 std::string name = pb_name_.getString() + "_" + ident_.getString() + "_indicatrice_cache_tag";
243 YAML_data ictag(name, "int");
244 ictag.set_local(false /*same value for everyone*/);
245 data.push_back(ictag);
246 return data;
247}
248
250{
251 // Il faut sauvegarder l'indicatrice_cache car elle ne peut pas toujours etre
252 // correctement reconstruite a partir de l'interface (on tolere qu'il y ait
253 // des inconsistances) :
254 int bytes=0;
255 bytes += indicatrice_cache->sauvegarder(os);
256
257 int special, afaire;
258 const int format_xyz = EcritureLectureSpecial::is_ecriture_special(special, afaire);
259 if (format_xyz)
260 {
262 {
263 os << indicatrice_cache_tag << finl;
264 }
265 }
267 {
268 std::string name = pb_name_.getString() + "_" + ident_.getString() + "_indicatrice_cache_tag";
269 TRUST_2_PDI pdi_interface;
270 pdi_interface.TRUST_start_sharing(name, &indicatrice_cache_tag);
271 }
272 else
273 os << indicatrice_cache_tag << finl;
274
276 {
277 Cerr << "Transport_Interfaces_FT_Disc_interne::sauvegarder : WARNING ! PDI format is not supported for the FT mesh so we save it in xyz format " << finl;
280 Sortie_Fichier_base& xyz_os = const_cast<Sortie_Fichier_base&>(fic_front_sauv_.valeur());
282 {
283 Nom mon_ident(maillage_interface.que_suis_je());
284 mon_ident += Nom(time_,"%e");
285 xyz_os << mon_ident << finl;
286 xyz_os << maillage_interface.que_suis_je() << finl;
287 }
288 bytes += maillage_interface.sauvegarder(xyz_os);
289
291 {
292 Nom mon_ident(remaillage_interface_.que_suis_je());
293 mon_ident += Nom(time_,"%e");
294 xyz_os << mon_ident << finl;
295 xyz_os << remaillage_interface_.que_suis_je() << finl;
296 }
297 bytes += remaillage_interface_.sauvegarder(xyz_os);
300 }
301 else
302 {
303 bytes += maillage_interface.sauvegarder(os);
304 bytes += remaillage_interface_.sauvegarder(os); // Sauvegarde du temps du dernier remaillage...
305 }
306 return bytes;
307}
308
310{
311 Cerr << "Transport_Interfaces_FT_Disc_interne::reprendre" << finl;
312 Nom ident, type;
314 {
315 TRUST_2_PDI pdi_interface;
316 // getting type
317 Nom name = pb_name_ + "_" + indicatrice_cache->le_nom();
318 pdi_interface.get_type(name, type);
319
320 // getting indicatrice cache tag
321 name = pb_name_ + "_" + ident_ + "_indicatrice_cache_tag";
322 pdi_interface.read(name.getString(), &indicatrice_cache_tag);
323 }
324 else
325 is >> ident >> type;
326
327 if (!indicatrice_cache)
328 {
329 // Le champ n'est pas discretise, on lit ceci pour sauter le bloc
330 indicatrice_cache.typer(type);
331 }
332 indicatrice_cache->reprendre(is);
333
335 {
336 Cerr << "Transport_Interfaces_FT_Disc_interne::reprendre : WARNING ! PDI format is not supported for the FT mesh so we use xyz format" << finl;
340 xyz_is.typer(EcritureLectureSpecial::Input);
341 const Nom& nomfic = maillage_interface_xyz_filename(1 /* restart mode */);
342 xyz_is->ouvrir(nomfic);
343 if (xyz_is->fail())
344 {
345 Cerr << "Error during the opening of the restart file : " << nomfic << finl;
347 }
348 else
349 Cerr << "Reading interface in file " << nomfic << finl;
350
351 Nom mon_ident(maillage_interface.que_suis_je());
352 mon_ident += Nom(time_,"%e");
353 avancer_fichier(xyz_is, mon_ident);
354 maillage_interface.reprendre(xyz_is);
355
356 mon_ident=remaillage_interface_.que_suis_je();
357 mon_ident += Nom(time_,"%e");
358 avancer_fichier(xyz_is, mon_ident);
359 remaillage_interface_.reprendre(xyz_is);
362 }
363 else
364 {
366 maillage_interface.reprendre(is);
367 remaillage_interface_.reprendre(is);
368 }
369 return 1;
370}
371
372/*! @brief constructeur par defaut
373 *
374 * TODO: remove the new Transport_Interfaces_FT_Disc_interne in there. why do that ?
375 */
377{
378 variables_internes_ = new Transport_Interfaces_FT_Disc_interne;
379 temps_debut_=-1.e38;
380 interpolation_repere_local_ = 0;
381 force_.resize(dimension);
382 moment_.resize((dimension==2?1:dimension));
383}
384
385/*! @brief le destructeur qui va avec
386 *
387 */
388Transport_Interfaces_FT_Disc::~Transport_Interfaces_FT_Disc()
389{
390 delete variables_internes_;
391}
392
394{
396}
397
399{
400
401 /* Noms& nom=champs_compris_.liste_noms_compris();
402 nom[0] += le_nom();
403 nom[1] += le_nom();
404 nom[2] += le_nom();
405 nom[3] += le_nom();
406 */
407
410 {
411 Cerr << "Name of subdomaine for interfaces deletion: " << suppression_interfaces_sous_domaine_ << finl;
412 // Juste un test pour verifier que le nom existe:
414 }
415 return is;
416}
417
419{
421 param.ajouter_non_std("maillage",(this));
422 param.ajouter("remaillage",&remaillage_interface());
423 param.ajouter("collisions",&topologie_interface());
424 param.ajouter_non_std("methode_transport",(this),Param::REQUIRED);
425 param.ajouter_non_std("n_iterations_distance",(this));
426 param.ajouter_non_std("iterations_correction_volume",(this)); // Former Keyword, Obsolete
427 param.ajouter("VOFlike_correction_volume",&variables_internes_->VOFlike_correction_volume); // a flag: 0 or 1.
428 param.ajouter("nb_lissage_correction_volume",&variables_internes_->nb_lissage_correction_volume);
429 param.ajouter("nb_iterations_correction_volume",&variables_internes_->nb_iterations_correction_volume);
430 param.ajouter_non_std("volume_impose_phase_1",(this));
431 param.ajouter_non_std("methode_interpolation_v",(this));
432 param.ajouter("parcours_interface",&variables_internes_->parcours_interface_);
433 param.ajouter_non_std("injecteur_interfaces",(this));
434 param.ajouter("suppression_sous_domaine",&suppression_interfaces_sous_domaine_);
435 param.ajouter("sous_domaine_volume_impose",&variables_internes_->nom_domaine_volume_impose_);
436 param.ajouter_flag("interpolation_repere_local", &interpolation_repere_local_);
437 param.ajouter_non_std("interpolation_champ_face",(this));
438 param.ajouter("n_iterations_interpolation_ibc",&variables_internes_->n_iterations_interpolation_ibc);
439 param.ajouter_non_std("type_vitesse_imposee",(this));
440 param.ajouter("nombre_facettes_retenues_par_cellule",&variables_internes_->nomb_fa7_accepted);
441 param.ajouter("seuil_convergence_uzawa",&variables_internes_->seuil_uzawa) ;
442 param.ajouter("nb_iteration_max_uzawa",&variables_internes_->nb_iter_uzawa) ;
443 param.ajouter_non_std("distance_IBC_faces",(this));
444 param.ajouter_non_std("distance_projete_faces",(this));
445 param.ajouter("temps_debut",&temps_debut_);
446 param.ajouter("vitesse_imposee_regularisee", &variables_internes_->vimp_regul) ;
447 param.ajouter_flag("explicit_u_NS", &explicit_u_NS_); // X_D_ADD_P rien Flag to force a really explicit scheme
448 param.ajouter_non_std("type_indic_faces", (this)) ;
449 param.ajouter("collision_model_fpi",&collision_model_); // x_d_ADD_P collision model for fluid particle interaction
450 param.ajouter_flag("compute_particles_rms",&compute_particles_rms_); // TODO x_D_ADD_P compute particles velocity root mean square
451 param.ajouter("post_process_hydrodynamic_forces", &post_process_hydro_forces_); // TODO x_D_ADD_P post process hydrodynamic forces (pressure + friction) for each particle
452}
453
455{
456 if (un_mot=="maillage")
457 {
458 //lecture des parametres du remaillage
460 return 1;
461 }
462 else if (un_mot=="methode_transport")
463 {
464 Motcles motcles2(3);
465 motcles2[0] = "vitesse_imposee";
466 motcles2[1] = "loi_horaire";
467 motcles2[2] = "vitesse_interpolee";
468 Motcle motlu;
469 is >> motlu;
470 Cerr << un_mot << " " << motlu << finl;
471 int rang = motcles2.search(motlu);
472 switch(rang)
473 {
474 case 0:
475 {
477 Cerr << " Transport velocity imposed : reading " << Objet_U::dimension
478 << " analytical expressions vx(x,y,[z,]t) vy(...) [vz(...)]" << finl;
479 // vitesse de deplacement de la phase 1 imposee
480 variables_internes_->methode_transport =
482 // lecture de Objet_U::dimension expressions analytiques
483 // contenant les composantes du champ de vitesse de transport
484 // (voir calculer_vitesse_imposee)
485 // Ce sont des fonctions de x,y,[z,]t
486 for (int i = 0; i < Objet_U::dimension; i++)
487 {
488 Nom& expression = variables_internes_->expression_vitesse_imposee[i];
489 is >> expression;
491 Cerr << " Component " << i << " of the velocity : " << expression << finl;
492 }
493 break;
494 }
495 case 1:
496 {
497 Cerr << " Imposed motion by the time scheme : ";
498 variables_internes_->methode_transport = Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE;
499 Nom nom_loi;
500 is >> nom_loi;
501 Cerr << nom_loi << finl;
502 variables_internes_->loi_horaire_ = ref_cast(Loi_horaire, Interprete::objet(nom_loi));
503 break;
504 }
505 case 2:
506 {
508 Cerr << " Transport velocity interpolated from the velocity \n"
509 << " of the following Navier_Stokes equation :" << finl;
510 // vitesse de deplacement interpolee a partir du champ de vitesse fluide
511 variables_internes_->methode_transport =
513 // lecture du nom de l'equation de navier_stokes :
514 Motcle nom_eq;
515 is >> nom_eq;
516 Cerr << nom_eq << finl;
517 variables_internes_->refequation_vitesse_transport =
518 ref_cast(Probleme_FT_Disc_gen,
519 probleme_base_.valeur()).equation_hydraulique(nom_eq);
520
521 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
522 if (sub_type(Navier_Stokes_FT_Disc,eqn_hydraulique))
523 {
524 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
526 // for fpi mmodule
527 set_is_solid_particle(ns.get_is_solid_particle()); // must be done before Collision_Model_FT::reprendre
530 }
531 break;
532 }
533 default:
534 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
535 << "The options for methode_transport are :\n"
536 << motcles2;
538 }
539 return 1;
540 }
541
542 else if (un_mot=="n_iterations_distance")
543 {
544 int n;
545 is >> n;
546 variables_internes_->n_iterations_distance = n;
548 Cerr << "Iterations number of the smoothing tool \"distance_interface\": " << n << finl;
549 return 1;
550 }
551 else if (un_mot=="iterations_correction_volume")
552 {
553 int n;
554 is >> n;
555 variables_internes_->iterations_correction_volume = n;
556 if (n>0)
557 variables_internes_->VOFlike_correction_volume = 1;
558 variables_internes_->nb_lissage_correction_volume = n; // Historical behavior was to set it to the same value as the nb of iterations
559 variables_internes_->nb_iterations_correction_volume = n;
561 {
562 Cerr << "Obsolete Keyword is read Iterations_correction_volume : " << n << finl;
563 Cerr << "For future compatibility, it is recommended to switch to the new syntax : " << finl;
564 if (n>0)
565 Cerr << " VOFlike_correction_volume 1 # a flag (0 or 1) for activation #" << finl;
566 else
567 Cerr << " VOFlike_correction_volume 0 # a flag (0 or 1) for activation #" << finl;
568 Cerr << " nb_lissage_correction_volume " << n << " # Select 0 or N the number of smoothing to apply to avoid potential spikes due to volume correction. #" << finl;
569 Cerr << " nb_iterations_correction_volume " << n << " # to iterate on the volume correction until seuil is reached. #" << finl;
570 // Note: looking at past commits, there may have been a mistake when changing these parameters.
571 // The value 'n' may be wrong and it may be better to use remaillage_interface().get_nb_iter_bary_volume_seul() for nb_iterations_correction_volume.
572 // If you are motivated, you can investigate.
573 Cerr << "The value of nb_iterations_correction_volume is read from bloc remaillage at keyword: nb_iter_correction_volume" << finl;
575 }
576 return 1;
577 }
578 else if (un_mot=="volume_impose_phase_1")
579 {
580 double x;
581 is >> x;
582 variables_internes_->volume_impose_phase_1 = x;
584 Cerr << "volume_impose_phase_1 : " << x << finl;
585 return 1;
586 }
587 else if (un_mot=="methode_interpolation_v")
588 {
589 Motcles motcles2(3);
590 motcles2[0] = "valeur_a_elem";
591 motcles2[1] = "vdf_lineaire";
592 motcles2[2] = "mean_volumic_velocity";
593 Motcle motlu;
594 is >> motlu;
596 Cerr << un_mot << " " << motlu << finl;
597 int rang = motcles2.search(motlu);
598 switch(rang)
599 {
600 case 0:
601 variables_internes_->methode_interpolation_v =
603 break;
604 case 1:
605 variables_internes_->methode_interpolation_v =
607 break;
608 case 2:
609 variables_internes_->methode_interpolation_v =
611 if (interpolation_repere_local_)
612 {
613 Cerr <<"ERROR : interpolation_repere_local should not be employed"
614 " with methode_interpolation_v::MEAN_VOLUMIC_VELOCITY !!!!!!!!!!!" << finl;
615 exit();
616 }
617 break;
618
619 default:
620 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
621 << "The options for " << un_mot << " are :\n"
622 << motcles2;
624 }
625 return 1;
626 }
627 else if (un_mot=="parcours_interface")
628 {
629 is >> variables_internes_->parcours_interface_;
630 return 1;
631 }
632 else if (un_mot=="injecteur_interfaces")
633 {
634 Nom nom_fichier;
635 is >> nom_fichier;
637 {
638 Cerr << "Reading of the interfaces to inject in the file " << nom_fichier << finl;
639 EFichier fic(nom_fichier);
640 ArrOfDouble& temps = variables_internes_->injection_interfaces_temps_;
641 ArrOfInt& phase = variables_internes_->injection_interfaces_phase_;
642 Noms& expr = variables_internes_->injection_interfaces_expressions_;
643 Nom une_expr;
644 while(1)
645 {
646 double t;
647 fic >> t;
648 if (fic.eof())
649 break;
650 temps.append_array(t);
651 int ph;
652 fic >> ph;
653 fic >> une_expr;
654 phase.append_array(ph);
655 expr.add(une_expr);
656 Cerr << "Time=" << t << " phase=" << ph << " expression=" << une_expr << finl;
657 }
658 }
659 envoyer_broadcast(variables_internes_->injection_interfaces_temps_, 0);
660 envoyer_broadcast(variables_internes_->injection_interfaces_phase_, 0);
661 envoyer_broadcast(variables_internes_->injection_interfaces_expressions_, 0);
662 barrier();
663 return 1;
664 }
665 else if (un_mot=="interpolation_champ_face")
666 {
667 Motcles motcles2(2);
668 motcles2[0] = "base";
669 motcles2[1] = "lineaire";
670 Motcle motbis;
671 is >> motbis;
672 int rang = motcles2.search(motbis);
673 switch(rang)
674 {
675 case 0:
676 variables_internes_->interpolation_champ_face =
678 break;
679 case 1:
680 {
681 variables_internes_->interpolation_champ_face =
683
684 Motcles mots;
685 mots.add("vitesse_fluide_explicite"); // vitesse utilisee pour calculer l'interpolation du schema lineaire
686 mots.add("extrapolation_diphasique_solide"); // le gradient est etendu dans les mailles diphasiques solides
687 mots.add("extrapolation_solide"); // le gradient est etendu dans les mailles solides
688 mots.add("distance_projete_face"); // utilisation de la distance reelle entre le barycentre de la face
689 // et le point projete (au lieu d'utiliser dSigma)
690
691 Motcle mot2;
692 is >> mot2;
693 Motcle accouverte = "{" , accfermee = "}" ;
694 if (mot2 == accouverte)
695 {
696 is >> mot2;
697
698 while (mot2 != accfermee)
699 {
700 int rang2 = mots.search(mot2);
701 switch(rang2)
702 {
703 case 0:
704 {
705 variables_internes_->vf_explicite = 1 ;
706 Cerr << "Lecture du type de vitesse fluide pour le calcul de v_imp : vf_explicite " << finl;
707 break;
708 }
709 case 1:
710 {
711 variables_internes_->is_extra_diphasique_solide = 1 ;
712 variables_internes_->is_extra_solide = 0 ;
713 Cerr << "Lecture du type d'extrapolation considere : diphasique_solide " << finl;
714 break;
715 }
716 case 2:
717 {
718 variables_internes_->is_extra_solide = 1 ;
719 variables_internes_->is_extra_diphasique_solide = 1 ;
720 Cerr << "Lecture du type d'extrapolation considere : solide " << finl;
721 break;
722 }
723 case 3:
724 {
725 variables_internes_->is_distance_projete_face = 1 ;
726 Cerr << "Lecture du type de distance consideree dans l'interpolation : distance reelle entre projete et face " << finl;
727 break;
728 }
729 }
730 is >> mot2;
731 }
732 }
733 else
734 {
735 Cerr << "Erreur a la lecture des parametres de l'interpolation lineaire : " << finl;
736 Cerr << "On attendait : " << accouverte << " , on a eu " << mot2 << finl;
738 }
739 break;
740 }
741 default:
742 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
743 << " les options de interpolation_champ_face sont :\n"
744 << motcles2;
746 }
747 }
748 else if (un_mot=="type_vitesse_imposee")
749 {
750 Motcles motcles2(2);
751 motcles2[0] = "uniforme";
752 motcles2[1] = "analytique";
753 Motcle motbis;
754 is >> motbis;
755 int rang = motcles2.search(motbis);
756 switch(rang)
757 {
758 case 0:
759 variables_internes_-> type_vitesse_imposee = Transport_Interfaces_FT_Disc_interne::UNIFORME;
760 break;
761 case 1:
762 variables_internes_-> type_vitesse_imposee = Transport_Interfaces_FT_Disc_interne::ANALYTIQUE;
763 break;
764 default:
765 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
766 << " les options de type_vitesse_imposee sont :\n"
767 << motcles2;
769 }
770 }
771 else if (un_mot=="distance_IBC_faces")
772 {
773 Motcles motcles2(2);
774 motcles2[0] = "initiale";
775 motcles2[1] = "modifiee";
776 Motcle motbis;
777 is >> motbis;
778
779 int rang = motcles2.search(motbis);
780 switch(rang)
781 {
782 case 0:
783 variables_internes_-> type_distance_calculee = Transport_Interfaces_FT_Disc_interne::DIST_INITIALE;
784 break;
785 case 1:
786 {
787 variables_internes_-> type_distance_calculee = Transport_Interfaces_FT_Disc_interne::DIST_MODIFIEE;
788 break;
789 }
790 default:
791 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
792 << " les options de distance_IBC_faces sont :\n"
793 << motcles2;
795 }
796 }
797 else if (un_mot=="distance_projete_faces")
798 {
799 Motcles motcles2(3);
800 motcles2[0] = "initiale";
801 motcles2[1] = "modifiee";
802 motcles2[2] = "simplifiee";
803 Motcle motbis;
804 is >> motbis;
805
806 int rang = motcles2.search(motbis);
807 switch(rang)
808 {
809 case 0:
810 variables_internes_-> type_projete_calcule = Transport_Interfaces_FT_Disc_interne::PROJETE_INITIAL;
811 break;
812 case 1:
813 variables_internes_-> type_projete_calcule = Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE;
814 break;
815 case 2:
816 variables_internes_-> type_projete_calcule = Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE;
817 break;
818 default:
819 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
820 << " les options de distance_projete_faces sont :\n"
821 << motcles2;
823 }
824 }
825 else if (un_mot=="type_indic_faces")
826 {
827 Motcles motcles2(3);
828 motcles2[0] = "standard";
829 motcles2[1] = "modifiee";
830 motcles2[2] = "ai_based";
831 Motcle motlu;
832 is >> motlu;
833 Cerr << un_mot << " " << motlu << finl;
834 int rang = motcles2.search(motlu);
835 switch(rang)
836 {
838 {
839 variables_internes_->type_indic_faces_ = Transport_Interfaces_FT_Disc_interne::STANDARD;
841 Cerr << " Standard interpolation of indicatrice to faces." << finl;
842 return 1;
843 }
845 {
847 Cerr << " Transport velocity imposed : reading " << Objet_U::dimension
848 << " analytical expressions vx(x,y,[z,]t) vy(...) [vz(...)]" << finl;
849
850 variables_internes_->type_indic_faces_ = Transport_Interfaces_FT_Disc_interne::MODIFIEE;
851 // modified_indic_faces_* : Valeurs de la position et de l epaisseur de l indicatrice modifiee,
852 // exprimees en multiples de taille de maille. Cette nouvelle indicatrice est calculee
853 // a partir de la distance a l interface. La position represente une iso-ligne
854 // de distance a l interface, et l epaisseur, le domaine de variation lineaire vis a vis de la distance,
855 // qui fait passer l indicatrice de 0 a 1 (le domaine est centre sur l iso-ligne representee par la position).
856 // Par defaut :
857 variables_internes_->modified_indic_faces_position = 0. ;
858 variables_internes_->modified_indic_faces_thickness= 1. ;
859 Motcles mots;
860 mots.add("position");
861 mots.add("thickness");
862
863 Motcle mot;
864 is >> mot;
865 Motcle accouverte = "{" , accfermee = "}" ;
866 if (mot == accouverte)
867 {
868 is >> mot;
869
870 while (mot != accfermee)
871 {
872 int rang2 = mots.search(mot);
873 switch(rang2)
874 {
875 case 0:
876 {
877 is >> variables_internes_->modified_indic_faces_position ;
878 Cerr << "Lecture de la position de l interface modifiee " << finl;
879 break;
880 }
881 case 1:
882 {
883 is >> variables_internes_->modified_indic_faces_thickness ;
884 if ( variables_internes_->modified_indic_faces_thickness < 0.)
885 {
886 Cerr << "L epaisseur de l interface doit etre positive ou nulle!!" << finl;
888 }
889 Cerr << "Lecture de l epaisseur de l interface modifiee " << finl;
890 break;
891 }
892 }
893 is >> mot;
894 }
895 }
896 else
897 {
898 Cerr << "Erreur a la lecture des parametres de l'indicatrice modifiee " << finl;
899 Cerr << "On attendait : " << accouverte << finl;
901 }
903 {
904 Cerr << "L indicatrice face sera calculee a partir de la distance. Position : d=" << variables_internes_->modified_indic_faces_position << "h ; Epaisseur : "<< variables_internes_->modified_indic_faces_thickness << "h" <<finl;
905 }
906 return 1;
907 }
909 {
910 variables_internes_->type_indic_faces_ = Transport_Interfaces_FT_Disc_interne::AI_BASED;
912 Cerr << " The interpolation of indicatrice to faces is based on the interfacial area"
913 << " and on the normal to the interface." << finl;
914 return 1;
915 }
916 default:
917 Cerr << "Transport_Interfaces_FT_Disc::lire\n"
918 << " les options de type_indic_faces sont :\n"
919 << motcles2;
921 }
922 }
923 else
925 return 1;
926}
927
928/*! @brief Methode appelee par Equation_base::readOn On verifie que toutes les cl sont de type Paroi_FT_disc.
929 *
930 * Fait Process::exit() si erreur.
931 *
932 */
934{
935 const Conds_lim& les_cl = le_dom_Cl_dis->les_conditions_limites();
936 const int n = les_cl.size();
937 int i;
938 for (i = 0; i < n; i++)
939 {
940 if (! sub_type(Paroi_FT_disc, les_cl[i].valeur()))
941 break;
942 }
943 if (i < n)
944 {
945 Cerr << "Error in Transport_Interfaces_FT_Disc::verif_Cl():\n"
946 << " Boundary conditions for Transport_Interfaces_FT_Disc must be\n"
947 << " of type Paroi_FT_disc (example : \"Paroi_FT_disc symetrie\")" << finl;
949 }
950 return 1;
951}
952
953template <int _DIM_>
954int facettes_trier_retirer_doublons(IntTab& fa7)
955{
956 using line = std::array<int, _DIM_>;
957 line* chunked_fa7 = reinterpret_cast<line*>(fa7.addr());
958 int nb_facettes = fa7.dimension(0);
959 int dim = _DIM_;
960 auto same_fa7 = [&](line A, line B)
961 {
962 // here, A and B are copies, so we can sort them
963 std::sort(A.begin(), A.end());
964 std::sort(B.begin(), B.end());
965 int cmp = 0;
966 for (int i = 0; i < dim; i++)
967 {
968 cmp = A[i] - B[i];
969 if (cmp != 0)
970 break;
971 }
972 return cmp;
973 };
974
975 // sorting
976 std::sort(chunked_fa7, chunked_fa7 + nb_facettes, [&](const line& fa1, const line& fa2)
977 {
978 return (same_fa7(fa1,fa2) < 0);
979 });
980
981 // cleaning
982 int count = 0;
983 for (int i = 1; i < nb_facettes; i++)
984 {
985 line& fa1 = chunked_fa7[i];
986 line& fa2 = chunked_fa7[i-1];
987 if(same_fa7(fa1,fa2)!=0)
988 {
989 count++;
990 for(int j=0; j<dim; j++)
991 fa7(count,j)=fa7(i,j);
992 }
993 }
994 fa7.resize(count+1,dim);
995 return count;
996}
997
999{
1000 Domaine dom;
1001 OBS_PTR(Domaine) ref_dom;
1002 Nom filename;
1003 ArrOfInt phase_specifiee;
1004 DoubleTab points;
1005 int default_phase = -1;
1006 Nom lata_file;
1007 Nom domain_name;
1008 int reverse_normal = 0;
1009
1010 Motcle motlu;
1011 is >> motlu;
1012 if (motlu != "{")
1013 {
1014 Cerr << "Error in Transport_Interfaces_FT_Disc::lire_cond_init, expected { after fichier_geom" << finl;
1015 Process::exit();
1016 }
1017
1018 Motcles motcles(6);
1019 motcles[0] = "fichier_geom";
1020 motcles[1] = "point_phase";
1021 motcles[2] = "default_phase";
1022 motcles[3] = "lata_dump";
1023 motcles[4] = "nom_domaine";
1024 motcles[5] = "reverse_normal";
1025 do
1026 {
1027 is >> motlu;
1028 if (motlu == "}")
1029 break;
1030 const int rang = motcles.search(motlu);
1031 switch(rang)
1032 {
1033 case 0:
1034 is >> filename;
1035 Cerr << " Reading .geom file in following file: " << filename << finl;
1036 break;
1037 case 1:
1038 {
1039 const int i = phase_specifiee.size_array();
1040 phase_specifiee.resize_array(i+1);
1041 points.resize(i+1, dimension);
1042 is >> phase_specifiee[i];
1043 Cerr << " Reading point in phase " << phase_specifiee[i];
1044 if (phase_specifiee[i] != 0 && phase_specifiee[i] != 1)
1045 {
1046 Cerr << " Error reading point_phase : expected 0 or 1" << finl;
1047 Process::exit();
1048 }
1049 for (int j = 0; j < dimension; j++)
1050 {
1051 is >> points(i, j);
1052 Cerr << " " << points(i,j);
1053 }
1054 Cerr << finl;
1055 break;
1056 }
1057 case 2:
1058 is >> default_phase;
1059 if (default_phase != 0 && default_phase != 1)
1060 {
1061 Cerr << " Error reading default_phase : expected 0 or 1" << finl;
1062 Process::exit();
1063 }
1064 Cerr << " Default phase : " << default_phase << finl;
1065 break;
1066 case 3:
1067 is >> lata_file;
1068 Cerr << " Dumping connex components and indicator function in lata file : "
1069 << lata_file << finl;
1070 break;
1071 case 4:
1072 is >> domain_name;
1073 Cerr << " Reading interface data in domain: " << domain_name << finl;
1074 break;
1075 case 5:
1076 reverse_normal = 1;
1077 Cerr << " Reverse_normal : swap nodes to reverse the normal vector of the surface mesh" << finl;
1078 break;
1079 default:
1080 Cerr << " Unknown keyword " << motlu
1081 << "\n Known keywords are " << motcles << finl;
1082 Process::exit();
1083 }
1084 }
1085 while (1);
1086
1087 if (filename != "??" && domain_name != "??")
1088 {
1089 Cerr << "Error: you specified both a .geom file name AND a domain name" << finl;
1090 Process::exit();
1091 }
1092 else if (filename == "??" && domain_name == "??")
1093 {
1094 Cerr << "Error: you must specify a FICHIER_GEOM or a NOM_DOMAINE" << finl;
1095 Process::exit();
1096 }
1097 if (filename != "??")
1098 {
1099 Cerr << "Reading geometry file and building interface mesh" << finl;
1100 if (is_a_binary_file(filename))
1101 {
1102 EFichierBin fic(filename);
1103 fic >> dom;
1104 }
1105 else
1106 {
1107 LecFicDiffuse fic(filename);
1108 fic >> dom;
1109 }
1110 ref_dom = dom;
1111 }
1112 else
1113 {
1114 Cerr << "Reading interface in existing domain: " << domain_name << finl;
1115 if (!sub_type(Domaine, Interprete::objet(domain_name)))
1116 {
1117 Cerr << "Error : object " << domain_name << " is not a domain" << finl;
1118 Process::exit();
1119 }
1120 ref_dom = ref_cast(Domaine, Interprete::objet(domain_name));
1121 }
1122 if (reverse_normal)
1123 {
1124 Cerr << "Reversing mesh normal vectors" << finl;
1125 Domaine& domaine = ref_dom.valeur();
1126 IntTab& elems = domaine.les_elems();
1127 const int nb_elem = elems.dimension(0);
1128 const int nb_som_elem = elems.line_size();
1129 if (nb_som_elem != 2 && nb_som_elem != 3)
1130 {
1131 Cerr << "Error: mesh has wrong dimension (must be segments in 2D, triangles in 3D)" << finl;
1132 Process::exit();
1133 }
1134 const int j0 = nb_som_elem - 2;
1135 for (int i = 0; i < nb_elem; i++)
1136 {
1137 const int s0 = elems(i, j0);
1138 const int s1 = elems(i, j0+1);
1139 elems(i, j0) = s1;
1140 elems(i, j0+1) = s0;
1141 }
1142 }
1143
1144 //MODIF SM 01/12/08
1145 //Effacer les fa7 doublons dans la cas d'un reprise d'un .MED parallele
1146 // Verification qu'il n'existe pas deux fois la meme facette
1147 {
1148 Scatter::uninit_sequential_domain(ref_dom.valeur());
1149 Domaine& domaine = ref_dom.valeur();
1150 IntTab& fa7 = domaine.les_elems();
1151
1152 // tri du tableau
1153 const int nb_facettes = fa7.dimension(0);
1154 assert(Objet_U::dimension == fa7.line_size());
1155
1156 int count = 0;
1157 if(Objet_U::dimension==2)
1158 count = facettes_trier_retirer_doublons<2>(fa7);
1159 else if(Objet_U::dimension == 3)
1160 count = facettes_trier_retirer_doublons<3>(fa7);
1161
1162 Scatter::init_sequential_domain(ref_dom.valeur());
1163 Cerr<<"End correction SM 12/08 the removed faces number is: "<< nb_facettes <<" - "<< count+1 << " = " << nb_facettes-count-1 << finl;
1164 }
1165 //Fin modif SM 01/12/08
1166
1167
1168 Cerr << "Building interface mesh" << finl;
1169 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
1171 Sauvegarde_Reprise_Maillage_FT::lire_xyz(maillage, &domaine_vf, 0, &(ref_dom.valeur()));
1172 Cerr << "Extracting connex components and assigning indicator function." << finl;
1173
1174 maillage.parcourir_maillage();
1175 const int nb_elem = domaine_vf.domaine().nb_elem();
1176 IntVect num_compo;
1177 domaine_vf.domaine().creer_tableau_elements(num_compo);
1178 // On marque avec -1 les elements traverses par une interface:
1179 const ArrOfInt& index_elem = maillage.intersections_elem_facettes().index_elem();
1180 {
1181 for (int i = 0; i < nb_elem; i++)
1182 {
1183 int n = 0;
1184 if (index_elem[i] >= 0)
1185 n = -1; // L'element est traverse par une interface
1186 num_compo[i] = n;
1187 }
1188 }
1189 num_compo.echange_espace_virtuel();
1190 const IntTab& elem_faces = domaine_vf.elem_faces();
1191 const IntTab& faces_elem = domaine_vf.face_voisins();
1192 const int nb_local_connex_components = search_connex_components_local(elem_faces, faces_elem, num_compo);
1193 const int nb_connex_components = compute_global_connex_components(num_compo, nb_local_connex_components);
1194
1195 //const int nb_connex_components = nb_local_connex_components;
1196 Cerr << " found " << nb_connex_components << " connex components" << finl;
1197 // Calcul de la phase a associer a chaque composante:
1198 ArrOfInt phase_of_component(nb_connex_components);
1199 phase_of_component= default_phase;
1200 // Pour chaque point ou la phase a ete specifiee, trouver l'element dans
1201 // lequel il se trouve, puis sa composante connexe et associer cette phase
1202 // a la composante connexe:
1203 const int nb_pts = phase_specifiee.size_array();
1204 if (nb_pts!=0)
1205 {
1206 ArrOfInt elem_points;
1207 domaine_vf.domaine().chercher_elements(points, elem_points);
1208 for (int i = 0; i < nb_pts; i++)
1209 {
1210 int composante_connexe = -2;
1211 if (elem_points[i] >= 0)
1212 composante_connexe = num_compo[elem_points[i]];
1213 // En general un seul processeur trouve le point chez lui, il distribue sa
1214 // trouvaille aux autres :
1215 composante_connexe = (int) mp_max(composante_connexe);
1216 if (composante_connexe == -2)
1217 {
1218 Cerr << "Error : point " << i << " is not in the domain" << finl;
1219 barrier();
1220 Process::exit();
1221 }
1222 else if (composante_connexe == -1)
1223 {
1224 Cerr << "Error : point " << i << " is in connex_component -1"
1225 << " (this point is in a mesh cell containing the interface)."
1226 << " Use the dump_lata keyword to find a point away from the interface" << finl;
1227 barrier();
1228 Process::exit();
1229 }
1230 else
1231 {
1232 const int phase = phase_specifiee[i];
1233 Cerr << "Assigning phase " << phase << " to component " << composante_connexe << finl;
1234 phase_of_component[composante_connexe] = phase;
1235 }
1236 }
1237 }
1238 // Met a jour l'indicatrice de phase:
1239 DoubleTab& indic = variables_internes_->indicatrice_cache->valeurs();
1240 for (int i = 0; i < nb_elem; i++)
1241 {
1242 const int compo = num_compo[i];
1243 if (compo >= 0)
1244 {
1245 const int phase = phase_of_component[compo];
1246 indic(i) = phase;
1247 }
1248 }
1249 // TODO : probablement plutot update_indicatrice_normale_distance(); ? A tester..
1251 // Postraitement des composantes connexes et de l'indicatrice
1252 if (lata_file != "??")
1253 {
1254 Cerr << "Writing lata file" << finl;
1255 Format_Post_Lata lata;
1256 const Domaine& un_dom = domaine_vf.domaine();
1257 constexpr double TEMPS = 0.;
1258 constexpr int FIRST_POST = 1;
1259 lata.initialize(lata_file, Format_Post_Lata::BINAIRE, "SIMPLE");
1260 lata.ecrire_entete(TEMPS, 0 /*reprise*/, FIRST_POST);
1261 lata.ecrire_domaine(un_dom, FIRST_POST);
1262 lata.ecrire_temps(TEMPS);
1263 DoubleTab data(nb_elem);
1264 for (int i = 0; i < nb_elem; i++)
1265 data(i) = num_compo(i);
1266 Noms unites;
1267 unites.add("-");
1268 Noms noms_compo;
1269 noms_compo.add("");
1270 Nom nom_dom(un_dom.le_nom());
1271
1272 Nom nom_champ("connex_component");
1273 lata.ecrire_champ(un_dom, unites, noms_compo, 1, TEMPS, nom_champ, nom_dom, "elem", "scalar",
1274 data);
1275 nom_champ = "indicatrice";
1276 lata.ecrire_champ(un_dom, unites, noms_compo, 1, TEMPS, nom_champ, nom_dom, "elem", "scalar",
1277 indic);
1278 nom_champ = "distance";
1279 lata.ecrire_champ(un_dom, unites, noms_compo, 1, TEMPS, nom_champ, nom_dom, "elem", "scalar",
1280 get_distance_interface().valeurs());
1281 }
1282 // permettra de passer le assert et de recalculer indic et distance dans le mettre_a_jour meme si c'est inutile dans ce cas
1283 // on a dû le faire une fois de trop ci-dessus pour permettre de le postprocesser juste avant ici.
1285
1286 if (phase_of_component.size_array() > 0 && min_array(phase_of_component) < 0)
1287 {
1288 Cerr << "Error: some connex components of the indicator function were not initialized\n"
1289 << " you must either specify more points or specify a default_phase.\n"
1290 << " With the lata_dump keyword, you can watch connex components and find where\n"
1291 << " points should be added." << finl;
1292 Process::exit();
1293 }
1294}
1295
1296
1297/*! @brief Lecture des conditions initiales.
1298 *
1299 * On s'attend a trouver ceci : { fonction EXPRESSION }
1300 * ou expression depend de x, y et z et sera interpretee par le
1301 * parser de TRUST. L'expression est envoyee a Marching_Cubes
1302 * pour construire l'interface.
1303 * Voir aussi parser et Marching_Cubes.
1304 *
1305 */
1307{
1309 Cerr << "Reading initial condition" << finl;
1310 Motcles motcles(4);
1311 motcles[0] = "fonction";
1312 motcles[1] = "fichier_geom";
1313 motcles[2] = "fonction_ignorer_collision";
1314 motcles[3] = "reprise";
1315 Motcle motlu;
1316 is >> motlu;
1317 if (motlu != "{")
1318 {
1319 Cerr << "Erreur dans Transport_Interfaces_FT_Disc::lire_cond_init\n";
1320 Cerr << " On attendait {\n On a trouve " << motlu << finl;
1321 Process::exit();
1322 }
1323 const Motcle virgule = ",";
1324 int init = 1;
1325 do
1326 {
1327 Maillage_FT_Disc maillage_tmp;
1328 maillage_tmp.associer_equation_transport(*this);
1329 //boucle sur la lecture des conditions intiales
1330 is >> motlu;
1331 int rang = motcles.search(motlu);
1332 switch (rang)
1333 {
1334 case 0:
1335 case 2:
1336 {
1338 if (init)
1339 {
1340 init = 0;
1341 }
1342 else
1343 {
1344 //a partir de la 2e interface ajoutee, il faut indiquer quelle phase on ajoute
1345 Motcle nom_phase;
1346 is >> nom_phase;
1347 if (nom_phase=="ajout_phase1")
1348 {
1350 }
1351 else if (nom_phase=="ajout_phase0")
1352 {
1354 }
1355 else
1356 {
1357 Cerr << "Transport_Interfaces_FT::lire_cond_init :\n";
1358 Cerr << " The keyword " << nom_phase << " is not understood.\n";
1359 Cerr << " Allowed keywords are : ajout_phase0 or ajout_phase1" << finl;
1360 assert(0);
1361 Process::exit();
1362 }
1363 }
1364 Nom expression;
1365 is >> expression;;
1366 if (probleme().reprise_effectuee())
1367 {
1368 Cerr << " Interface not build since a restarting is expected." << finl;
1369 }
1370 else
1371 {
1372 Cerr << " Interface construction : " << expression << finl;
1373 // Construction de l'interface comme l'isovaleur zero de la fonction
1374 // La valeur de la fonction "expression" aux sommets est temporairement stockee
1375 // dans distance_interface_sommets qui a la bonne structure d'espace virtuel
1376 // (items communs correctement initialises).
1377 int ignorer_collision = (rang==2);
1378 const int ok = marching_cubes().construire_iso(expression, 0., maillage_tmp,
1379 variables_internes_->indicatrice_cache->valeurs(),
1380 phase,
1381 variables_internes_->distance_interface_sommets,
1382 ignorer_collision);
1383 if (!ok)
1384 {
1385 if (ignorer_collision)
1386 Cerr << "Warning: the interface is colliding with an existing interface (ignorer_collision=1)." << finl;
1387 else
1388 {
1389 Cerr << "Error: the interface is colliding with an existing interface." << finl;
1390 barrier();
1391 Process::exit();
1392 }
1393 }
1394 maillage_interface().ajouter_maillage(maillage_tmp);
1395 }
1396 break;
1397 }
1398 case 1:
1399 {
1401 break;
1402 }
1403 case 3:
1404 {
1405 Nom file;
1406 is >> file;
1407 if (!file.finit_par(".xyz"))
1408 {
1409 Cerr << "A .xyz file is waited to restart the calculation for the interface equation." << finl;
1410 Process::exit();
1411 }
1412 int mode_lec_sa = EcritureLectureSpecial::mode_lec;
1414 EFichierBin is2(file);
1415 Motcle tmp;
1416 int version;
1417 is2 >> tmp >> version; // FORMAT_SAUVEGARDE: VERSION
1418 reprendre(is2);
1420 break;
1421 }
1422 default:
1423 Cerr << "Transport_Interfaces_FT::lire_cond_init :\n";
1424 Cerr << " The keyword " << motlu << " is not understood here.\n";
1425 Cerr << " Allowed keywords are :\n" << motcles << finl;
1426 Process::exit();
1427 }
1428 is >> motlu;
1429 Cerr<<"lectureF "<<motlu<<finl;
1430 }
1431 while (motlu==virgule);
1432
1433 if (motlu != "}")
1434 {
1435 Cerr << "Error for method Transport_Interfaces_FT_Disc::lire_cond_init\n";
1436 Cerr << " A } was expected\n It has been found " << motlu << finl;
1437 Process::exit();
1438 }
1439
1440 return is;
1441}
1442
1444{
1445 assert(!probleme_base_);
1446 if ( (! sub_type(Probleme_FT_Disc_gen, un_probleme))
1447 && !(un_probleme.is_dilatable()))
1448 {
1449 Cerr << "Error for method Transport_Interfaces_FT_Disc::associer_pb_base\n";
1450 Cerr << " The Transport_Interfaces_FT_Disc equation must be associated to a problem\n";
1451 Cerr << " of type Probleme_FT_Disc_gen" << finl;
1452 Cerr << " or type Pb_Thermohydraulique_Especes_QC" << finl;
1453 Cerr << " or type Pb_Thermohydraulique_Especes_Turbulent_QC" << finl;
1454 Process::exit();
1455 }
1456 probleme_base_ = un_probleme;
1458
1459 Nom pb_name = un_probleme.le_nom();
1460 variables_internes_->set_pb_name(pb_name);
1461}
1462
1463/*! @brief Discretisation des champs: - indicatrice_ : champ scalaire discretise aux elements
1464 *
1465 * - typage du maillage et de l'algorithme marching cubes
1466 *
1467 */
1469{
1470 // Le nom des differents champs est un identifiant (indicatrice, vitesse, ...)
1471 // suivi de "_nom_de_l_equation" :
1472 Nom suffix("_");
1473 suffix += le_nom();
1474 variables_internes_->set_ident(le_nom());
1475
1476 const Discretisation_base& dis = discretisation();
1477 const double temps = schema_temps().temps_courant();
1478 const Domaine_dis_base& mon_dom_dis = domaine_dis();
1479 const int nb_valeurs_temps = schema_temps().nb_valeurs_temporelles();
1480
1481 Nom fieldname;
1482 fieldname = "INDICATRICE";
1483 fieldname += suffix;
1484 dis.discretiser_champ("champ_elem", mon_dom_dis,
1485 fieldname, "-",
1486 1 /* composantes */, nb_valeurs_temps,
1487 temps,
1488 indicatrice_);
1489 indicatrice_->associer_eqn(*this);
1490 //Nouvelle formulation
1491 champs_compris_.ajoute_champ(indicatrice_);
1492 //champs_compris_.liste_noms_compris()[0]+le_nom();
1493
1494 fieldname = "INDICATRICE_CACHE";
1495 fieldname += suffix;
1496 dis.discretiser_champ("champ_elem", mon_dom_dis,
1497 fieldname, "-",
1498 1 /* composantes */, 1 /* valeur temporelle */,
1499 temps,
1500 variables_internes_->indicatrice_cache);
1501 variables_internes_->indicatrice_cache->associer_eqn(*this);
1502 champs_compris_.ajoute_champ(variables_internes_->indicatrice_cache);
1503 variables_internes_->indicatrice_cache->PDI_save_type(true);
1504
1505 //champs_compris_.liste_noms_compris()[1]+le_nom();
1506
1507 fieldname = "INDICATRICE_FACES";
1508 fieldname += suffix;
1509 dis.discretiser_champ("vitesse", mon_dom_dis,
1510 fieldname, "-",
1511 1 /* composantes */, nb_valeurs_temps,
1512 temps,
1513 indicatrice_faces_);
1514 indicatrice_faces_->associer_eqn(*this);
1515 champs_compris_.ajoute_champ(indicatrice_faces_);
1516
1517 fieldname = "VITESSE_FILTREE";
1518 fieldname += suffix;
1519 dis.discretiser_champ("vitesse", mon_dom_dis,
1520 fieldname, "m/s",
1521 Objet_U::dimension /* composantes */, 1, /* valeur temporelle */
1522 temps,
1523 variables_internes_->vitesse_filtree);
1524 variables_internes_->vitesse_filtree->associer_eqn(*this);
1525 champs_compris_.ajoute_champ(variables_internes_->vitesse_filtree);
1526 //champs_compris_.liste_noms_compris()[2]+le_nom();
1527
1528 fieldname = "FLUX_TMP";
1529 fieldname += suffix;
1530 dis.discretiser_champ("vitesse", mon_dom_dis,
1531 fieldname, "m/s",
1532 1 /* composantes */,
1533 temps,
1534 variables_internes_->tmp_flux);
1535 champs_compris_.ajoute_champ(variables_internes_->tmp_flux);
1536 //champs_compris_.liste_noms_compris()[2]+le_nom();
1537
1538 fieldname = "INDEX_ELEM";
1539 dis.discretiser_champ("champ_elem", mon_dom_dis,
1540 fieldname, "m",
1541 Objet_U::dimension /* composantes */,
1542 temps,
1543 variables_internes_->index_element);
1544 champs_compris_.ajoute_champ(variables_internes_->index_element);
1545
1546 fieldname = "NELEM_PAR_DIRECTION";
1547 dis.discretiser_champ("champ_elem", mon_dom_dis,
1548 fieldname, "m",
1549 1 /* composantes */,
1550 temps,
1551 variables_internes_->nelem_par_direction);
1552 champs_compris_.ajoute_champ(variables_internes_->nelem_par_direction);
1553
1554 fieldname = "DISTANCE_INTERFACE_ELEM";
1555 fieldname += suffix;
1556 dis.discretiser_champ("champ_elem", mon_dom_dis,
1557 fieldname, "m",
1558 1 /* composantes */,
1559 temps,
1560 variables_internes_->distance_interface);
1561 champs_compris_.ajoute_champ(variables_internes_->distance_interface);
1562
1563 fieldname = "DISTANCE_INTERFACE_FACE";
1564 fieldname += suffix;
1565 dis.discretiser_champ("vitesse", mon_dom_dis,
1566 fieldname, "m",
1567 1 /* composantes */,
1568 temps,
1569 variables_internes_->distance_interface_faces);
1570 champs_compris_.ajoute_champ(variables_internes_->distance_interface_faces);
1571
1572 fieldname = "DISTANCE_INTERFACE_FACE_COR";
1573 fieldname += suffix;
1574 dis.discretiser_champ("vitesse", mon_dom_dis,
1575 fieldname, "m",
1576 1 /* composantes */,
1577 temps,
1578 variables_internes_->distance_interface_faces_corrigee);
1579 champs_compris_.ajoute_champ(variables_internes_->distance_interface_faces_corrigee);
1580
1581 fieldname = "DISTANCE_INTERFACE_FACE_DIF";
1582 fieldname += suffix;
1583 dis.discretiser_champ("vitesse", mon_dom_dis,
1584 fieldname, "m",
1585 1 /* composantes */,
1586 temps,
1587 variables_internes_->distance_interface_faces_difference);
1588 champs_compris_.ajoute_champ(variables_internes_->distance_interface_faces_difference);
1589
1590 fieldname = "VITESSE_IMP_INTERP";
1591 fieldname += suffix;
1592 dis.discretiser_champ("vitesse", mon_dom_dis,
1593 fieldname, "m",
1594 -1 /* composantes */,
1595 temps,
1596 vitesse_imp_interp_);
1597 champs_compris_.ajoute_champ(vitesse_imp_interp_);
1598
1599 //champs_compris_.liste_noms_compris()[3]+le_nom();
1600
1601 // Construction de la structure du tableau avec l'espace virtuel:
1602 {
1603 DoubleTab& d = variables_internes_->distance_interface_sommets;
1604 const Domaine& dom = domaine_dis().domaine();
1605 d.resize(0);
1606 dom.creer_tableau_sommets(d);
1607 }
1608 variables_internes_->distance_interface_sommets = 0.;
1609
1610 fieldname = "NORMALE_INTERFACE";
1611 fieldname += suffix;
1612 dis.discretiser_champ("champ_elem", mon_dom_dis,
1613 fieldname, "-",
1614 Objet_U::dimension /* composantes */,
1615 temps,
1616 variables_internes_->normale_interface);
1617 champs_compris_.ajoute_champ(variables_internes_->normale_interface);
1618 //champs_compris_.liste_noms_compris()[4]+le_nom();
1619
1620 //GB : Ajout du post-traitement de l'aire interfaciale par cellule :
1621 fieldname = "SURFACE_INTERFACE";
1622 fieldname += suffix;
1623 dis.discretiser_champ("champ_elem", mon_dom_dis,
1624 fieldname, "m2",
1625 1 /* composantes */,
1626 temps,
1627 variables_internes_->surface_interface);
1628 champs_compris_.ajoute_champ(variables_internes_->surface_interface);
1629 //GB : Fin de l'ajout.
1630
1632 {
1633 //TF : Ajout de la gestion de la derivee en temps
1634 fieldname = "TIME_DERIVATIVE_INTERFACE";
1635 fieldname += suffix;
1636 dis.discretiser_champ(Motcle("champ_elem"), mon_dom_dis,
1637 fieldname, Nom(""),
1638 1 /* composantes */,
1639 schema_temps().nb_valeurs_temporelles(),
1640 temps,
1641 derivee_en_temps_);
1642 //TF : Fin de l'ajout
1643 }
1644
1646 {
1647 // On modifie le domaine ici => on a besoin d'une reference non constante
1648 Domaine_dis_base& le_dom_dis2 = domaine_dis();
1649 le_dom_dis2.domaine().construire_elem_virt_pe_num();
1650 }
1651 {
1652 Domaine_VF& domaine_vf = ref_cast_non_const(Domaine_VF, mon_dom_dis);
1653 domaine_vf.construire_face_virt_pe_num();
1654 variables_internes_->connectivite_frontieres_.associer_domaine_vf(domaine_vf);
1655 }
1656 {
1657 Parcours_interface& parcours = variables_internes_->parcours_interface_;
1660 }
1661 {
1662 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
1663 marching_cubes().associer_domaine_vf(domaine_vf);
1664 }
1667
1668 variables_internes_->algorithmes_transport_.typer("Algorithmes_Transport_FT_Disc");
1669 // On n'appelle pas Equation_base::discretiser car on ne veut pas
1670 // de solveur masse.
1671
1672 Cerr << "Discretizing of the boundary conditions... ";
1673 le_dom_Cl_dis.typer(discretisation().domaine_cl_dis_type());
1674 le_dom_Cl_dis->associer(domaine_dis());
1675 Cerr << " OK " << finl;
1676
1677 le_dom_Cl_dis->associer_eqn(*this);
1678 le_dom_Cl_dis->associer_inconnue(inconnue());
1679
1680}
1681
1682/*! @brief Remaillage de l'interface : - amelioration petites et grandes facettes,
1683 *
1684 * - barycentrage,
1685 * - gestion des coalescences-fragmentations.
1686 *
1687 */
1689{
1690 Journal() << "Transport_Interfaces_FT_Disc::remailler_interface " << le_nom() << finl;
1691 const double temps = schema_temps().temps_courant();
1693 // Ce champ sera mis a jour si on realise un remaillage global...
1694 Champ_base& indicatrice = variables_internes_->indicatrice_cache.valeur();
1695 Remaillage_FT& algo_remaillage_local = remaillage_interface();
1696 Topologie_Maillage_FT& algo_topologie = topologie_interface();
1697 algo_topologie.remailler_interface(temps, maillage, indicatrice, algo_remaillage_local);
1698}
1699
1701{
1702
1703 if (not(preparer_calcul_anticipated_done_))
1704 {
1706 }
1707 else
1708 {
1709 Process::Journal()<<"Transport_Interfaces_FT_Disc::preparer_calcul does nothing because it has been anticipated in the problem"<<finl;
1710 }
1711 return 1;
1712}
1713
1715{
1716 Process::Journal()<<"Transport_Interfaces_FT_Disc::preparer_calcul"<<finl;
1717
1718 preparer_calcul_anticipated_done_ = true;
1719
1721 {
1722 compute_nb_particles_tot(); // must be done before Collision_Model_FT::reprendre
1724 mean_particles_volumic_velocity_.resize(nb_particles_tot_,dimension);
1725 mean_particles_volumic_squared_velocity_.resize(nb_particles_tot_,dimension);
1726 rms_particles_volumic_velocity_.resize(nb_particles_tot_,dimension);
1727 particles_purely_solid_mesh_volume_.resize(nb_particles_tot_);
1728 post_process_hydro_forces_.associate_ns_equation(equation_ns_);
1729 post_process_hydro_forces_.associate_transport_equation(*this);
1730 post_process_hydro_forces_Stokes_.associate_ns_equation(equation_ns_);
1731 post_process_hydro_forces_Stokes_.associate_transport_equation(*this);
1733 post_process_hydro_forces_.resize_and_init_tables(nb_particles_tot_);
1734 post_process_hydro_forces_Stokes_.resize_and_init_tables(nb_particles_tot_);
1735 }
1736
1737 if (collision_model_)
1738 {
1739 const Navier_Stokes_FT_Disc& ns = equation_ns_.valeur();
1740 const Domaine_VDF& domain_vdf = ref_cast(Domaine_VDF, domaine_dis());
1741 const Schema_Comm& schema_comm_FT=maillage_interface().get_schema_comm_FT();
1742 collision_model_.valeur().preparer_calcul(domain_vdf, nb_particles_tot_,
1743 ns, *this, schema_comm_FT);
1744 }
1745
1746 const double temps = schema_temps().temps_courant();
1747 // La ligne suivante doit figurer avant le premier remaillage
1748 // car le remaillage utilise les angles de contact (lissage courbure)
1749 le_dom_Cl_dis->initialiser(temps);
1750
1751 if (probleme().reprise_effectuee())
1752 {
1753 Cerr << "Calculation restarting : no initial meshing" << finl;
1754 }
1755 else
1756 {
1757 Cerr << "Initial condition remeshing." << finl;
1758 //maillage_interface().nettoyer_maillage(); // GB : Pour supprimer toutes ces facettes nulles...
1760 //maillage_interface().nettoyer_maillage(); // GB : Pour supprimer toutes ces facettes nulles...
1761 }
1762
1763 // Ajout pour la sauvegarde au premier pas de temps si reprise
1764 indicatrice_->changer_temps(temps);
1765 variables_internes_->indicatrice_cache->changer_temps(temps);
1766 indicatrice_faces_->changer_temps(temps);
1767 variables_internes_->vitesse_filtree->changer_temps(temps);
1768 variables_internes_->tmp_flux->changer_temps(temps);
1769 variables_internes_->index_element->changer_temps(temps);
1770 variables_internes_->nelem_par_direction->changer_temps(temps);
1771 variables_internes_->distance_interface->changer_temps(temps);
1772 variables_internes_->distance_interface_faces->changer_temps(temps);
1773 variables_internes_->distance_interface_faces_corrigee->changer_temps(temps);
1774 variables_internes_->distance_interface_faces_difference->changer_temps(temps);
1775 vitesse_imp_interp_->changer_temps(temps);
1776 variables_internes_->normale_interface->changer_temps(temps);
1777 variables_internes_->surface_interface->changer_temps(temps);
1778
1779 const Nom& checkpoint_fname = get_probleme_base().checkpoint_filename();
1780 variables_internes_->set_checkpoint_fname(checkpoint_fname);
1781
1782 //calcul de l'indicatrice
1785
1786 // On verifie que la methode de transport a bien ete fournie dans le jeu
1787 // de donnees:
1788 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::INDEFINI)
1789 {
1790 Cerr << "Error for the method Transport_Interfaces_FT_Disc::preparer_calcul\n"
1791 << "The transport method has not indicated for the equation\n"
1792 << le_nom() << finl;
1793 assert(0);
1794 Process::exit();
1795 }
1796
1797 // Pour le premier postraitement :
1798 //variables_internes_->maillage_pour_post.recopie(maillage,
1799 // Maillage_FT_Disc::MINIMAL);
1800
1801 //Ajout TF : gestion de la derivee en temps
1803 //Fin TF
1804 return 1;
1805}
1806
1808{
1809 // PDI not supported for FT so writing front in xyz format
1810 variables_internes_->init_save_file();
1811}
1812
1814{
1815 variables_internes_->close_save_file();
1816}
1817
1822
1824{
1825 // TODO:
1826 // We should think of implementing it as in eq. 16 for instance:
1827 // https://hal.archives-ouvertes.fr/hal-02304125/document
1828 // and use the Lagrangian min edge length instead of Delta_x.
1829 //
1830 // Ou encore :
1831 // Par ailleurs du fait de la contrainte sur le pas de temps capillaire (Popinet 2009) cette approche
1832 // connait egalement des limites (Pierson 2021). En effet, quand les films deviennent suffisamment minces,
1833 // et que les cellules composant le film sont suffisamment petites, le pas de temps necessaire au calcul
1834 // decroit drastiquement, comme la taille des cellules a la puissance trois-demi.
1835 // Pierson, J. (2021). Numerical study of drop bouncing on a fluid-fluid interface. ICTAM, Milan.
1836 // Popinet, S. (2020). A vertically-Lagrangian, non-hydrostatic, multilayer model for multiscale free-surface flows. Journal of Computational Physics, 109609
1837 //
1838 return DMAXFLOAT;
1839}
1840
1841/*! @brief Updates normals and distances to interface, then updates indicatrice
1842 *
1843 * calls Maillage_FT_Disc::parcourir_maillage() first.
1844 * calls update_normale_distance_interface then update_indicatrice
1845 */
1847{
1848 // Si le Maillage_FT_Disc::MINIMAL, le parcourir:
1850
1851 // L'indicatrice a besoin de la distance Eulerienne (type LS) pour etre calculee
1852 // (plus precisement, la distance permet de la corriger localement):
1855}
1856
1857/*! @brief Calcule la normale et la distance a l'interface,
1858 * evaluees sur une epaisseur egale a n_iterations_distance aux elements et discretisee aux elements
1859 *
1860 */
1862{
1863 const int tag = maillage_interface().get_mesh_tag();
1864
1865 // Check if the call is useful
1866 if (tag == variables_internes_->distance_normale_cache_tag)
1867 {
1868 Cerr << "WARNING : Unneeded call to Transport_Interfaces_FT_Disc::update_normale_distance_interface" << finl;
1869 Cerr << " mesh tag: " << tag << ", cache tag: "<< variables_internes_->distance_normale_cache_tag << finl;
1870 Process::exit();
1871 }
1872
1873 DoubleTab& distance = variables_internes_->distance_interface->valeurs();
1874 DoubleTab& normale = variables_internes_->normale_interface->valeurs();
1876 distance,
1877 normale,
1878 variables_internes_->n_iterations_distance);
1879 variables_internes_->distance_normale_cache_tag = tag;
1880}
1881
1882/*! @brief Recalcul du champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
1883 *
1884 * ATTENTION, ce n'est pas l'inconnue du probleme. L'inconnue est mise a jour
1885 * a partir de ce champ dans mettre_a_jour.
1886 *
1887 */
1889{
1890 const int tag = maillage_interface().get_mesh_tag();
1891
1892 // Check if the call is useful
1893 // can be bypassed by changing the tag before calling update_indicatrice (use this knowledge carefully)
1894 if (tag == variables_internes_->indicatrice_cache_tag)
1895 {
1896 Cerr << "WARNING : Unneeded call to Transport_Interfaces_FT_Disc::update_indicatrice. tag = " << tag << finl;
1897 Cerr << " indicatrice is already up to date" << finl;
1898 Process::exit();
1899 }
1900
1901 // Le calcul de l'indicatrice a besoin d'une distance qui soit bien a jour...
1902 if (tag != variables_internes_->distance_normale_cache_tag)
1903 {
1904 Cerr << "ERROR : in Transport_Interfaces_FT_Disc::update_indicatrice : distance_normale not up to date" << finl;
1905 Cerr << " Call update_indicatrice_normale_distance before or update_normale_distance_interface to do both at the same time" << finl;
1906 Cerr << " mesh tag: " << tag << ", cache tag: "<< variables_internes_->distance_normale_cache_tag << finl;
1907 Process::exit();
1908 }
1909
1910 // Voir s'il manque un appel a maillage_interface().parcourir_maillage()
1911 if (not(maillage_interface().type_statut()>=Maillage_FT_Disc::PARCOURU))
1912 {
1913 Cerr << "ERROR : in Transport_Interfaces_FT_Disc::update_indicatrice : maillage pas parcouru" << finl;
1914 Process::exit();
1915 }
1916
1917 DoubleVect& valeurs_indicatrice = variables_internes_->indicatrice_cache->valeurs();
1918
1919
1920 maillage_interface().calcul_indicatrice(valeurs_indicatrice, valeurs_indicatrice);
1921 variables_internes_->indicatrice_cache_tag = tag;
1922
1923 // TODO : nettoyer ce doublon de champs historique pour ne garder qu'un champ
1924 indicatrice_->valeurs() = get_indicatrice().valeurs(); // met a jour l'indicatrice a partir de indicatrice_cache qui vient d'etre calculee.
1925}
1926
1927/*! @brief Checks if the indicator is up to date
1928 *
1929 * Exits if it is not the case. To be used when we want to be sure that update_indicatrice has been called recently enough.
1930 * The same test is also done in Transport_Interfaces_FT_Disc::get_indicatrice
1931 *
1932 */
1934{
1935 const int tag = maillage_interface().get_mesh_tag();
1936 if (tag != variables_internes_->indicatrice_cache_tag)
1937 {
1938 Cerr << "Error: indicatrice not up to date" << finl;
1939 Process::exit();
1940 }
1941}
1942
1943/*! @brief getter champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
1944 *
1945 * ATTENTION, ce n'est pas l'inconnue du probleme. L'inconnue est mise a jour
1946 * a partir de ce champ dans mettre_a_jour.
1947 *
1948 */
1950{
1951 const int tag = maillage_interface().get_mesh_tag();
1952 if (tag != variables_internes_->indicatrice_cache_tag)
1953 {
1954 Cerr << "Error: indicatrice not up to date in get_indicatrice. " << finl;
1955 Process::exit();
1956 }
1957 return variables_internes_->indicatrice_cache.valeur();
1958}
1959
1961{
1962 const int tag = maillage_interface().get_mesh_tag();
1963 if (tag != variables_internes_->distance_normale_cache_tag)
1964 {
1965 Cerr << "Error: indicatrice not up to date in get_distance_interface. " << finl;
1966 Process::exit();
1967 }
1968 return variables_internes_->distance_interface.valeur();
1969}
1970
1972{
1973 const int tag = maillage_interface().get_mesh_tag();
1974 if (tag != variables_internes_->distance_normale_cache_tag)
1975 {
1976 Cerr << "Error: indicatrice not up to date in get_normale_interface. " << finl;
1977 Process::exit();
1978 }
1979 return variables_internes_->normale_interface.valeur();
1980}
1981
1982/*! @brief Interpolation lineaire d'un champ de vitesse VDF aux faces en un point de coordonnees coord_som.
1983 *
1984 * Le point coord_som est suppose se trouver dans
1985 * l'element "element".
1986 * Pour chaque composante, on cherche le cube contenant coord_som et dont
1987 * les sommets sont des noeuds de vitesse pour cette composante et on
1988 * interpole lineairement dans ce cube. Au bord du domaine, la vitesse
1989 * tangentielle dans le demi-element colle a la paroi est la vitesse
1990 * discrete de l'element (la condition aux limites n'est PAS utilisee).
1991 *
1992 */
1993void interpoler_vitesse_point_vdf(const Champ_base& champ_vitesse,
1994 const FTd_vecteur3& coord_som,
1995 const int element,
1996 FTd_vecteur3& vitesse,
1997 const int future_or_past)
1998{
1999 const DoubleTab& valeurs_v = (bool)(future_or_past) ? champ_vitesse.futur() : champ_vitesse.valeurs();
2000 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, champ_vitesse.domaine_dis_base());
2001 const IntTab& elem_faces = domaine_vf.elem_faces();
2002 const DoubleTab& xv = domaine_vf.xv();
2003 const DoubleTab& xp = domaine_vf.xp();
2004 const IntTab& face_voisins = domaine_vf.face_voisins();
2005
2006 // La vitesse est la moyenne ponderee des 4 ou 8 vitesses
2007 // aux faces qui encadrent le sommet.
2008 // On designe par i,j,k l'une des 8 faces, avec 0<=i<=1, 0<=j<=1, 0<=k<=1.
2009 // La composante vitesse au sommet est
2010 // vitesse = SOMME(vitesse(face_i,j,k)*coef[0]*coef[1]*coef[2]);
2011 // Exemple : interpolation de la composante horizontale de vitesse
2012 // pour le sommet "x". On fait une interpolation bilineaire
2013 // entre les quatre composantes horizontales de vitesses v (8 vitesses en 3d)
2014 // On a besoin de l'element voisin situe au dessus car le sommet
2015 // est dans la moitie superieure de l'element :
2016 // --------
2017 // | |
2018 // | v10 | v11
2019 // |--> |-->
2020 // | |
2021 // | |
2022 // --------
2023 // | x |
2024 // | v00 | v01
2025 // |--> |-->
2026 // | |
2027 // | |
2028 // --------
2029
2030 // Boucle sur les 2 ou 3 composantes de la vitesse
2031 int compo;
2032 const int dim = Objet_U::dimension;
2033 for (compo = 0; compo < dim; compo++)
2034 {
2035 // ****
2036 // Calcul des 2 ou 3 coefficients de ponderation coef[x]
2037 // ****
2038 double coef[3];
2039 // Numeros des elements voisins dans chaque direction
2040 // (le numero de l'element voisins dans la direction "compo" n'est pas
2041 // utilise et reste a -1)
2042 int elem_voisins[3] = { -1, -1, -1 };
2043 // Indice local de la face de "element" qui est commune avec elem_voisin[i]:
2044 int indice_local_face_voisine[3] = { -1, -1, -1 };
2045 // Numero du quatrieme element utilise pour interpoler la vitesse
2046 // (les elements utilises en 3D sont "element", "elem_voisins[(compo+1)%3]",
2047 // "elem_voisins[(compo+2)%3]" et "elem_diagonal".
2048 int elem_diagonal = -1;
2049
2050 // Boucle sur les 2 ou 3 dimensions du cube dans lequel on interpole la valeur
2051 int direction;
2052 for (direction = 0; direction < dim; direction++)
2053 {
2054 // Coordonnee du point ou il faut interpoler la vitesse
2055 const double x = coord_som[direction];
2056 double a; // Le coef d'interpolation dans la direction
2057 if (direction == compo)
2058 {
2059 // Dans la direction de la composante traitee on interpole
2060 // entre les deux faces opposees de l'element. Coordonnees
2061 // de ces faces :
2062 const int face_inf_compo = elem_faces(element, compo);
2063 const int face_sup_compo = elem_faces(element, compo + dim);
2064 const double xmin = xv(face_inf_compo, direction);
2065 const double xmax = xv(face_sup_compo, direction);
2066 a = (xmax - x) / (xmax - xmin);
2067 }
2068 else
2069 {
2070 // Dans les autres directions, on cherche les faces des
2071 // elements voisins si elles existent.
2072 // Calcul de l'element voisin a utiliser: le plus proche du point
2073 // a interpoler
2074 const double centre_elem = xp(element, direction);
2075 // Indice local dans l'element de la face la plus proche dans la
2076 // direction i
2077 const int i_face_voisine = direction + ((x < centre_elem) ? 0 : dim);
2078 // Indice de la face dans le domaine
2079 const int face_voisine = elem_faces(element, i_face_voisine);
2080 // Indice de l'element voisin par cette face
2081 const int elem_voisin =
2082 face_voisins(face_voisine, 0) + face_voisins(face_voisine, 1) - element;
2083 if (elem_voisin >= 0)
2084 {
2085 // Il y a un voisin: coordonnee du centre de la face voisine
2086 const double centre_voisin = xp(elem_voisin, direction);
2087 a = (centre_voisin - x) / (centre_voisin - centre_elem);
2088 elem_voisins[direction] = elem_voisin;
2089 indice_local_face_voisine[direction] = i_face_voisine;
2090 }
2091 else
2092 {
2093 // Pas de voisin (face de bord). La vitesse est supposee constante
2094 // dans la direction "i".
2095 a = 1.;
2096 }
2097 }
2098 if (a < 0.)
2099 a = 0.;
2100 if (a > 1.)
2101 a = 1.;
2102 coef[direction] = a;
2103 }
2104
2105 if (dim == 3)
2106 {
2107 const int direction1 = (compo + 1) % 3;
2108 const int direction2 = (compo + 2) % 3;
2109 const int elem_voisin1 = elem_voisins[direction1];
2110 const int elem_voisin2 = elem_voisins[direction2];
2111 // Recherche de l'element diagonal:
2112 if (elem_voisin1 >= 0 && elem_voisin2 >= 0)
2113 {
2114 // On cherche l'element voisin de elem_voisin1 dans la direction direction2:
2115 int i_face_voisine, face_voisine, elem_diagonal1, elem_diagonal2;
2116
2117 i_face_voisine = indice_local_face_voisine[direction2];
2118 face_voisine = elem_faces(elem_voisin1, i_face_voisine);
2119 // element diagonal obtenu par le voisin de elem_voisin1:
2120 elem_diagonal1 = face_voisins(face_voisine, 0)
2121 + face_voisins(face_voisine, 1) - elem_voisin1;
2122 if (elem_diagonal1 >= 0)
2123 {
2124 // Ok, on a un element diagonal, on verifie qu'on l'a aussi par
2125 // l'autre cote (voisin de elem_voisin2 dans la direction direction1) :
2126 i_face_voisine = indice_local_face_voisine[direction1];
2127 face_voisine = elem_faces(elem_voisin2, i_face_voisine);
2128 // element diagonal obtenu par le voisin de elem_voisin2:
2129 elem_diagonal2 = face_voisins(face_voisine, 0)
2130 + face_voisins(face_voisine, 1) - elem_voisin2;
2131 if (elem_diagonal1 == elem_diagonal2)
2132 {
2133 // Les deux elements existent et sont identiques:
2134 elem_diagonal = elem_diagonal1;
2135 }
2136 else
2137 {
2138 // L'un des deux elements n'existe pas (il y a un bord)
2139 // => pas d'element diagonal
2140 elem_diagonal = -1;
2141 }
2142 }
2143 else
2144 {
2145 // Pas de voisin => pas d'element diagonal
2146 elem_diagonal = -1;
2147 }
2148 if (elem_diagonal < 0)
2149 {
2150 // Pas d'element diagonal => il y a un coin => pas d'interpolation.
2151 elem_voisins[direction1] = -1;
2152 elem_voisins[direction2] = -1;
2153 }
2154 }
2155 else
2156 {
2157 // Il n'y a qu'un voisin au maximum, donc pas d'element diagonal.
2158 // Rien a faire.
2159 }
2160 }
2161 if (dim == 2)
2162 {
2163 // Numeros des faces utilisees pour interpoler le champ:
2164 const int direction1 = 1 - compo;
2165 int element_voisin = elem_voisins[direction1];
2166 if (element_voisin < 0)
2167 element_voisin = element;
2168 const int f00 = elem_faces(element, compo);
2169 const int f10 = elem_faces(element, compo + dim);
2170 const int f01 = elem_faces(element_voisin, compo);
2171 const int f11 = elem_faces(element_voisin, compo + dim);
2172 // Coefficient d'interpolation dans la direction de la composante traitee
2173 double ci = coef[compo];
2174 // Coefficient dans l'autre direction
2175 double cj = coef[direction1];
2176 vitesse[compo] =
2177 ci * cj * valeurs_v(f00)
2178 + (1.-ci) * cj * valeurs_v(f10)
2179 + ci * (1.-cj) * valeurs_v(f01)
2180 + (1.-ci) * (1.-cj) * valeurs_v(f11);
2181 if (Objet_U::bidim_axi && (compo==0) && (ci>Objet_U::precision_geom) && (ci<1.-Objet_U::precision_geom)
2182 && (xv(f00,0) <DMINFLOAT)
2183 && ((fabs(valeurs_v(f00)-valeurs_v(f10))>DMINFLOAT) || (fabs(valeurs_v(f01)-valeurs_v(f11))>DMINFLOAT)))
2184 {
2185 Cerr << "In bidim_axi, when interpolating u_r within the first cell, we use the value on the symetry axis u_r(r=0)=0." << finl;
2186 Cerr << "We take a simple mean on that and the value at the other face. But for a divergence-free field, neglecting dv/dy, " << finl;
2187 Cerr << "it would be better to assume a velocity as u(x) = x_1/x * u_1 (if x!=0). GB 2020/03/05." << finl;
2188 const double x = coord_som[0];
2189 Cerr << "Here, the difference is "<< (1.-ci) << " vs. " << xv(f10, 0)/x << finl;
2190 Cerr << "u1= " << valeurs_v(f10) << " direction1 : " << direction1 << finl;
2191 Cerr << "interpoler_vitesse_point_vdf of Transport_Interface..cpp not exiting but interpolation is adapted" << finl;
2192 Cerr << "Former: " << vitesse[compo];
2193 vitesse[compo] = xv(f10, 0)/x * (
2194 cj * valeurs_v(f10)
2195 + (1.-cj) * valeurs_v(f11));
2196 Cerr << " New: " << vitesse[compo] << finl;
2197 //Process::exit();
2198 }
2199 }
2200 else if (dim == 3)
2201 {
2202 // 4 elements utilises pour interpoler la valeur:
2203 const int direction1 = (compo + 1) % 3;
2204 const int direction2 = (compo + 2) % 3;
2205 int elem00 = element;
2206 int elem10 = elem_voisins[direction1];
2207 int elem01 = elem_voisins[direction2];
2208 int elem11 = elem_diagonal;
2209 if (elem10 < 0) elem10 = element;
2210 if (elem01 < 0) elem01 = element;
2211 if (elem11 < 0) elem11 = element;
2212 // Numeros des faces utilisees pour interpoler le champ:
2213 const int f000 = elem_faces(elem00, compo);
2214 const int f100 = elem_faces(elem00, compo + dim);
2215 const int f010 = elem_faces(elem10, compo);
2216 const int f110 = elem_faces(elem10, compo + dim);
2217 const int f001 = elem_faces(elem01, compo);
2218 const int f101 = elem_faces(elem01, compo + dim);
2219 const int f011 = elem_faces(elem11, compo);
2220 const int f111 = elem_faces(elem11, compo + dim);
2221 // Coefficients d'interpolation
2222 double ci = coef[compo];
2223 double cj = coef[direction1];
2224 double ck = coef[direction2];
2225 // Calcul de la valeur interpolee
2226 vitesse[compo] =
2227 ( ci * cj * valeurs_v(f000)
2228 + (1.-ci) * cj * valeurs_v(f100)
2229 + ci * (1.-cj) * valeurs_v(f010)
2230 + (1.-ci) * (1.-cj) * valeurs_v(f110)) * ck
2231 +( ci * cj * valeurs_v(f001)
2232 + (1.-ci) * cj * valeurs_v(f101)
2233 + ci * (1.-cj) * valeurs_v(f011)
2234 + (1.-ci) * (1.-cj) * valeurs_v(f111)) * (1. - ck);
2235
2236 }
2237 else
2238 {
2239 // Hey, what are you doing here ?
2240 Process::exit();
2241 }
2242 }
2243}
2244
2245
2246// Description:
2247// Interpolation uni-lineaire d'un champ de vitesse VDF aux faces en un point
2248// de coordonnees coord_som. Le point coord_som est suppose se trouver dans
2249// l'element "element". Contrairement a la methode interpoler_vitesse_point_vdf
2250// dont elle s'inspire, cette methode n'interpole chaque composante que dans sa propre
2251// direction
2252// Pour chaque composante, on cherche le cube contenant coord_som et dont
2253// les sommets sont des noeuds de vitesse pour cette composante et on
2254// interpole lineairement dans ce cube. Au bord du domaine, la vitesse
2255// tangentielle dans le demi-element colle a la paroi est la vitesse
2256// discrete de l'element (la condition aux limites n'est PAS utilisee).
2257void interpoler_simple_vitesse_point_vdf(const Champ_base& champ_vitesse,
2258 const FTd_vecteur3& coord_som,
2259 const int element,
2260 FTd_vecteur3& vitesse,
2261 const int future_or_past)
2262{
2263 const DoubleTab& valeurs_v = (bool)(future_or_past) ? champ_vitesse.futur() : champ_vitesse.valeurs();
2264 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, champ_vitesse.domaine_dis_base());
2265 const IntTab& elem_faces = domaine_vf.elem_faces();
2266 const DoubleTab& xv = domaine_vf.xv();
2267
2268 // Chaque composante de vitesse est la moyenne ponderee des 2 vitesses
2269 // aux faces de l'element qui encadrent le sommet.
2270 // On designe par i,j,k l'une des 8 faces, avec 0<=i<=1, 0<=j<=1, 0<=k<=1.
2271 // La composante vitesse au sommet est
2272 // vitesse = SOMME(vitesse(face_i,j,k)*coef[0]*coef[1]*coef[2]);
2273 // Exemple : interpolation de la composante horizontale de vitesse
2274 // pour le sommet "x". On fait une interpolation bilineaire
2275 // entre les DEUX composantes horizontales de vitesses v.
2276 // Pas besoin des voisins!
2277 // --------
2278 // | x |
2279 // | v0 | v1
2280 // |--> |-->
2281 // | |
2282 // | |
2283 // --------
2284
2285 // Boucle sur les 2 ou 3 composantes de la vitesse
2286 int compo;
2287 const int dim = Objet_U::dimension;
2288 for (compo = 0; compo < dim; compo++)
2289 {
2290 // ****
2291 // Calcul d'un unique coefficient de ponderation coef
2292 // ****
2293 double coef;
2294
2295 // Boucle sur les 2 ou 3 dimensions du cube dans lequel on interpole la valeur
2296 int direction = compo;
2297 // Coordonnee du point ou il faut interpoler la vitesse
2298 const double x = coord_som[direction];
2299 // Dans la direction de la composante traitee on interpole
2300 // entre les deux faces opposees de l'element. Coordonnees
2301 // de ces faces :
2302 const int face_inf_compo = elem_faces(element, compo);
2303 const int face_sup_compo = elem_faces(element, compo + dim);
2304 const double xmin = xv(face_inf_compo, direction);
2305 const double xmax = xv(face_sup_compo, direction);
2306 coef = (xmax - x) / (xmax - xmin); // Le coef d'interpolation dans la direction
2307
2308 if (coef < 0.)
2309 coef = 0.;
2310 if (coef > 1.)
2311 coef = 1.;
2312
2313 vitesse[compo] = coef * valeurs_v(face_inf_compo) + (1.-coef) * valeurs_v(face_sup_compo);
2314 }
2315}
2316
2317double Transport_Interfaces_FT_Disc::calculer_integrale_indicatrice(const DoubleVect& indicatrice, double& integrale_ph0) const
2318{
2319 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
2320 const DoubleVect& volumes = domaine_vf.volumes();
2321 int nd, nb_nd = indicatrice.size();
2322 assert(nb_nd==domaine_vf.nb_elem());
2323
2324 double integrale = 0.;
2325 integrale_ph0 = 0.;
2326 for (nd=0 ; nd<nb_nd ; nd++)
2327 {
2328 integrale += indicatrice(nd) * volumes(nd);
2329 integrale_ph0 += (1 - indicatrice(nd))*volumes(nd);
2330 }
2331 // Reduce 2 mp_sum calls to 1 by using mp_sum_for_each
2332 Process::mp_sum_for_each(integrale_ph0, integrale);
2333 return integrale;
2334}
2335
2336/*! @brief Calcul de la vitesse de deplacement des noeuds du maillage a partir d'un champ eulerien par interpolation.
2337 *
2338 * Le deplacement fourni n'a aucune propriete particuliere de conservation
2339 * du volume.
2340 * Les lignes de contact sont deplacees avec une vitesse qui n'a pas de
2341 * propriete particuliere non plus...
2342 *
2343 * ATTENTION : on evalue simplement la vitesse a l'endroit ou sont les sommets.
2344 * Param nv_calc : si =1 : recalcule le champ eulerien de la vitesse par filtrage L2
2345 * sinon, reutilise celui stocke dans variables_internes_
2346 *
2347 */
2349 const Champ_base& champ_vitesse,
2350 const Maillage_FT_Disc& maillage,
2351 DoubleTab& vitesse_noeuds,
2352 const int nv_calc,
2353 const int standard,
2354 const bool la_roue_de_vitesse_a_deja_tournee) const
2355{
2356 switch(variables_internes_->methode_interpolation_v)
2357 {
2359 {
2360 const Champ_base * champ_vitesse_interp = 0; // Le champ a utiliser pour interpoler
2361 if (sub_type(Champ_P1NC, champ_vitesse) || sub_type(Champ_Fonc_P1NC,champ_vitesse))
2362 {
2363 // Champ P1NC en VEF: on projette L2 sur un champ P1,
2364 // puis on interpole lineairement
2365 Champ_base& champ_filtre = variables_internes_->vitesse_filtree.valeur();
2366 champ_vitesse_interp = & champ_filtre;
2367 if (nv_calc)
2368 {
2369 // Premier jet :
2370 // Calcul d'un champ aux sommets par filtrage L2 (inversion d'une matrice)
2371 // c'est assez long...
2372 // TODO GB2024 : Selon d'ou on fait l'appel, il faut .valeurs() ou .futur()
2373 // Je ne sais pas si l'option explicit_u_NS_ est correcte ici.
2374 const DoubleTab& val_champ_vitesse = (bool)(explicit_u_NS_) ? champ_vitesse.futur() : champ_vitesse.valeurs();
2375 champ_filtre.valeurs() = val_champ_vitesse;
2376 ////if (type == "Champ_P1NC")
2377 if (sub_type(Champ_P1NC, champ_vitesse))
2378 ref_cast(Champ_P1NC, champ_vitesse).filtrer_L2(champ_filtre.valeurs());
2379 else
2380 ref_cast(Champ_Fonc_P1NC, champ_vitesse).filtrer_L2(champ_filtre.valeurs());
2381 if (explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee) champ_filtre.futur() = champ_filtre.valeurs();
2382 }
2383 else
2384 Process::exit("Code never verified. I guess something is missing like : champ_filtre.valeurs() = val_champ_vitesse");
2385 }
2386 else if (sub_type(Champ_Face_VDF, champ_vitesse) || sub_type(Champ_Fonc_Face_VDF,champ_vitesse))
2387 {
2388 // On appelle 'valeur_aux_elems' du champ aux faces.
2389 champ_vitesse_interp = &champ_vitesse;
2390 }
2391 else
2392 {
2393 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calculer_vitesse_transport_interpolee\n";
2394 Cerr << "The interpolation from a field " << champ_vitesse.que_suis_je();
2395 Cerr << "is not developped." << finl;
2396 assert(0); // a coder...
2397 Process::exit();
2398 }
2399
2400 // Calcul de la vitesse interpolee a partir du champ P1
2401 // On ne calcule que les vitesses des sommets reels :
2402 DoubleTab& les_positions = variables_internes_->doubletab_pos;
2403 IntVect& les_elements = variables_internes_->intvect_elements;
2404 DoubleTab& les_vitesses = variables_internes_->doubletab_vitesses;
2405 // Remplissage des tableaux :
2406 const DoubleTab& pos = maillage.sommets();
2407 const ArrOfInt& elem = maillage.sommet_elem();
2408 const int nb_pos_tot = pos.dimension(0);
2409 const int dim = Objet_U::dimension;
2410 les_positions.resize(nb_pos_tot, dim);
2411 les_elements.resize(nb_pos_tot);
2412 int i, j;
2413 int nb_positions = 0;
2414 for (i = 0; i < nb_pos_tot; i++)
2415 {
2416 const int num_elem = elem[i];
2417 if (num_elem >= 0)
2418 {
2419 for (j = 0; j < dim; j++)
2420 les_positions(nb_positions, j) = pos(i, j);
2421 les_elements(nb_positions) = num_elem;
2422 nb_positions++;
2423 }
2424 }
2425 les_positions.resize(nb_positions, dim);
2426 les_elements.resize(nb_positions);
2427 les_vitesses.resize(nb_positions, dim);
2428
2429 if (explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee)
2430 //champ_vitesse_interp->valeur_aux_elems_passe(les_positions, les_elements, les_vitesses);
2431 champ_vitesse_interp->valeur_aux_elems_passe(les_positions, les_elements, les_vitesses);
2432 else
2433 champ_vitesse_interp->valeur_aux_elems(les_positions, les_elements, les_vitesses);
2434
2435 // Copie des vitesses :
2436 vitesse_noeuds.resize(nb_pos_tot, dim);
2437 nb_positions = 0;
2438 for (i = 0; i < nb_pos_tot; i++)
2439 {
2440 if (elem[i] >= 0)
2441 {
2442 for (j = 0; j < dim; j++)
2443 vitesse_noeuds(i, j) = les_vitesses(nb_positions, j);
2444 nb_positions++;
2445 }
2446 }
2447 maillage.desc_sommets().echange_espace_virtuel(vitesse_noeuds);
2448
2449 break;
2450 }
2452 {
2453 if (!sub_type(Champ_Face_VDF, champ_vitesse) && !sub_type(Champ_Fonc_Face_VDF,champ_vitesse) )
2454 {
2455 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calculer_vitesse_transport_interpolee\n"
2456 << "the interpolation VDF_LINEAIRE is valid only for a VDF discretization with a Champ_face field\n"
2457 << " (type for the current field: " << champ_vitesse.que_suis_je() << finl;
2458 Process::exit();
2459 }
2460 const DoubleTab& pos = maillage.sommets();
2461 const ArrOfInt& elem = maillage.sommet_elem();
2462 const int nb_pos_tot = pos.dimension(0);
2463 const int dim = Objet_U::dimension;
2464 int i;
2465 FTd_vecteur3 coord;
2466 FTd_vecteur3 vitesse;
2467 vitesse_noeuds.resize(nb_pos_tot, dim);
2468 for (i = 0; i < nb_pos_tot; i++)
2469 {
2470 const int element = elem[i];
2471 if (element >= 0) // sommet reel ?
2472 {
2473 int j;
2474 for (j = 0; j < dim; j++)
2475 coord[j] = pos(i,j);
2476 if (standard)
2477 {
2478 // Interpolation M-lineaire dans toutes les M-directions pour chaque compo
2479 interpoler_vitesse_point_vdf(champ_vitesse, coord, element, vitesse, explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee);
2480 }
2481 else
2482 {
2483 // Interpolation uni-lineaire dans chaque direction de chaque compo :
2484 interpoler_simple_vitesse_point_vdf(champ_vitesse, coord, element, vitesse, explicit_u_NS_ && la_roue_de_vitesse_a_deja_tournee);
2485 }
2486 for (j = 0; j < dim; j++)
2487 vitesse_noeuds(i,j) = vitesse[j];
2488 }
2489 }
2490 maillage.desc_sommets().echange_espace_virtuel(vitesse_noeuds);
2491 break;
2492 }
2494 {
2495 const DoubleTab& vertices = maillage.sommets();
2496 const int nb_vertices_tot = vertices.dimension(0);
2497 vitesse_noeuds.resize(nb_vertices_tot, dimension);
2498 const int& nb_fa7 = maillage.nb_facettes();
2499 ArrOfInt id_number_fa7(nb_fa7);
2500 const ArrOfDouble& surface_fa7 = maillage.get_update_surface_facettes();
2501 int n = search_connex_components_local_FT(maillage, id_number_fa7);
2502 const int nb_particles_tot=compute_global_connex_components_FT(maillage, id_number_fa7, n);
2503 const DoubleTab& phase_indicator_function = indicatrice_->valeurs();
2504 const ArrOfInt& sommets_elem = maillage.sommet_elem();
2505 const IntTab& facettes = maillage.facettes();
2506 DoubleTab Particles_velocity(nb_particles_tot,dimension);
2507 Particles_velocity=0;
2508 DoubleVect V_compo_elem(nb_particles_tot);
2509 V_compo_elem=0;
2510 ArrOfDouble Particles_surfaces(nb_particles_tot);
2511 Particles_surfaces=0;
2512 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
2513 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
2514 const DoubleTab& tab_velocity=champ_vitesse.valeurs();
2515 const Domaine_dis_base& mon_dom_dis = domaine_dis();
2516 const Domaine_VDF& domain_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
2517 const DoubleVect& volumes_maille = domain_vdf.volumes();
2518 const IntTab& elem_faces = domain_vdf.elem_faces();
2519 ns.compute_particles_eulerian_id_number(collision_model_);
2521 const IntTab& particles_eulerian_id_number = ns.get_particles_eulerian_id_number();
2522
2523 // STEP 1 : computing the mean volumic velocity inside each particle.
2524 // The ideal method would be to obtain the elem containing the gravity center of each
2525 // particle, then to locate the purely solid cells from near to far in order to avoid
2526 // a loop on all elements of the domain. However, a domain can contain zero real
2527 // particles (in the sense that it doesn't contain a particle's gravity center)
2528 // and still have purely solid cells due to the overlap of a particle between
2529 // the domain of two CPUs.
2530 // The "ideal" method would therefore require the CPU that owns the particle to
2531 // send its first row of distant element that are purely solid to the other CPU for
2532 // it to add velocity contributions.
2533 // As it add complexity to the implementation and communication time between CPU,
2534 // the naive method is implemented.
2535 const Fluide_Diphasique& two_phase_elem=ns.fluide_diphasique();
2536 const int id_solid_phase=1-two_phase_elem.get_id_fluid_phase();
2537 for (int elem=0; elem<domain_vdf.nb_elem(); elem++)
2538 {
2539 // the mean is realized on pure elem only
2540
2541 if (phase_indicator_function(elem)==id_solid_phase)
2542 {
2543 const int compo= particles_eulerian_id_number(elem);
2544 V_compo_elem(compo)+=volumes_maille(elem)*(1-phase_indicator_function(elem));
2545 for (int dim=0; dim<dimension; dim++) Particles_velocity(compo,dim)+=0.5*
2546 (tab_velocity(elem_faces(elem,dim))
2547 +tab_velocity(elem_faces(elem,dim+dimension))
2548 )*volumes_maille(elem);
2549 }
2550 }
2551
2552 mp_sum_for_each_item(Particles_velocity);
2553 mp_sum_for_each_item(V_compo_elem);
2554 DoubleVect s_vcompo;
2555 s_vcompo.ref_array(V_compo_elem);
2556 tab_divide_any_shape(Particles_velocity, s_vcompo);
2557 particles_velocity_collision_ = Particles_velocity;
2558
2559 // STEP 2 : computing the gravity center of particles
2560 DoubleTab Positions_compo(nb_particles_tot_,dimension);
2561 Positions_compo=0;
2562 for (int fa7=0; fa7<nb_fa7; fa7++)
2563 {
2564 if (!maillage.facette_virtuelle(fa7))
2565 {
2566 const int compo = id_number_fa7(fa7);
2567 const double s_fa7 = surface_fa7(fa7);
2568 Particles_surfaces(compo)+=s_fa7;
2569 for (int dim=0; dim<dimension; dim++)
2570 {
2571 for (int k = 0; k < vertices.dimension(1); k++)
2572 {
2573 int som = facettes(fa7, k);
2574 Positions_compo(compo, dim) += s_fa7 * vertices(som, dim)/dimension;
2575 }
2576 }
2577 }
2578 }
2579 mp_sum_for_each_item(Positions_compo);
2580 mp_sum_for_each_item(Particles_surfaces);
2581 DoubleVect s_scompo;
2582 s_scompo.ref_array(Particles_surfaces);
2583 tab_divide_any_shape(Positions_compo, s_scompo);
2584 particles_position_collision_ = Positions_compo;
2585 const Domaine& domain = domaine_dis().domaine();
2587
2588 // STEP 3 : identification of the id number of lagrangian vertices
2589 IntVect id_number_lagrangian_vertices;
2590 maillage.creer_tableau_sommets(id_number_lagrangian_vertices,
2591 RESIZE_OPTIONS::NOCOPY_NOINIT);
2592 id_number_lagrangian_vertices = -1;
2593 {
2594 const int dim = vitesse_noeuds.dimension(1);
2595 for (int iface = 0; iface < nb_fa7; iface++)
2596 {
2597 const int id_number = id_number_fa7[iface];
2598 for (int j = 0; j < dim; j++)
2599 id_number_lagrangian_vertices[facettes(iface, j)] = id_number;
2600 }
2601 MD_Vector_tools::echange_espace_virtuel(id_number_lagrangian_vertices,
2603 }
2604
2605 // STEP 4 : updating the lagrangian vertices displacement table
2606 for (int som = 0; som < nb_vertices_tot; som++)
2607 {
2608 if (sommets_elem[som] >= 0)
2609 {
2610 for (int dim = 0; dim < dimension; dim++)
2611 vitesse_noeuds(som, dim) =
2612 Particles_velocity(id_number_lagrangian_vertices(som), dim);
2613 }
2614
2615 }
2616 maillage.desc_sommets().echange_espace_virtuel(vitesse_noeuds);
2617 break;
2618 }
2619 default:
2620 {
2621 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_transport_interpolee\n"
2622 << " interpolation method not developped" << finl;
2623 Process::exit();
2624 }
2625 }
2626}
2627
2628
2630 const Champ_base& champ_scal,
2631 const Maillage_FT_Disc& maillage,
2632 DoubleTab& val_scal_noeuds,
2633 int nv_calc) const
2634{
2635
2636 switch(variables_internes_->methode_interpolation_v)
2637 {
2639 {
2640
2641 OWN_PTR(Champ_base) champ_scal_interp;
2642 champ_scal_interp=champ_scal;
2643 if (sub_type(Champ_P1NC, champ_scal) || sub_type(Champ_Fonc_P1NC,champ_scal))
2644 {
2645
2646 if (nv_calc)
2647 {
2648 // Premier jet :
2649 // Calcul d'un champ aux sommets par filtrage L2 (inversion d'une matrice)
2650 // c'est assez long...
2651
2652 DoubleTab scal_filtre_val(champ_scal.valeurs());
2653
2654 if (sub_type(Champ_P1NC, champ_scal))
2655 ref_cast(Champ_P1NC, champ_scal).filtrer_L2(scal_filtre_val);
2656 else if (sub_type(Champ_Fonc_P1NC, champ_scal))
2657 ref_cast(Champ_Fonc_P1NC, champ_scal).filtrer_L2(scal_filtre_val);
2658 champ_scal_interp->valeurs() = scal_filtre_val;
2659 }
2660
2661 }
2662 else if (sub_type(Champ_Fonc_P0_base, champ_scal))
2663 champ_scal_interp->valeurs() = champ_scal.valeurs();
2664
2665 else
2666 {
2667 Cerr<<"champ_scal type ="<<champ_scal.que_suis_je()<<finl;
2668 Cerr << "Erreur dans Transport_Interfaces_FT_Disc::calculer_scalaire_interpole\n";
2669 Cerr << " L'interpolation a partir d'un champ " << champ_scal.que_suis_je();
2670 Cerr << " n'est pas codee." << finl;
2671
2672 Cerr<<"champ_scal type ="<<champ_scal.que_suis_je()<<finl;
2673 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calculer_scalaire_interpole\n";
2674 Cerr << " The interpolation from a field " << champ_scal.que_suis_je();
2675 Cerr << " is not developped." << finl;
2676 assert(0); // a coder...
2677 Process::exit();
2678 }
2679
2680 // Calcul de la vitesse interpolee a partir du champ P1
2681 // On ne calcule que les vitesses des sommets reels :
2682 DoubleTab& les_positions = variables_internes_->doubletab_pos;
2683 IntVect& les_elements = variables_internes_->intvect_elements;
2684 ///DoubleTab & les_vitesses = variables_internes_->doubletab_vitesses;
2685 // Remplissage des tableaux :
2686 const DoubleTab& pos = maillage.sommets();
2687 const ArrOfInt& elem = maillage.sommet_elem();
2688 const int nb_pos_tot = pos.dimension(0);
2689 const int dim = Objet_U::dimension;
2690 les_positions.resize(nb_pos_tot, dim);
2691 les_elements.resize(nb_pos_tot);
2692 int i, j;
2693 int nb_positions = 0;
2694 for (i = 0; i < nb_pos_tot; i++)
2695 {
2696 const int num_elem = elem[i];
2697 if (num_elem >= 0)
2698 {
2699 for (j = 0; j < dim; j++)
2700 les_positions(nb_positions, j) = pos(i, j);
2701 les_elements(nb_positions) = num_elem;
2702 nb_positions++;
2703 }
2704 }
2705 les_positions.resize(nb_positions, dim);
2706 les_elements.resize(nb_positions);
2707
2708 champ_scal_interp->valeur_aux_elems(les_positions, les_elements,val_scal_noeuds);
2709
2710 break;
2711 }
2714 {
2715
2716 Process::exit();
2717 break;
2718 }
2719 default:
2720 {
2721 Cerr << "Transport_Interfaces_FT_Disc::calculer_scalaire_interpole\n"
2722 << " the interpolation method is not coded" << finl;
2723 Process::exit();
2724 }
2725 }
2726}
2727
2728
2729/*! @brief Calcul de la derivee en temps de l'inconnue : zero.
2730 *
2731 */
2733{
2734 derivee = 0.;
2735 return derivee;
2736}
2737
2738void Transport_Interfaces_FT_Disc::assembler( Matrice_Morse& mat_morse, const DoubleTab& present, DoubleTab& secmem)
2739{
2740 Cerr<<" On ne doit pas resoudre Transport_Interfaces_FT_Disc en implicite "<<finl;
2741 abort();
2742}
2743
2744static void init_parser_v_impose(const Noms& expression_vitesse, Parser& parser_x, Parser& parser_y, Parser& parser_z, double temps)
2745{
2746 const int dimension3 = (Objet_U::dimension==3);
2747 // Preparation des parsers...
2748 std::string sx(expression_vitesse[0]);
2749 parser_x.setString(sx);
2750 parser_x.setNbVar(4);
2751 parser_x.addVar("x");
2752 parser_x.addVar("y");
2753 parser_x.addVar("z");
2754 parser_x.addVar("t");
2755 parser_x.parseString();
2756 parser_x.setVar("z", 0.);
2757 parser_x.setVar("t", temps);
2758
2759 std::string sy(expression_vitesse[1]);
2760 parser_y.setString(sy);
2761 parser_y.setNbVar(4);
2762 parser_y.addVar("x");
2763 parser_y.addVar("y");
2764 parser_y.addVar("z");
2765 parser_y.addVar("t");
2766 parser_y.parseString();
2767 parser_y.setVar("z", 0.);
2768 parser_y.setVar("t", temps);
2769
2770 Nom unused_expr("0");
2771 std::string sz(dimension3
2772 ? expression_vitesse[2]
2773 : unused_expr /* inutilise */);
2774
2775 parser_z.setString(sz);
2776 parser_z.setNbVar(4);
2777 parser_z.addVar("x");
2778 parser_z.addVar("y");
2779 parser_z.addVar("z");
2780 parser_z.addVar("t");
2781 parser_z.parseString();
2782 parser_z.setVar("z", 0.);
2783 parser_z.setVar("t", temps);
2784}
2785
2786
2787//La presence d un interface solide dans l ecoulement implique d appliquer un terme source
2788//dans l equation de quantite de mouvement pour imposer au fluide la vitesse de l interface.
2789//Ce terme source n est pas standard mais consiste en une modification de vpoint qui depend
2790//de la valeur de vpoint elle meme.
2791//Contrainte : methode_transport==VITESSE_IMPOSEE
2792//
2793//Les etapes de la methode sont :
2794//-Calcul de la vitesse imposee a l interface a un temps donne: calcul_vitesse(...)
2795//-On determine le type du domaine discretisee (is_VDF vaut 1 pour VDF et 0 pour VEF)
2796// et le type dequation traitee (is_QC vaut 0 pour Navier_Stokes_FT_Disc et 1 sinon)
2797//-Estimation de l increment de quantite de mouvement a ajouter a vpoint
2798// puis ajout de cet increment : calcul_source_et_modifie_vpoint(...)
2799// Rq : la methode est parallele pour vpoint
2800// Le terme vpoint*dt permet d'impliciter un peu le terme source, mais
2801// semble poser quelques problemes avec la gravite. Un solide fixe dans un
2802// liquide sous gravite avec l'option terme_gravite rho_g met en mouvement
2803// le fluide dans le sens inverse a la gravite !!!
2804void Transport_Interfaces_FT_Disc::modifier_vpoint_pour_imposer_vit(const DoubleTab& inco_val,DoubleTab& vpoint0,
2805 DoubleTab& vpoint,const DoubleTab& rho_faces,
2806 DoubleTab& source_val,const double temps,
2807 const double dt,const int is_explicite,
2808 const double eta)
2809{
2810 if (!(temps>temps_debut_))
2811 return;
2812 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE
2813 || variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE)
2814 {
2815 // Etape 1 : calcul de la vitesse imposee sur l'interface a un temps donne
2816 DoubleTab vit_imposee;
2817 calcul_vitesse(vit_imposee,inco_val,vpoint0,temps,dt); // vpoint0 au lieu de vpoint
2818 vit_imposee.echange_espace_virtuel() ;
2819
2820 // Etape 2.1 : determination du domaine de discretisation
2821 const Domaine_dis_base& mon_dom_dis = domaine_dis();
2822 const IntTab& face_voisins = mon_dom_dis.face_voisins();
2823 assert(inco_val.dimension(0) == face_voisins.dimension(0));
2824
2825 // Etape 2.2 : determiniation du systeme d'equations a resoudre
2826 int is_QC=0;
2827 const Equation_base& eq = probleme_base_->equation(0);
2828 if (sub_type(Navier_Stokes_FT_Disc,eq))
2829 is_QC=0;
2830 else
2831 is_QC=1;
2832
2833 // Etape 3 : calcul et ajout du terme de penalisation dans la qdm
2834 const DoubleTab& indicatrice = get_indicatrice().valeurs();
2835
2836 calcul_indicatrice_faces(indicatrice,face_voisins);
2837 const DoubleTab& indicatrice_faces = get_indicatrice_faces().valeurs();
2838
2839 // Si on souhaite regulariser l interface IBC/fluide :
2840 // combinaison convexe de la vitesse imposee et la vitesse predite.
2841 // Ceci est realise seulement pendant une etape explicite.
2842 // En penalise, pas de regularisation pendant l etape implicite
2843 // (pour regulariser en penalise, on ajoute une etape explicite)
2844 const int n = vpoint.dimension(0);
2845 const int m = vpoint.line_size();
2846 if(variables_internes_->vimp_regul && is_explicite)
2847 {
2848
2849 DoubleTab vitesse(vpoint0);
2850 vitesse *= dt ;
2851 vitesse += inco_val ;
2852
2853 for (int i=0 ; i < n; i++)
2854 {
2855 if (indicatrice_faces(i) > 0. )
2856 {
2857 double f = indicatrice_faces(i);
2858 for (int j = 0; j < m; j++)
2859 {
2860 if (!is_QC)
2861 vit_imposee(i,j) = f*vit_imposee(i,j) + (1.-f)*vitesse(i,j);
2862 else
2863 vit_imposee(i,j) = f*vit_imposee(i,j) + (1.-f)*vitesse(i,j)/rho_faces(i);
2864
2865 vitesse_imp_interp_->valeurs()(i,j)= vit_imposee( i,j ) ;
2866 }
2867
2868 }
2869 }
2870 }
2871
2872 calcul_source(inco_val,vpoint0,rho_faces,source_val,vit_imposee,indicatrice_faces,
2873 is_QC,dt,is_explicite,eta); // vpoint0 au lieu de vpoint
2874 source_val.echange_espace_virtuel();
2875
2876 const DoubleVect& volumes_entrelaces = ref_cast(Domaine_VF,mon_dom_dis).volumes_entrelaces();
2877 const Solveur_Masse_base& le_solveur_masse = eq.solv_masse();
2878 int i, j;
2879
2880 DoubleTab termes_sources_face(vpoint);
2881 termes_sources_face=0.;
2882 modifie_source(termes_sources_face,source_val,rho_faces,n,m,is_QC,volumes_entrelaces,le_solveur_masse);
2883 termes_sources_face.echange_espace_virtuel() ; // CI
2884
2885 for (i = 0; i < n; i++)
2886 for (j = 0; j < m; j++)
2887 vpoint(i, j) += termes_sources_face(i,j);
2888 }
2889 else if (sub_type(Transport_Marqueur_FT,*this))
2890 {
2891
2892 }
2893 else
2894 {
2895 Cerr << "Error for the method Transport_Interfaces_FT_Disc::modifier_vpoint_pour_imposer_vit\n"
2896 << " The transport equation is not of type \"methode_transport vitesse_imposee\"."
2897 << " or \"methode_transport loi_horaire\"."
2898 << finl;
2899 Process::exit();
2900 }
2901 vpoint.echange_espace_virtuel();
2902 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_vitesse_imposee vpoint",vpoint);
2903}
2904
2905
2907 const IntTab& face_voisins)
2908{
2909 DoubleTab& indicatrice_faces = indicatrice_faces_->valeurs();
2910 const int nfaces = face_voisins.dimension_tot(0);
2911 for (int i = 0; i < nfaces; i++)
2912 {
2913 const int elem0 = face_voisins(i, 0);
2914 const int elem1 = face_voisins(i, 1);
2915 indicatrice_faces(i)= 0.;
2916
2917 if (elem0 >= 0)
2918 indicatrice_faces(i) = indicatrice(elem0);
2919 if (elem1 >= 0)
2920 indicatrice_faces(i) += indicatrice(elem1);
2921 if (elem0 >= 0 && elem1 >= 0)
2922 indicatrice_faces(i) *= 0.5;
2923 double bmax=1.-1e-9;
2924 if(indicatrice_faces(i) <= 1.0e-9) indicatrice_faces(i) = 0. ;
2925 else if(indicatrice_faces(i) >= bmax) indicatrice_faces(i) = 1. ;
2926 }
2927
2928 switch(variables_internes_->type_indic_faces_)
2929 {
2931 {
2932 // Does nothing more.
2933 break;
2934 }
2936 {
2937 // si on souhaite calculer l'indicatrice a partir de la distance :
2938 const DoubleTab& dist_face = get_update_distance_interface_faces().valeurs();
2939 const Domaine_dis_base& domaine_dis_base = domaine_dis();
2940 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, domaine_dis_base);
2941 const DoubleVect& face_surfaces = domaine_vdf.face_surfaces();
2942 const DoubleVect& volumes_entrelaces = domaine_vdf.volumes_entrelaces();
2943 double& position = variables_internes_->modified_indic_faces_position;
2944 double& thickness = variables_internes_->modified_indic_faces_thickness;
2945 for (int i = 0; i < nfaces; i++)
2946 {
2947 double h=volumes_entrelaces(i)/face_surfaces(i);
2948 if (dist_face(i) > (position+thickness/2.)*h || indicatrice_faces(i)==1.)
2949 indicatrice_faces(i)=1.;
2950 else if (dist_face(i) >= (position-thickness/2.)*h && thickness !=0.)
2951 indicatrice_faces(i) = (dist_face(i) - position*h)/(thickness*h) + 0.5 ;
2952 else
2953 indicatrice_faces(i)=0.;
2954 }
2955 break;
2956 }
2958 {
2959 // This method should be very much like case Navier_Stokes_FT_Disc_interne::INTERP_AI_BASED in Navier_Stokes_FT_Disc::calculer_dI_dt
2960 // (but just the part to compute indicatrices faces...
2961 // WARNING : contrary to what is done in Navier_Stokes_FT_Disc::calculer_dI_dt, we compute chi_1 (ie same as indicatrice),
2962 // not the opposite chi_0 = 1-chi_1
2963 //
2964 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
2965 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
2966 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
2967 {
2968 // On recupere le saut de vitesse a l'interface (changement de phase)
2969 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
2970 const DoubleTab& interfacial_area = ns.get_interfacial_area();
2971 const DoubleTab& normale_elements = get_normale_interface().valeurs();
2972
2973 const int dim = ns.inconnue().valeurs().line_size();
2974 const int vef = (dim == 2);
2975 if (vef)
2976 {
2977 Cerr << "Code never applied or checked in VEF. You should read the algo first and assess it!" << finl;
2978 Process::exit();
2979 }
2980 // On fait la moyenne des 2 valeurs calculees sur les voisins
2981 // ATTENTION, ici on veut la valeur de chiv (cad chi_0) a la face.
2982 for (int face = 0; face < nfaces; face++)
2983 {
2984 double indic_face = 0.;
2985 int v;
2986 for (v = 0; v < 2; v++)
2987 {
2988 const int elem = face_voisins(face, v);
2989 if (elem >=0)
2990 {
2991 // If a neighbour is pure, we use that value at the face and stop further calculation.
2992 const double indic = indicatrice[elem]; // This is the value of chi_1 (ie =1 in phase 1!)
2993 //if (indic == 0. || indic == 1.)
2994 if (indic <=5e-3 || indic >= 1.-5e-3)
2995 {
2996 indic_face = indic; // Obviously, We want chi of phase_1
2997 break;
2998 }
2999 else
3000 {
3001 const double surface=domaine_vf.face_surfaces(face);
3002 const double ai= interfacial_area(elem); // nx pointe vers le liquide (sortant de phase 0)
3003 if (fabs(ai)>DMINFLOAT)
3004 {
3005 double x = 0.;
3006 if (vef)
3007 {
3008 for (int j = 0; j < dim; j++)
3009 {
3010 const double nf = domaine_vf.face_normales(face , j);
3011 const double nx = normale_elements(elem, j);
3012 // produit scalaire :
3013 x += nf*nx;
3014 }
3015 x *= ai/surface;
3016 // Que/comment Choisir?
3017 indic_face += x;
3018 Cerr << "Never tested. To be verified. It should depend on a scalar product with the vect (xp-xv)" << finl;
3019 Process::exit();
3020 }
3021 else
3022 {
3023 // En VDF, l'acces a orientation permet d'eviter le calcul du produit scalaire.
3024 const Domaine_VDF& zvdf = ref_cast(Domaine_VDF, domaine_dis());
3025 const IntVect& orientation = zvdf.orientation();
3026 const int dir = orientation[face];
3027 const double nx = normale_elements(elem, dir);
3028 // Assumes a cube, nx larger than diag means we can use the method rather safely
3029 if (nx>0.707)
3030 {
3031 x = ai/surface*nx;
3032 // On suppose que v0 est a gauche et v1 a droite!!!
3033 if (v==0)
3034 indic_face += x; // This way, we build chi_1 because normale points towards chi_1
3035 else
3036 indic_face += 1-x;
3037 }
3038 else
3039 {
3040 // L'interface croise probablement la face d'en face et la methode ne marche plus.
3041 // We revert back to the standard method :
3042 double tmp = 0.;
3043 if (elem >= 0)
3044 tmp = indicatrice(elem);
3045
3046 double bmax=1.-1e-9;
3047 if(tmp <= 1.0e-9) tmp = 0. ;
3048 else if(tmp >= bmax) tmp = 1. ;
3049
3050 indic_face += tmp;
3051 }
3052 }
3053 }
3054 else
3055 {
3056 Cerr <<" WTF, c'est impossible" << finl;
3057 Process::exit();
3058 }
3059 }
3060 }
3061 else
3062 {
3063 // The only neighbour to the face :
3064 const int elem_voisin = face_voisins(face, 1-v); // The other one is accessed by 1-v
3065 const double indic = indicatrice[elem_voisin]; // This is the value of chi_1 (ie =1 in phase 1!)
3066 indic_face = indic; // We want chi of phase_1
3067 break; // c'est important pour le if d'apres.
3068 }
3069 }
3070 if (v==2)
3071 // On n'a pas touche le break, on est donc passe 2 fois. donc :
3072 indic_face*=0.5;
3073
3074 // assert((indic_face >=0) && (indic_face<=1.));
3075 // ca arrive des petits derapages..
3076 if (indic_face <0)
3077 indic_face=0.;
3078 if (indic_face >1.)
3079 indic_face=1.;
3080
3081 indicatrice_faces_->valeurs()(face) = indic_face;
3082 }
3083 }
3084 else
3085 {
3086 Cerr << "Interpolation option AI_BASED in Transport_Interfaces_FT_Disc is not available "
3087 << "in Transport_Interfaces_FT_Disc::calcul_indicatrice_faces if we do not "
3088 << "have a Navier_Stokes_FT_Disc equation..." << finl;
3089 Process::exit();
3090 }
3091 break;
3092 }
3093 default:
3094 Cerr << "Transport_Interfaces_FT_Disc::calcul_indicatrice_faces\n"
3095 << " unknown case?" << finl;
3096 Process::exit();
3097 }
3098
3099 indicatrice_faces.echange_espace_virtuel();
3100 Debog::verifier("Transport_Interfaces_FT_Disc::calcul_indicatrice_faces indicatrice_faces",indicatrice_faces);
3101}
3102
3104{
3105 return variables_internes_->vimp_regul;
3106}
3108{
3109 return indicatrice_faces_;
3110}
3111
3113{
3114 const Domaine_dis_base& mon_dom_dis = domaine_dis();
3115 const DoubleTab& indicatrice = get_indicatrice().valeurs();
3116 const IntTab& face_voisins = mon_dom_dis.face_voisins();
3117 calcul_indicatrice_faces(indicatrice,face_voisins);
3118 return indicatrice_faces_;
3119}
3120
3121//Methode outil qui estime la valeur d increment de qdm a ajouter a
3122//la derivee temporelle de la vitesse
3123// L'expression calculee
3124// Cas Front-Tracking (is_QC vaut 0):
3125// (v_impose - (champ_vitesse + vpoint*dt)) / dt * indicatrice * rho_face;
3126// Cas Quasi-compressible (is_QC vaut 1) :
3127// (rho_np1 v_impose - (rho_vitesse_n + vpoint*dt)) / dt * indicatrice
3128
3129void Transport_Interfaces_FT_Disc::calcul_source(const DoubleTab& inco_val,
3130 const DoubleTab& vpoint,
3131 const DoubleTab& rho_faces,
3132 DoubleTab& source_val,const DoubleTab& vit_imposee,const DoubleTab& indicatrice_faces,
3133 const int is_QC,
3134 const double dt,
3135 const int is_explicite,
3136 const double eta)
3137
3138{
3139 DoubleTab terme_explicite(vpoint);
3140 double c;
3141 const int nfaces = vpoint.dimension(0);
3142 c = 1. / eta;
3143 if (indicatrice_faces.dimension(0) == nfaces )
3144 {
3145 if (is_explicite)
3146 {
3147 terme_explicite *= dt;
3148 }
3149 else
3150 {
3151 terme_explicite *= 0.;
3152 }
3153
3154 for (int i = 0; i < nfaces; i++)
3155 {
3156
3157 double indic = (indicatrice_faces(i) > 0. ? 1.0 : 0.0) ;
3158 // Si on veut regulariser le passage de IBC/fluide et que l'on est penalise,
3159 // seules les faces telles que indic=1 sont penalisees, les autres sont DF.
3160 if (variables_internes_->vimp_regul && !is_explicite ) indic = (indicatrice_faces(i) ==1. ? 1.0 : 0.0);
3161 double tsource;
3162 double rho_face = rho_faces(i);
3163 const int dim = inco_val.line_size(); // > 1 => VEF, =1 => VDF
3164
3165 for (int j = 0; j < dim; j++)
3166 {
3167 double increment_inco = inco_val(i,j) + terme_explicite(i,j);
3168 if (!is_QC)
3169 tsource = (vit_imposee(i,j) - increment_inco) / dt * indic * rho_face * c;
3170 else
3171 tsource = (vit_imposee(i,j) * rho_face - increment_inco) / dt * indic * c;
3172
3173 source_val(i,j) = tsource;
3174 }
3175 }
3176 }
3177 else
3178 {
3179
3180 Cerr << "Erreur dans Transport_Interfaces_FT_Disc::calcul_source\n" << finl;
3181 Cerr << "Dimension de indicatrice_face differente de dimension de vpoint.\n" << finl;
3182 Process::exit();
3183 }
3184}
3185
3186void ouvrir_fichier(SFichier& os,const Nom& type, const int flag, const Transport_Interfaces_FT_Disc& equation)
3187{
3188
3189 if (flag==0)
3190 return ;
3191 Noms files(14);
3192 Nom file=Objet_U::nom_du_cas();
3193 if (type=="force")
3194 files[0]=type,
3195 file+="_Force_totale_sur_";
3196 else if( type=="force_totale" )
3197 files[1]= type,
3198 file+="_Friction_totale_sur_";
3199 else if( type=="Friction" )
3200 files[2]= type,
3201 file+="_Friction_conv_diff_sur_";
3202 else if( type=="Pressure" )
3203 files[3]= type ,
3204 file+="_Friction_Pression_sur_";
3205 else if ( type =="moment")
3206 files[4]+= type,
3207 file+="_Moment_total_sur_";
3208 else if ( type=="particles_trajectory" )
3209 files[5]=type,
3210 file+="_particles_trajectory_";
3211 else if ( type=="mean_rms_particles_velocity")
3212 files[6]=type,
3213 file+="_mean_rms_particles_velocity_";
3214 else if (type=="particles_data")
3215 files[7]=type,
3216 file+="_particles_data_";
3217 else if (type=="particle_hydrodynamic_forces")
3218 {
3219 files[8]=type,
3220 file+="_particle_hydrodynamic_forces_";
3221 }
3222 else if( type=="Stokes_theoretical_forces" )
3223 {
3224 files[9]=type,
3225 file+= "_Stokes_theoretical_forces_";
3226 }
3227 else if (type=="particle_hydrodynamic_forces_bed")
3228 {
3229 files[10]=type,
3230 file+= "_particle_hydrodynamic_forces_bed_";
3231 }
3232 else if (type=="fluid_to_particle_heat_transfer")
3233 {
3234 files[11]=type,
3235 file+= "_fluid_to_particle_heat_transfer_";
3236 }
3237 else if (type=="fluid_to_particle_heat_transfer_bed")
3238 {
3239 files[12]=type,
3240 file+= "_fluid_to_particle_heat_transfer_bed_";
3241 }
3242 else if(type=="Friction_diff")
3243 files[13]= type,
3244 file+="_Friction_diff_sur_" ;
3245 else
3246 {
3247 Cerr << "The file " << type << " is not understood by Transport_Interfaces_FT_Disc::ouvrir_fichier. "
3248 << finl;
3249 }
3250
3251 const int rang=files.search(type);
3252 file+=equation.le_nom();
3253 file+=".out";
3254
3255 const Schema_Temps_base& sch=equation.probleme().schema_temps();
3256 const int precision=sch.precision_impr();
3257 // We create the file during the first writting sequence, or if it does not exist
3258 struct stat f;
3259 if ((stat(file,&f) && (sch.nb_impr()==1 && !equation.probleme().reprise_effectuee())))
3260 {
3261 os.ouvrir(file);
3262 SFichier& fic=os;
3263 Nom espace="\t\t";
3264 if (rang<5)
3265 {
3266 fic << (Nom)"# Printing " << (type=="moment"?"of the drag moment exerted":"of the drag exerted");
3267 fic << " by the fluid on the interface " << equation.le_nom();
3268 fic << " " << (type=="moment"?"[N.m]":"[N]") << finl;
3269 int nb_compo=(type=="moment" && Objet_U::dimension==2?1:Objet_U::dimension);
3270 fic << "# Time";
3271
3272 Nom ch=espace;
3273 if (type=="moment")
3274 {
3275 if (Objet_U::dimension==2) ch+="Mz";
3276 else
3277 {
3278 ch+="Mx";
3279 ch+=espace+"My";
3280 ch+=espace+"Mz";
3281 }
3282 }
3283 else
3284 {
3285 if (nb_compo>1) ch+="Fx";
3286 if (nb_compo>=2) ch+=espace+"Fy";
3287 if (nb_compo>=3) ch+=espace+"Fz";
3288 }
3289 fic << ch << finl;
3290 }
3291 else if (rang==5)
3292 {
3293 espace="\t";
3294 fic << "#########################################" << finl;
3295 fic << "# Position - Velocity - Collision force #" << finl;
3296 fic << "#########################################" << finl;
3297 fic << "# Time [s]" << finl;
3298 fic << "# Position of the gravity center of the particle [m] (px py pz)" << finl;
3299 fic << "# Velocity of the gravity center of the particle [m/s] (vx vy vz)" << finl;
3300 fic << "# Collision force discretized on the particle volume [N] (fcx fcy fcz)" << finl;
3301 fic << finl;
3302 fic << "# Time" << espace << "px py pz" << espace << "vx vy vz" << espace << "fcx fcy fcz" << finl;
3303 fic << finl;
3304 }
3305 else if (rang==6)
3306 {
3307 espace="\t";
3308 fic << "#####################################################" << finl;
3309 fic << "# Average velocity - Average velocity squared - RMS #" << finl;
3310 fic << "#####################################################" << finl;
3311 fic << "# Time [s]" << finl;
3312 fic << "# Average velocity of purely solid cells. For each purely solid cell,"
3313 " the velocity at gravity center is computed as the average velocity of"
3314 " the opposing faces weighted by its volume. [m/s] (vx_av vy_av vz_av)" << finl;
3315 fic << "# Average velocity squared of purely solid cells. [m^2/s^2] (vx2_av vy2_av vz2_av)" << finl;
3316 fic << "# Once the average velocity and the average velocity squared is known,"
3317 " the RMS is computed as sqrt(abs(vi_av^2 - vi2_av)) with i in {x,y,z}."
3318 " [-] (rmsx rmsy rmsz)" << finl;
3319 fic << finl;
3320 fic << "# Time" << espace << "vx_av vy_av vz_av" << espace << "vx2_av vy2_av vz2_av"
3321 << espace << "rmsx rmsy rmsz" << finl;
3322 fic << finl;
3323 }
3324 else if (rang==7)
3325 {
3326 espace="\t";
3327 fic << "############################################################" << finl;
3328 fic << "# Position - Velocity - Collision force - Collision number #" << finl;
3329 fic << "############################################################" << finl;
3330 fic << "# Time [s] - Total number of collision " << finl;
3331 fic << "# Position of the gravity center of the particle [m] (px py pz)" << finl;
3332 fic << "# Velocity of the gravity center of the particle [m/s] (vx vy vz)" << finl;
3333 fic << "# Collision force discretized on the particle volume [N] (fcx fcy fcz)" << finl;
3334 fic << finl;
3335 fic << "# Time" <<espace <<"total collision number" << finl;
3336 fic << "# particle_id px py pz vx vy vz fcx fcy fcz number_of_particles_in_collision"<< finl;
3337 fic << finl;
3338 }
3339 else if (rang==8)
3340 {
3341 fic << "###################################" << finl;
3342 fic << "# Hydrodynamic force computation #" << finl;
3343 fic << "###################################" << finl;
3344 fic << finl;
3345 fic << "# Time [s]"<< espace << "Particle surface [m^2]" << espace <<
3346 "Pressure force [N] (fpx fpy fpz)" << espace << "Friction force [N] (ffx ffy ffz)" << finl;
3347 fic << finl;
3348 }
3349 else if (rang==9)
3350 {
3351 fic << "#####################################################################" << finl;
3352 fic << "# Hydrodynamic force computation - Stokes theoretical configuration #" << finl;
3353 fic << "#####################################################################" << finl;
3354 fic << "# Time [s]"<< finl;
3355 fic << "# Stokes theoretical PRESSURE FORCE computed from the integration, on the lagrangian mesh,"
3356 " of the discretized analytical solution [N] (fpx_th fpy_th fpz_th)" << finl;
3357 fic << "# Stokes PRESSURE FORCE computed with the developed method on the theoretical"
3358 " pressure field discretized on the eulerian mesh [N] (fpx_th_interp fpy_th_interp"
3359 " fpz_th_interp)" << finl;
3360 fic << "# Stokes theoretical FRICTION FORCE computed from the integration,"
3361 " on the lagrangian mesh, of the discretized analytical solution [N]"
3362 " (ffx_th ffy_th ffz_th)" << finl;
3363 fic << "# Stokes FRICTION FORCE computed with the developed method on the theoretical"
3364 " velocity field discretized on the eulerian mesh [N] (ffx_th_interp"
3365 " ffy_th_interp ffz_th_interp)" << finl;
3366 fic << finl;
3367 fic << "# Time" << espace << "fpx_th fpy_th fpz_th" << espace <<
3368 "fpx_th_interp fpy_th_interp fpz_th_interp" << espace << "ffx_th ffy_th ffz_th" <<
3369 espace << "ffx_th_interp ffy_th_interp ffz_th_interp" << finl;
3370 fic << finl;
3371 }
3372 else if (rang==10)
3373 {
3374 fic << "#########################################################" << finl;
3375 fic << "# Hydrodynamic force computation in a particle assembly #" << finl;
3376 fic << "#########################################################" << finl;
3377 fic << finl;
3378 fic << "# Time [s]" << espace << "particle_id" << espace << "Pressure force [N] (fpx fpy fpz)"
3379 << espace << "Friction force [N] (ffx ffy ffz)" << espace <<
3380 "Percentage of facets for which forces were computable" << espace <<
3381 "Average fluid velocity in P2" << "Percentage of purely fluid cells in P2"<< finl;
3382 fic << finl;
3383 }
3384 else if (rang==11)
3385 {
3386 fic << "#########################" << finl;
3387 fic << "# Heat flux computation #" << finl;
3388 fic << "#########################" << finl;
3389 fic << "# Time [s]" << finl;
3390 fic << "# Computation of the heat flux received by the particle from the surrounding fluid. [W] (phi)" << finl;
3391 fic << finl;
3392 fic << "# Time" << espace << "phi" << finl;
3393 fic << finl;
3394 }
3395 else if (rang==12)
3396 {
3397 fic << "################################################" << finl;
3398 fic << "# Heat flux computation in a particle assembly #" << finl;
3399 fic << "################################################" << finl;
3400 fic << "# Time [s]" << finl;
3401 fic << "# Computation of the heat flux received by the particle from the surrounding fluid. [W] (phi_i), where i stands for the particle number." << finl;
3402 fic << "# Average temperature of purely fluid cells in P2. [K] (T_i)" << finl;
3403 fic << finl;
3404 fic << "Time" << espace << "phi_0 T_0 ... phi_N T_N" << finl;
3405 fic << finl;
3406 }
3407 }
3408 // otherwise, we open it
3409 else
3410 {
3411 os.ouvrir(file,ios::app);
3412 }
3413 os.precision(precision);
3414 os.setf(ios::scientific);
3415}
3416void Transport_Interfaces_FT_Disc::modifie_source(DoubleTab& termes_sources_face,const DoubleTab& source_val,const DoubleTab& rho_faces,
3417 const int n,const int m, const int is_QC,
3418 const DoubleVect& vol_entrelaces,const Solveur_Masse_base& un_solv_masse)
3419{
3420
3421 for (int face=0; face<n; face++)
3422 for (int dim=0; dim<m; dim++)
3423 termes_sources_face(face,dim)=vol_entrelaces(face)*source_val(face,dim);
3424
3425 termes_sources_face.echange_espace_virtuel() ; // CI
3426 un_solv_masse.appliquer(termes_sources_face);
3427
3428 if (!is_QC)
3429 {
3430 for (int i = 0; i < n; i++)
3431 {
3432 const double rho_face = rho_faces(i);
3433
3434 for (int j = 0; j < m; j++)
3435 termes_sources_face(i,j) = termes_sources_face(i,j) / rho_face;
3436 }
3437 }
3438}
3439
3440void Transport_Interfaces_FT_Disc::impr_effort_fluide_interface( DoubleTab& source_val, DoubleTab& pressure_part, DoubleTab& friction_part, DoubleTab& diff_part)
3441{
3442 const DoubleTab& indicatrice_faces = get_indicatrice_faces().valeurs();
3443 const int n = source_val.dimension(0);
3444 const int nbdim1 = source_val.line_size() == 1; // VDF
3445 const int m = source_val.line_size();
3446
3447 const Domaine_dis_base& mon_dom_dis = domaine_dis();
3448 const Domaine_VDF * zvdf = 0;
3449 if (sub_type(Domaine_VDF, domaine_dis())) zvdf = &ref_cast(Domaine_VDF, domaine_dis());
3450
3451 DoubleTab termes_sources_face(source_val);
3452 DoubleTab termes_pressure_face(pressure_part);
3453 DoubleTab termes_friction_face(friction_part);
3454 DoubleTab termes_diff_face(diff_part);
3455 DoubleTrav values(4,dimension);
3456 values=0.;
3457
3458 const DoubleVect& vol_entrelaces = ref_cast(Domaine_VF,mon_dom_dis).volumes_entrelaces();
3459 // Construction d'un tableau des items reels non communs
3460 ArrOfInt sequential_items_flags;
3461 source_val.get_md_vector()->get_sequential_items_flags(sequential_items_flags);
3462
3463
3464 for (int face=0; face<n; face++)
3465 {
3466 double indic = (indicatrice_faces(face) > 0. ? 1.0 : 0.0);
3467 double coef = vol_entrelaces(face)*indic;
3468 for (int dim=0; dim<m; dim++)
3469 {
3470 termes_sources_face(face,dim)=source_val(face,dim)*coef;
3471 termes_pressure_face(face,dim)=pressure_part(face,dim)*coef;
3472 termes_friction_face(face,dim)=friction_part(face,dim)*coef;
3473 termes_diff_face(face,dim)=diff_part(face,dim)*coef;
3474 }
3475 // Calcul de dforce contribution de la force du fluide sur la face i
3476 // si ce n'est pas une face commune a plusieurs processeurs
3477 if (sequential_items_flags[face])
3478 {
3479 if (nbdim1) // VDF
3480 {
3481 int j = zvdf->orientation(face);
3482
3483 values(0,j) -= termes_sources_face(face,0);
3484 values(1,j) -= termes_pressure_face(face,0);
3485 values(2,j) -= termes_friction_face(face,0);
3486 values(3,j) -= termes_diff_face(face,0);
3487 }
3488 else // VEF
3489 {
3490 for (int j = 0; j < dimension; j++)
3491 {
3492 values(0,j) -= termes_sources_face(face,j);
3493 values(1,j) -= termes_pressure_face(face,j);
3494 values(2,j) -= termes_friction_face(face,j);
3495 values(3,j) -= termes_diff_face(face,j);
3496 }
3497 }
3498 }
3499 }
3500
3501 // Impression des efforts exerces par le fluide sur l'interface
3502 {
3503 // Ajout des differents processeurs en //
3504 mp_sum_for_each_item(values);
3505
3506 // Impression dans les fichiers
3508 {
3509 SFichier Force;
3510 ouvrir_fichier(Force,"force_totale",1,*this);
3511 Nom espace=" \t";
3513 Force.precision(10) ;
3514 for(int k=0; k<dimension; k++)
3515// Force << espace << dforce(k);
3516 Force << espace << values(0,k);
3517 Force << finl;
3518 const int impr_mom = 1 ;
3519
3520 SFichier Pressure;
3521 ouvrir_fichier(Pressure,"Pressure",impr_mom,*this);
3523 Pressure.precision(10) ;
3524// for(int k=0; k<pressure.size_array(); k++)
3525 for(int k=0; k<dimension ; k++)
3526// Pressure << espace << pressure(k);
3527 Pressure << espace << values(1,k);
3528 Pressure << finl;
3529
3530 SFichier Friction;
3531 ouvrir_fichier(Friction,"Friction",impr_mom,*this);
3533 Friction.precision(10) ;
3534// for(int k=0; k<friction.size_array(); k++)
3535 for(int k=0; k<dimension; k++)
3536// Friction << espace << friction(k);
3537 Friction << espace << values(2,k);
3538 Friction << finl;
3539
3540 SFichier Friction2;
3541 ouvrir_fichier(Friction2,"Friction_diff",impr_mom,*this);
3543 Friction2.precision(10) ;
3544// for(int k=0; k<friction.size_array(); k++)
3545 for(int k=0; k<dimension; k++)
3546 Friction2 << espace << values(3,k);
3547 Friction2 << finl;
3548 }
3549 }
3550}
3551
3552
3553// Impression des forces et moment
3555{
3556 // Impression dans les fichiers
3558 {
3559 SFichier Force;
3560 ouvrir_fichier(Force,"force",1,*this);
3561 Nom espace=" \t";
3563 for(int k=0; k<dimension; k++)
3564 Force << espace << force_[k];
3565 Force << finl;
3566 const Domaine& domaine=domaine_dis().domaine();
3567 const int impr_mom = domaine.moments_a_imprimer();
3568 if (impr_mom)
3569 {
3570 SFichier Moment;
3571 ouvrir_fichier(Moment,"moment",impr_mom,*this);
3573 for(int k=0; k<moment_.size_array(); k++)
3574 Moment << espace << moment_[k];
3575 Moment << finl;
3576 }
3577
3579 {
3580 espace= " ";
3581 int dim_max_impr=5; // on imprime pas les valeurs si il y a plus de 5 particules dans le domaine
3582 if (nb_particles_tot_<dim_max_impr)
3583 {
3584 SFichier Particles_trajectory;
3585 ouvrir_fichier(Particles_trajectory,"particles_trajectory",1,*this);
3586 schema_temps().imprimer_temps_courant(Particles_trajectory);
3587 for (int particle=0; particle<nb_particles_tot_; particle++)
3588 {
3589 Particles_trajectory << espace;
3590 for (int dim=0; dim<dimension; dim++)
3591 Particles_trajectory << espace << particles_position_collision_(particle,dim);
3592 Particles_trajectory << espace;
3593
3594 for (int dim=0; dim<dimension; dim++)
3595 Particles_trajectory << espace << particles_velocity_collision_(particle,dim);
3596 Particles_trajectory << espace;
3597
3598 if (collision_model_)
3599 {
3600 const DoubleTab& lagrangian_contact_forces=
3601 collision_model_.valeur().get_lagrangian_contact_forces();
3602 for (int dim=0; dim<dimension; dim++)
3603 Particles_trajectory << espace << lagrangian_contact_forces(particle,dim);
3604 }
3605 Particles_trajectory << finl;
3606 }
3607 }
3608
3610 {
3611 SFichier Moy_Rms_Vitesse_Particule;
3612 ouvrir_fichier(Moy_Rms_Vitesse_Particule,"mean_rms_particles_velocity",1,*this);
3613 schema_temps().imprimer_temps_courant(Moy_Rms_Vitesse_Particule);
3614 Moy_Rms_Vitesse_Particule << "Time " << schema_temps().temps_courant() << finl;
3615 const DoubleTab& mean_velocity=get_mean_particles_volumic_velocity();
3616 const DoubleTab& rms_velocity=get_mean_particles_volumic_squared_velocity();
3617 const DoubleTab& mean_squared_velocity=get_rms_particles_volumic_velocity();
3618 const DoubleTab& particles_purely_solid_mesh_volume=get_particles_purely_solid_mesh_volume();
3619
3620 for (int particle=0; particle<nb_particles_tot_; particle++)
3621 {
3622 Moy_Rms_Vitesse_Particule << particle << " ";
3623 Moy_Rms_Vitesse_Particule << espace;
3624 Moy_Rms_Vitesse_Particule << particles_purely_solid_mesh_volume(particle)<< espace;
3625
3626 for (int dim=0; dim<dimension; dim++)
3627 Moy_Rms_Vitesse_Particule << espace << mean_velocity(particle,dim);
3628 Moy_Rms_Vitesse_Particule << espace;
3629
3630 for (int dim=0; dim<dimension; dim++)
3631 Moy_Rms_Vitesse_Particule << espace << mean_squared_velocity(particle,dim);
3632 Moy_Rms_Vitesse_Particule << espace;
3633
3634 for (int dim=0; dim<dimension; dim++)
3635 Moy_Rms_Vitesse_Particule << espace << rms_velocity(particle,dim);
3636
3637 Moy_Rms_Vitesse_Particule << finl;
3638 }
3639 }
3640
3641 SFichier Particles_data;
3642 ouvrir_fichier(Particles_data,"particles_data",1,*this);
3643 if (collision_model_)
3644 {
3645 const int collision_number=collision_model_.valeur().get_collision_number();
3646 Particles_data << "Time " << schema_temps().temps_courant() << "\t" <<
3647 collision_number<< finl;
3648 }
3649 for (int particle = 0; particle < nb_particles_tot_; particle++)
3650 {
3651 Particles_data << particle << " ";
3652 for (int d = 0; d < dimension; d++)
3653 Particles_data << particles_position_collision_(particle,d) << espace ;
3654
3655 for (int d = 0; d < dimension; d++)
3656 Particles_data << particles_velocity_collision_(particle,d) << espace ;
3657
3658 if (collision_model_)
3659 {
3660 const DoubleTab& lagrangian_contact_forces=
3661 collision_model_.valeur().get_lagrangian_contact_forces();
3662 const ArrOfDouble particles_collision_number=collision_model_.valeur().get_particles_collision_number();
3663
3664 for (int d = 0; d < dimension; d++)
3665 Particles_data << lagrangian_contact_forces(particle,d) << espace ;
3666
3667 Particles_data << particles_collision_number(particle) << espace ;
3668 }
3669 Particles_data << finl;
3670 }
3671
3672 const Transport_Interfaces_FT_Disc& mon_eq = *this;
3673 if (post_process_hydro_forces_.get_is_compute_forces())
3674 {
3675 const DoubleTab& total_pressure_force=post_process_hydro_forces_.get_pressure_force();
3676 const DoubleTab& total_friction_force=post_process_hydro_forces_.get_friction_force();
3677 const DoubleVect& total_surface_interf=post_process_hydro_forces_.get_total_surface_interf();
3678
3679 if (nb_particles_tot_<dim_max_impr)
3680 {
3681 SFichier particle_hydro_forces;
3682 ouvrir_fichier(particle_hydro_forces,"particle_hydrodynamic_forces",1,mon_eq);
3683 schema_temps().imprimer_temps_courant(particle_hydro_forces);
3684
3685 for (int compo=0; compo<nb_particles_tot_; compo++)
3686 {
3687 particle_hydro_forces << espace << total_surface_interf(compo) << espace;
3688 for (int dim=0; dim<dimension; dim++) particle_hydro_forces <<
3689 espace << total_pressure_force(compo,dim);
3690 particle_hydro_forces << espace;
3691 for (int dim=0; dim<dimension; dim++) particle_hydro_forces <<
3692 espace << total_friction_force(compo,dim);
3693 particle_hydro_forces << espace;
3694 }
3695
3696 particle_hydro_forces << finl;
3697 }
3698 else
3699 {
3700 SFichier particle_hydro_forces_bed;
3701 ouvrir_fichier(particle_hydro_forces_bed,"particle_hydrodynamic_forces_bed",1,mon_eq);
3702 particle_hydro_forces_bed << "TIME ";
3703 schema_temps().imprimer_temps_courant(particle_hydro_forces_bed);
3704 particle_hydro_forces_bed << finl;
3705 const DoubleTab& U_P2_moy = post_process_hydro_forces_.get_U_P2_moy();
3706 const DoubleTab& Nb_fa7_ok_prop = post_process_hydro_forces_.get_prop_fa7_ok_P2();
3707 const DoubleTab& Prop_indic_fluide_P2 = post_process_hydro_forces_.get_prop_P2_fluid();
3708 for (int particle = 0; particle < nb_particles_tot_; particle++)
3709 {
3710 int dim;
3711 particle_hydro_forces_bed << particle ;
3712 particle_hydro_forces_bed << espace << total_surface_interf(particle) << espace;
3713 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3714 total_pressure_force(particle,dim);
3715 particle_hydro_forces_bed << espace;
3716 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3717 total_friction_force(particle,dim);
3718 particle_hydro_forces_bed << espace;
3719 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3720 Nb_fa7_ok_prop(particle,dim);
3721 for (dim=0; dim<dimension; dim++) particle_hydro_forces_bed << espace <<
3722 U_P2_moy(particle,dim);
3723 particle_hydro_forces_bed << espace << Prop_indic_fluide_P2(particle);
3724 particle_hydro_forces_bed << finl;
3725 }
3726 }
3727
3728 }
3729
3730 if (post_process_hydro_forces_.get_is_compute_forces_Stokes_th() && schema_temps().nb_pas_dt()==1)
3731 {
3732 const DoubleTab& total_pressure_force=post_process_hydro_forces_Stokes_.get_pressure_force();
3733 const DoubleTab& total_friction_force=post_process_hydro_forces_Stokes_.get_friction_force();
3734 const DoubleTab& total_pressure_force_Stokes=post_process_hydro_forces_Stokes_.
3735 get_pressure_force_Stokes_th();
3736 const DoubleTab& total_friction_force_Stokes=post_process_hydro_forces_Stokes_.
3737 get_friction_force_Stokes_th();
3738 int nb_particles_tot = total_pressure_force.dimension(0);
3739
3740 if (nb_particles_tot<dim_max_impr)
3741 {
3742 SFichier Force_Particule_th;
3743 ouvrir_fichier(Force_Particule_th,"Stokes_theoretical_forces",1,mon_eq);
3744 schema_temps().imprimer_temps_courant(Force_Particule_th);
3745 for (int particle=0; particle<nb_particles_tot; particle++)
3746 {
3747 Force_Particule_th << espace;
3748 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3749 total_pressure_force_Stokes(particle,dim);
3750 Force_Particule_th << espace;
3751 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3752 total_pressure_force(particle,dim);
3753 Force_Particule_th << espace;
3754 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3755 total_friction_force_Stokes(particle,dim);
3756 Force_Particule_th << espace;
3757 for (int dim=0; dim<dimension; dim++) Force_Particule_th << espace <<
3758 total_friction_force(particle,dim);
3759 Force_Particule_th << finl;
3760 }
3761 }
3762
3763 }
3764
3765 if (post_process_hydro_forces_.get_is_compute_heat_transfer())
3766 {
3767 const DoubleVect& total_heat_transfer =
3768 post_process_hydro_forces_.get_heat_transfer();
3769 if (nb_particles_tot_ < dim_max_impr)
3770 {
3771 SFichier Heat_Transfer;
3772 ouvrir_fichier(Heat_Transfer,
3773 "fluid_to_particle_heat_transfer", 1, mon_eq);
3774 schema_temps().imprimer_temps_courant(Heat_Transfer);
3775 for (int particle = 0; particle < nb_particles_tot_;
3776 particle++)
3777 {
3778 Heat_Transfer << espace << total_heat_transfer(particle);
3779 }
3780 Heat_Transfer << finl;
3781 }
3782 else
3783 {
3784 SFichier Heat_Transfer_bed;
3785 ouvrir_fichier(Heat_Transfer_bed,
3786 "fluid_to_particle_heat_transfer_bed", 1, mon_eq);
3787 schema_temps().imprimer_temps_courant(Heat_Transfer_bed);
3788 for (int particle = 0; particle < nb_particles_tot_;
3789 particle++)
3790 {
3791 Heat_Transfer_bed << espace << total_heat_transfer(particle);
3792 }
3793 Heat_Transfer_bed << finl;
3794 }
3795 }
3796 }
3797 }
3798 return 1;
3799}
3800
3801//Cette methode actualise le critere de stationnnarite dI/dt (en derivee partielle)
3802//du fait que pour ce type d equation derivee_en_temps_inco fixe dI/dt a 0.
3803//
3805{
3806 Schema_Temps_base& sch_tps = schema_temps();
3807 const DoubleTab& present = inconnue().valeurs();
3808 const DoubleTab& passe = inconnue().passe();
3809 const double dt = sch_tps.pas_de_temps();
3810 DoubleTab tab_critere(present);
3811
3812 tab_critere = present;
3813 tab_critere -=passe;
3814 tab_critere /= dt;
3815 sch_tps.update_critere_statio(tab_critere,*this);
3816}
3817
3819 const DoubleTab& rho_faces,DoubleTab& source_val,
3820 const int is_explicite,const double eta)
3821{
3822 const DoubleTab& indicatrice_faces = get_indicatrice_faces().valeurs();
3823 const int n = vpoint.dimension(0);
3824 const int m = vpoint.line_size();
3825 double c= 1./eta;
3826 const Domaine_dis_base& mon_dom_dis = domaine_dis();
3827
3828 int is_QC=0;
3829 const Equation_base& eq = probleme_base_->equation(0);
3830 const Solveur_Masse_base& le_solveur_masse = eq.solv_masse();
3831 if (sub_type(Navier_Stokes_FT_Disc,eq))
3832 is_QC=0;
3833 else
3834 is_QC=1;
3835
3836 if ( !is_explicite )
3837 {
3838 for (int i = 0; i<n; i++)
3839 {
3840 double indic = (indicatrice_faces(i) > 0. ? 1.0 : 0.0);
3841 for (int j = 0; j < m; j++)
3842 {
3843 if (!is_QC)
3844 source_val(i,j) -= vpoint(i,j) * indic * rho_faces(i) * c;
3845 else
3846 source_val(i,j) -= vpoint(i,j) * indic * c;
3847 }
3848 }
3849 }
3850
3851 DoubleTab termes_sources_face(vpoint);
3852 const DoubleVect& vol_entrelaces = ref_cast(Domaine_VF,mon_dom_dis).volumes_entrelaces();
3853
3854 for (int face=0; face<n; face++)
3855 for (int dim=0; dim<m; dim++)
3856 {
3857 double indic = (indicatrice_faces(face) > 0. ? 1.0 : 0.0);
3858 termes_sources_face(face,dim)=vol_entrelaces(face)*vol_entrelaces(face)*source_val(face,dim)*indic;
3859 }
3860
3861 termes_sources_face.echange_espace_virtuel() ;
3862 le_solveur_masse.appliquer(termes_sources_face);
3863
3864 // Impression des efforts exerces par le fluide sur l'interface
3865 {
3866 ArrOfDouble dforce(dimension);
3867 force_=0;
3868 moment_=0;
3869 const Domaine& domaine=domaine_dis().domaine();
3870 const int impr_mom = domaine.moments_a_imprimer();
3871 const ArrOfDouble& centre_gravite = domaine.cg_moments();
3872 const DoubleTab& centre_faces = ref_cast(Domaine_VF,domaine_dis()).xv();
3873 ArrOfDouble xgr(dimension);
3874
3875 const Domaine_VDF * zvdf = 0;
3876 if (sub_type(Domaine_VDF, domaine_dis()))
3877 zvdf = &ref_cast(Domaine_VDF, domaine_dis());
3878
3879 // Construction d'un tableau des items sequentiels
3880 ArrOfInt sequential_items_flags;
3881 rho_faces.get_md_vector()->get_sequential_items_flags(sequential_items_flags);
3882
3883 // Calcul de la force et du moment en fonction de la discretisation
3884 for (int i = 0; i < n; i++)
3885 {
3886 // Calcul de dforce contribution de la force du fluide sur la face i
3887 // si c'est une face sequentielle
3888 if (sequential_items_flags[i])
3889 {
3890 dforce=0;
3891 if (zvdf)
3892 {
3893 int j = zvdf->orientation(i);
3894 dforce[j] = -termes_sources_face(i);
3895 force_[j] += dforce[j];
3896 }
3897 else
3898 for (int j = 0; j < dimension; j++)
3899 {
3900 dforce[j] = -termes_sources_face(i,j);
3901 force_[j] += dforce[j];
3902 }
3903 // Ajout de dforce au calcul eventuel du moment
3904 if (impr_mom)
3905 {
3906 for (int j = 0; j < dimension; j++)
3907 xgr[j] = centre_faces(i,j) - centre_gravite[j];
3908
3909 if (dimension==2)
3910 moment_[0] += dforce[1]*xgr[0] - dforce[0]*xgr[1];
3911 else
3912 {
3913 moment_[0] += dforce[2]*xgr[1] - dforce[1]*xgr[2];
3914 moment_[1] += dforce[0]*xgr[2] - dforce[2]*xgr[0];
3915 moment_[2] += dforce[1]*xgr[0] - dforce[0]*xgr[1];
3916 }
3917 }
3918 }
3919 }
3920
3921 // Ajout des differents processeurs en //
3922
3923 mp_sum_for_each_item(force_);
3924 mp_sum_for_each_item(moment_);
3925 // Impression dans les fichiers
3927 }
3928}
3929
3931{
3932 const double temps=le_schema_en_temps->temps_courant();
3933 const int dim = Objet_U::dimension;
3934 const int dimension3 = (dim==3);
3935 Parser parser_x, parser_y, parser_z;
3936 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
3937 const IntTab& face_voisins = domaine_vf.face_voisins();
3938 const int nfaces = face_voisins.dimension(0);
3939 const DoubleTab& xv = domaine_vf.xv();
3940 const Domaine_VDF * zvdf = 0;
3941 if (sub_type(Domaine_VDF, domaine_vf))
3942 zvdf = &ref_cast(Domaine_VDF, domaine_vf);
3943
3944 if (zvdf)
3945 vit_ibc.resize(nfaces,1);
3946 else
3947 vit_ibc.resize(nfaces,dim);
3948
3949 init_parser_v_impose(variables_internes_->expression_vitesse_imposee,
3950 parser_x, parser_y, parser_z,temps);
3951 for (int i = 0; i < nfaces; i++)
3952 {
3953 for (int j = 0; j < dim; j++)
3954 {
3955 const double coord = xv(i,j);
3956 parser_x.setVar(j, coord);
3957 parser_y.setVar(j, coord);
3958 if (dimension3)
3959 parser_z.setVar(j, coord);
3960 }
3961 if (zvdf)
3962 {
3963
3964 switch(zvdf->orientation(i))
3965 {
3966 case 0:
3967 vit_ibc(i,0) = parser_x.eval();
3968 break;
3969 case 1:
3970 vit_ibc(i,0) = parser_y.eval();
3971 break;
3972 case 2:
3973 vit_ibc(i,0) = parser_z.eval();
3974 break;
3975 }
3976 }
3977 else
3978 {
3979 vit_ibc(i,0) = parser_x.eval();
3980 vit_ibc(i,1) = parser_y.eval();
3981 if (dimension3)
3982 vit_ibc(i,2) = parser_z.eval();
3983 }
3984 }
3985}
3986
3987//Methode qui effectue le calcul de la vitesse imposee a l interface a l instant temps
3988//- Utilise l expression de la vitesse imposee specifiee par l utilisateur : expression_vitesse_imposee
3989//- La vitesse calculee est contenue dans vitesse_imp
3990
3992 const DoubleTab& vitesse,
3993 const DoubleTab& vpoint,
3994 const double temps,
3995 const double dt)
3996{
3997 const int dim = Objet_U::dimension;
3998 const int dimension3 = (dim==3);
3999 const Domaine_dis_base& mon_dom_dis = domaine_dis();
4000 const IntTab& face_voisins = mon_dom_dis.face_voisins();
4001 const int nfaces = face_voisins.dimension(0);
4002 const DoubleTab& xv = ref_cast(Domaine_VF, mon_dom_dis).xv();
4003 const Domaine_VDF * zvdf = 0;
4004 if (sub_type(Domaine_VDF, mon_dom_dis))
4005 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis);
4006
4007 if (zvdf)
4008 vitesse_imp.resize(nfaces,1);
4009 else
4010 vitesse_imp.resize(nfaces,dim);
4011
4012 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE)
4013 {
4014 ArrOfDouble coord(dim);
4015 ArrOfDouble v_imp(dim);
4016 for (int i = 0; i < nfaces; i++)
4017 {
4018 // Calcul de la vitesse au centre de la face par la loi horaire a temps+dt
4019 for (int j = 0; j < dim; j++)
4020 coord[j] = xv(i,j);
4021 v_imp = variables_internes_->loi_horaire_->vitesse(temps+dt,coord);
4022
4023 if (zvdf)
4024 vitesse_imp(i,0) = v_imp[zvdf->orientation(i)];
4025 else
4026 for (int j = 0; j < dim; j++)
4027 vitesse_imp(i,j) = v_imp[j];
4028 }
4029 }
4030 else if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE)
4031 {
4032 switch(variables_internes_->interpolation_champ_face)
4033 {
4035 {
4036 Parser parser_x, parser_y, parser_z;
4037 init_parser_v_impose(variables_internes_->expression_vitesse_imposee,
4038 parser_x, parser_y, parser_z,temps);
4039 for (int i = 0; i < nfaces; i++)
4040 {
4041
4042 for (int j = 0; j < dim; j++)
4043 {
4044 // Vitesse evaluee au centre de la face
4045 const double coord = xv(i,j);
4046 parser_x.setVar(j, coord);
4047 parser_y.setVar(j, coord);
4048 if (dimension3)
4049 parser_z.setVar(j, coord);
4050 }
4051 if (zvdf)
4052 {
4053
4054 switch(zvdf->orientation(i))
4055 {
4056 case 0:
4057 vitesse_imp(i,0) = parser_x.eval();
4058 break;
4059 case 1:
4060 vitesse_imp(i,0) = parser_y.eval();
4061 break;
4062 case 2:
4063 vitesse_imp(i,0) = parser_z.eval();
4064 break;
4065 }
4066
4067 }
4068 else
4069 {
4070
4071 vitesse_imp(i,0) = parser_x.eval();
4072 vitesse_imp(i,1) = parser_y.eval();
4073 if (dimension3)
4074 vitesse_imp(i,2) = parser_z.eval();
4075 }
4076 }
4077 break;
4078 }
4080 {
4081 double dt_loc = 0.;
4082 if ( !variables_internes_->vf_explicite )
4083 {
4084 //On calcule un dt_loc car diff et conv sont explicites pour cette estimation de vpoint
4085 const Equation_base& eq = probleme_base_->equation(0);
4086 const double nb_op = eq.nombre_d_operateurs();
4087 if(nb_op > 0) dt_loc += 1. / eq.operateur(0).calculer_pas_de_temps();
4088 if(nb_op > 1) dt_loc += 1. / eq.operateur(1).calculer_pas_de_temps();
4089 dt_loc = (1./dt_loc)*(le_schema_en_temps->facteur_securite_pas());
4090 dt_loc = Process::mp_min(dt_loc);
4091 // si le dt_loc obtenu est plus grand que le dt_min du jdd :
4092 dt_loc = std::min(dt_loc,dt);
4093 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_imposee avec dt_loc : "<<dt_loc<<finl;
4094 }
4095 if (zvdf)
4096 {
4097 const DoubleTab& dist_face = get_update_distance_interface_faces().valeurs();
4098 const int phase = 0;
4099 vitesse_imp = vpoint;
4100 vitesse_imp*= dt_loc;
4101 vitesse_imp += vitesse;
4102 vitesse_imp.echange_espace_virtuel() ; // CI
4103 DoubleTab gradient(vitesse);
4104 interpoler_vitesse_face(dist_face,phase,variables_internes_->n_iterations_interpolation_ibc,vitesse_imp,gradient,temps,dt);
4105 Debog::verifier("Transport_Interfaces_FT_Disc::calcul_vitesse vitesse_imp apres interp. ",vitesse_imp);
4106 }
4107 else
4108 {
4109 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_imposee\n"
4110 << " interpolation lineaire non codee en VEF" << finl;
4111 Process::exit();
4112 }
4113 break;
4114 }
4115 default:
4116 {
4117 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_imposee\n"
4118 << " methode d'interpolation non codee" << finl;
4119 Process::exit();
4120 }
4121 }
4122 }
4123 else
4124 {
4125 Cerr << "Error for the method Transport_Interfaces_FT_Disc::calcul_vitesse\n"
4126 << " The transport equation is not of type \"methode_transport vitesse_imposee\"."
4127 << " or \"methode_transport loi_horaire\"."
4128 << finl;
4129 Process::exit();
4130 }
4131}
4132
4133
4134//Calcul d'une distance signee a l'interface aux centres des faces, interpolee a partir de la distance signee aux
4135//centres des elements (dist_elem) et de la normale a l'interface evaluee aux centres des elements euleriens (normale_elem).
4136//
4137//Pour une face, on evalue la distance entre le centre de la face et l'interface par :
4138// dist_face = d1 + d2,
4139// d1 = dist_elem,
4140// d2 = normale_elem scalaire (position_centre_face - centre_element)
4141//Ensuite, la distance entre le centre d'une face et l'interface est la moyenne de toutes
4142//les distances calculee a l'aide des elements adjacents a cette face.
4143//La distance est invalide au-dela d'une certaine epaisseur autour de l'interface
4144//(voir iterations de lissage dans calculer_distance_interface).
4146 const DoubleTab& dist_elem,
4147 const DoubleTab& normale_elem,
4148 DoubleTab& dist_face) const
4149{
4150 statistics().create_custom_counter("Calculer_distance_interface",3,"FrontTracking");
4151 statistics().begin_count("Calculer_distance_interface",statistics().get_last_opened_counter_level()+1);
4152
4153 static const double distance_faces_invalides = -1.e30;
4154
4155 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
4156 const IntTab& elem_faces = domaine_vf.elem_faces();
4157 const DoubleTab& xv = domaine_vf.xv();
4158 const DoubleTab& xp = domaine_vf.xp();
4159 const int nb_faces = dist_face.dimension_tot(0);
4160 ArrOfInt ncontrib(nb_faces);
4161 ncontrib = 0;
4162 dist_face = 0.;
4163
4164 const int dim = Objet_U::dimension;
4165 double centre[3] = {0., 0., 0.};
4166 double normale[3] = {0., 0., 0.};
4167 // Calcul de SOMME(d1+d2) pour tous les elements voisins de chaque face :
4168 int elem, i;
4169 const int nb_elem_tot = dist_elem.dimension_tot(0);
4170 const int nb_faces_elem = elem_faces.line_size();
4171
4172 for (elem = 0; elem < nb_elem_tot; elem++)
4173 {
4174 const double d1 = dist_elem(elem);
4175 // Si la distance est invalide, on passe:
4176 if (d1 < distance_faces_invalides)
4177 continue;
4178 // Centre de l'element et normale a l'interface pour cet element :
4179 for (i = 0; i < dim; i++)
4180 {
4181 centre[i] = xp(elem, i);
4182 normale[i] = normale_elem(elem, i);
4183 }
4184 // Boucle sur les faces de l'element
4185 for (i = 0; i < nb_faces_elem; i++)
4186 {
4187 const int face = elem_faces(elem, i);
4188 // dist_face ne contient que des faces reelles en general.
4189 // si la face n'est pas dans dist_face, on ne calcule pas.
4190 if (face < nb_faces)
4191 {
4192 double d2 = 0.;
4193 int j;
4194 for (j = 0; j < dim; j++)
4195 {
4196 double position_centre_face = xv(face, j);
4197 d2 += (position_centre_face - centre[j]) * normale[j];
4198 }
4199 dist_face(face) += d1 + d2;
4200 ++(ncontrib[face]);
4201 }
4202 }
4203 }
4204 // Division par le nombre d'elements voisins
4205 const double valeur_invalide = distance_faces_invalides * 1.1;
4206#ifdef __INTEL_COMPILER
4207#pragma novector // Desactive vectorisation sur Intel car crash sinon
4208#endif
4209 for (i = 0; i < nb_faces; i++)
4210 {
4211 const int n = ncontrib[i];
4212 if (n > 0)
4213 dist_face(i) /= n;
4214 else
4215 dist_face(i) = valeur_invalide;
4216 }
4217 dist_face.echange_espace_virtuel();
4218 statistics().end_count("Calculer_distance_interface");
4219}
4220
4221
4223{
4224 // Si le tag du maillage et le tag du champ sont identiques, inutile de recalculer:
4225 const int tag = maillage_interface().get_mesh_tag();
4226 if (tag == variables_internes_->distance_faces_cache_tag)
4227 return variables_internes_->distance_interface_faces.valeur();
4228
4229 variables_internes_->distance_faces_cache_tag = tag;
4230 assert(tag == variables_internes_->distance_normale_cache_tag);
4231 const DoubleTab& dist_elem = get_distance_interface().valeurs();
4232 const DoubleTab& normale_elem = get_normale_interface().valeurs();
4233 DoubleTab& dist_face = variables_internes_->distance_interface_faces->valeurs();
4234
4235 calculer_distance_interface_faces(dist_elem, normale_elem, dist_face);
4236 return variables_internes_->distance_interface_faces.valeur();
4237}
4238
4239// Verification que la vitesse imposee est uniforme
4240inline void check(const DoubleTab& v_imp, int& i_face, double v, int v_est_initialise)
4241{
4242 if (v_est_initialise && v_imp(i_face)!= v)
4243 {
4244 Cerr << "=====================================================================================" << finl;
4245 Cerr << "You defined a non-uniform function for the keyword: methode_transport vitesse_imposee" << finl;
4246 Cerr << "Please add:" << finl;
4247 Cerr << "type_vitesse_imposee analytique" << finl;
4248 Process::exit();
4249 }
4250 else
4251 {
4252 v = v_imp(i_face);
4253 v_est_initialise = 1;
4254 }
4255}
4256// Modifie les valeurs de la vitesse aux faces pres de l'interface (le stencil depend du nombre d'iterations) via une
4257// interpolation lineaire de la vitesse.
4258// A partir d'une indicatrice interpolee aux faces, on calcule le gradient de chaque composante de la vitesse pour les
4259// faces ou :
4260// - indicatrice=phase
4261// - distance face/interface valide (depend du nb iterations de lissage dans calculer_distance_interface).
4262// On en deduit le gradient aux faces telles que indicatrice!=phase, via un processus iteratif qui permet d'etendre
4263// l'interpolation aux points interieurs a l'IBC. L'interpolation s'effectue sur les quatre faces les plus proches de
4264// meme orientation (vitesses non colocalisees).
4265// Le resultat OWN_PTR(Champ_base) est prealablement construit a partir du champ de vitesse Un+vpoint.dt dans la methode
4266// calcule_vitesse
4267//
4268// Attention :
4269// - phase=0 impose que l'indicatrice de la partie fluide soit egale a 0
4270// - l'interpolation est specifique au VDF
4271// - codage pour l'instant pour une IBC immobile ou a vitesse uniforme
4272
4274 const DoubleTab& distance_interface_faces,
4275 const int phase,
4276 const int stencil_width,
4277 DoubleTab& champ,
4278 DoubleTab& gradient,
4279 const double t, const double dt)
4280{
4281 const Domaine_dis_base& mon_dom_dis = domaine_dis();
4282 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
4283 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
4284 const Domaine_VDF * zvdf = 0;
4285 if (sub_type(Domaine_VDF, mon_dom_dis))
4286 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis);
4287
4288 const IntTab& elem_faces = domaine_vf.elem_faces();
4289 const IntTab& faces_elem = domaine_vf.face_voisins();
4290 const int nfaces = faces_elem.dimension(0);
4291 const int nb_elem = domaine_vf.nb_elem() ;
4292 const int nb_elem_tot = domaine_vf.nb_elem_tot() ;
4293 const IntVect& orientation = domaine_vdf.orientation();
4294 const DoubleTab& xv = domaine_vf.xv();
4295 const DoubleTab& xp = domaine_vf.xp();
4296 assert(champ.dimension(0) == nfaces);
4297 assert(gradient.dimension(0) == nfaces);
4298 assert(distance_interface_faces.dimension(0) == nfaces);
4299
4300 const int dim = Objet_U::dimension;
4301 const int dimension3 = (Objet_U::dimension==3);
4302
4303 Parser parser_x, parser_y, parser_z;
4304 init_parser_v_impose(variables_internes_->expression_vitesse_imposee,parser_x, parser_y, parser_z, t);
4305
4306 const double invalid_test = -1.e30;
4307 const double invalid_value = -2.e30;
4308 gradient = invalid_value;
4309 const double indic_phase = (phase == 0) ? 0. : 1.;
4310 int i_face;
4311 Maillage_FT_Disc& maillage = maillage_interface() ;
4312 const DoubleTab& indicatrice = get_indicatrice().valeurs();
4313 const DoubleTab& indicatrice_face = update_indicatrice_faces().valeurs();
4314 // distance signee aux faces corrigee
4315 DoubleTab dist_face_cor(distance_interface_faces) ;
4316 // type de face : fluide (0), solide (1) et 0.5 si le barycentre de la face est proche de l'IBC
4317 DoubleTab typeface(champ) ;// CI
4318 typeface = -1.e30 ;
4319
4320 if(variables_internes_-> type_distance_calculee == Transport_Interfaces_FT_Disc_interne::DIST_MODIFIEE )
4321 {
4322 //////////////////////////////////////////////////////////////////////////////////////////////
4323 ////// LANCE DE RAYON
4324 //////////////////////////////////////////////////////////////////////////////////////////////
4325
4326 //////////////////////////////////////////////////////////////////////////////////////////////
4327 //------- Calcul du nombre de fois qu'un rayon local (par direction) traverse l'IBC dans une cellule
4328 IntTab trav(nb_elem,dim) ;
4329 if( nb_elem < nb_elem_tot )
4330 domaine_vf.domaine().creer_tableau_elements(trav, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
4331 trav = 0 ;
4332
4333 DoubleTab xe(dim) ;
4334 xe = 0. ;
4335 for(int i_elem=0 ; i_elem<nb_elem ; i_elem++)
4336 {
4337 for(int i=0 ; i<dim ; i++ )
4338 xe(i)=xp(i_elem,i) ;
4339 // Cas des elements diphasiques
4340 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. )
4341 {
4342 for(int dir = 0 ; dir < dim ; dir++ )
4343 {
4344 int a = elem_faces(i_elem, dir) ;
4345 int b = elem_faces(i_elem, dir+dim) ;
4346 const double pas = std::fabs(domaine_vdf.distance_face(a,b,dir)) ;
4347 int traverse = 0 ;
4348 calcul_nb_traverse(xe,pas,dim,dir,maillage,i_elem,traverse) ;
4349 trav(i_elem,dir) = traverse ;
4350 }
4351 }
4352 else if( indicatrice(i_elem) == 0. )
4353 {
4354 // Cas des elements fluides
4355 for( int k=0; k<dim; k++)
4356 trav(i_elem,k) = -1 ;
4357 }
4358 else if( indicatrice(i_elem) == 1. )
4359 {
4360 // Cas des elements solides
4361 for( int k=0; k<dim; k++)
4362 trav(i_elem,k) = -2 ;
4363 }
4364 }
4365 trav.echange_espace_virtuel() ;
4366 //-----------------------------------------------------------------
4367 //-----------------------------------------------------------------
4368 // initialisation des compteurs de faces
4369 // faces monophasiques (de reference) : cpt_ref
4370 // faces diphasiques avec une cellule voisine de reference : cpt_vref
4371 // faces avec indicatrice_face = 0.5 et deux cellules voisines de reference : cpt_halfref
4372 int cpt_ref = 0 ;
4373 int cpt_vref = 0 ;
4374 int cpt_halfref = 0 ;
4375 DoubleTab typefacejoint ;
4376 IntList FACEJOINT ;
4377
4378 int nbjoints=domaine_vf.nb_joints();
4379 for(int njoint=0; njoint<nbjoints; njoint++)
4380 {
4381 const Joint& joint_temp = domaine_vf.joint(njoint);
4382 const IntTab& indices_faces_joint = joint_temp.joint_item(JOINT_ITEM::FACE).renum_items_communs();
4383 const int nb_faces = indices_faces_joint.dimension(0);
4384 for (int j = 0; j < nb_faces; j++)
4385 {
4386 int face_de_joint = indices_faces_joint(j, 1);
4387 FACEJOINT.add_if_not(face_de_joint) ;
4388 }
4389 }
4390 //-----------------------------------------------------------------
4391 // Parcourt des faces monophasiques sur le processeur courant
4392 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4393 {
4394 if( indicatrice_face(i_face) == 0. || indicatrice_face(i_face) == 1. )
4395 {
4396 typeface(i_face) = indicatrice_face(i_face) ;
4397 cpt_ref++ ;
4398 }
4399 }
4400 typefacejoint = typeface ;
4401 typeface.echange_espace_virtuel() ;
4402 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4403 {
4404 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4405 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1 )
4406 cpt_ref++;
4407 }
4408
4409 // Traitement des faces diphasiques locales ayant une cellule voisine de reference
4410 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4411 {
4412 // les faces avec une indicatrice de 0.5 sont traitees apres
4413 if( indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. && indicatrice_face(i_face) != 0.5 )
4414 {
4415 // Si l'un des deux voisins est monophasique alors i_face est du meme cote
4416 int reference_trouvee = 0 ;
4417 int i_voisin = 0 ;
4418 while( i_voisin < 2 && reference_trouvee == 0)
4419 {
4420 const int elem_voisin = faces_elem(i_face,i_voisin) ;
4421
4422 if( elem_voisin > -1 &&
4423 ( indicatrice(elem_voisin) == 0. || indicatrice(elem_voisin) == 1. ) )
4424 {
4425 reference_trouvee = 1 ;
4426 typeface(i_face) = indicatrice(elem_voisin) ;
4427 cpt_vref++;
4428 }
4429 i_voisin++ ;
4430 }
4431 }
4432 }
4433 typefacejoint = typeface ;
4434 typeface.echange_espace_virtuel() ;
4435 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4436 {
4437 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4438 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1
4439 && indicatrice_face(FACEJOINT[i]) != 0. && indicatrice_face(FACEJOINT[i]) != 1.
4440 && indicatrice_face(FACEJOINT[i]) != 0.5 )
4441 cpt_vref++;
4442 }
4443
4444 // Traitement des faces avec indicatrice_face = 0.5 et deux cellules voisines de reference
4445 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4446 {
4447 if( indicatrice_face(i_face) == 0.5 )
4448 {
4449 int element = -1 ;
4450 if( faces_elem(i_face,0) > -1 )
4451 element = faces_elem(i_face,0) ;
4452 else
4453 element = faces_elem(i_face,1) ;
4454
4455 if( indicatrice(element) == 0. || indicatrice(element) == 1. )
4456 {
4457 typeface(i_face) = 0.5 ;
4458 cpt_halfref++;
4459 }
4460 }
4461 }
4462 typefacejoint = typeface ;
4463 typeface.echange_espace_virtuel() ;
4464 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4465 {
4466 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4467 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1 && indicatrice_face(FACEJOINT[i]) == 0.5 )
4468 cpt_halfref++;
4469 }
4470
4471
4472 // A ce niveau, il reste a traiter les faces diphasiques ayant
4473 // deux cellules voisines traversees par l'IBC
4474 // Pour determiner leur type, on procede de proche en proche
4475 // a partir des faces deja determinees.
4476 // On itere le processus tant que l'ensemble des faces
4477 // n'a pas ete determine.
4478 // En parallele, il faut que chaque processeur procede
4479 // simultanement car a la fin de chaque processus
4480 // l'info est echangee. Ceci explique le "barrier()" (utile?)
4481 // On s'arrete des que chaque processeur a determine
4482 // toutes ces faces.
4483 //-----------------------------------------------------------
4484 // Initialisation des compteurs de faces
4485 // nombre de faces restant a determiner par processeur
4486 int cpt_rest = nfaces - cpt_ref - cpt_vref - cpt_halfref ;
4487 // nombre de face diphasique determinee au processus n
4488 int cpt_diph = 0 ;
4489 // critere d'arret pour le processeur courant
4490 double proc_stop = -1. ;
4491 // critere d'arret pour l'ensemble des processeurs
4492 double stop = -1. ;
4493 //////////////////////////////////////////////////////////////
4494 //////////////////////////////////////////////////////////////
4495 while( stop < 0 )
4496 {
4497 if( proc_stop < 0. )
4498 {
4499
4500 for( i_face = 0 ; i_face<nfaces ; i_face++)
4501 {
4502 if( typeface( i_face ) < 0 )
4503 {
4504 const int ori = orientation[i_face] ;
4505 const int elem0 = faces_elem(i_face,0) ;
4506 const int elem1 = faces_elem(i_face,1) ;
4507
4508 int elem = 0 ;
4509 if( elem0 > -1 && elem0 < nb_elem_tot )
4510 elem = elem0 ;
4511 else if( elem1 > -1 && elem1 < nb_elem_tot )
4512 elem = elem1 ;
4513 else
4514 {
4515 Process::Journal() << "erreur dans le choix de l'element "<<finl ;
4516 Process::exit() ;
4517 }
4518 int nb = trav(elem,ori) ;
4519
4520 // On regarde la face voisine que l'on va determiner. Elle peut etre virtuelle.
4521 int j_face = elem_faces(elem, ori) + elem_faces(elem, ori+dim) - i_face ;
4522
4523 if( typeface(j_face) > -1 )
4524 {
4525 // On modifie typeface(i_face)
4526 if( fmod( nb, 2. ) > 0 )
4527 {
4528 //Cas impair
4529 // a) le rayon rencontre une face fluide alors la face est solide
4530 // b) le rayon rencontre une face solide alors la face est fluide
4531 typeface(i_face) = 1. - typeface(j_face) ;
4532 }
4533 else
4534 {
4535 //Cas pair
4536 // a) le rayon rencontre une face fluide alors la face est fluide
4537 // b) le rayon rencontre une face solide alors la face est solide
4538 typeface(i_face) = typeface(j_face) ;
4539 }
4540 cpt_diph++ ;
4541 }
4542 else
4543 {
4544 elem = elem0 + elem1 - elem ;
4545 if( elem > -1 && elem < nb_elem_tot )
4546 {
4547 nb = trav(elem,ori) ;
4548 j_face = elem_faces(elem, ori) + elem_faces(elem, ori+dim) - i_face ;
4549
4550 if( typeface(j_face) > -1 )
4551 {
4552 // On modifie typeface(i_face)
4553 if( fmod( nb, 2. ) > 0 )
4554 {
4555 //Cas impair
4556 // a) le rayon rencontre une face fluide alors la face est solide
4557 // b) le rayon rencontre une face solide alors la face est fluide
4558 typeface(i_face) = 1. - typeface(j_face) ;
4559 }
4560 else
4561 {
4562 //Cas pair
4563 // a) le rayon rencontre une face fluide alors la face est fluide
4564 // b) le rayon rencontre une face solide alors la face est solide
4565 typeface(i_face) = typeface(j_face) ;
4566 }
4567 cpt_diph++ ;
4568 }
4569 }
4570 }
4571 }
4572 }
4573 }
4574 typefacejoint = typeface ;
4575 typeface.echange_espace_virtuel() ;
4576 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4577 {
4578 typeface(FACEJOINT[i]) = std::max(typefacejoint(FACEJOINT[i]),typeface(FACEJOINT[i])) ;
4579 if( typefacejoint(FACEJOINT[i]) < 0 && typeface(FACEJOINT[i]) > -1
4580 && indicatrice_face(FACEJOINT[i]) != 0. && indicatrice_face(FACEJOINT[i]) != 1.
4581 && indicatrice_face(FACEJOINT[i]) != 0.5 )
4582 cpt_diph++ ;
4583 }
4584
4585 // A t on determiner toutes les faces reelles du processeurs
4586 if( cpt_diph == cpt_rest )
4587 proc_stop = 0. ;
4588
4590 stop = mp_sum( proc_stop ) ;
4591 }
4592
4593 // Traitement secondaire des faces tres proche de l'IBC
4594 for( i_face = 0 ; i_face < nfaces ; i_face++ )
4595 {
4596 if( indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. )
4597 {
4598 int elem_voisin = 0 ;
4599 int j_face = 0 ;
4600 double dxa = 0 ;
4601 double dxb = 0 ;
4602 double Lref = 0. ;
4603 const int ori = orientation[i_face] ;
4604 if( faces_elem(i_face,0) > -1 )
4605 {
4606 j_face = elem_faces(faces_elem(i_face,0), ori) + elem_faces(faces_elem(i_face,0), ori+dim) - i_face ;
4607 dxa = std::fabs(domaine_vdf.distance_face(i_face,j_face,ori)) ;
4608 }
4609 if( faces_elem(i_face,1) > -1 )
4610 {
4611 j_face = elem_faces(faces_elem(i_face,1), ori) + elem_faces(faces_elem(i_face,1), ori+dim) - i_face ;
4612 dxb = std::fabs(domaine_vdf.distance_face(i_face,j_face,ori)) ;
4613 }
4614 if( dxa < dxb )
4615 {
4616 elem_voisin = faces_elem(i_face,1) ;
4617 Lref = dxb*dxb ;
4618 }
4619 else
4620 {
4621 elem_voisin = faces_elem(i_face,0) ;
4622 Lref = dxa*dxa ;
4623 }
4624
4625 for( int k=0 ; k<dim ; k++ )
4626 {
4627 if( k != ori )
4628 {
4629 int a = elem_faces(elem_voisin, k) ;
4630 int b = elem_faces(elem_voisin, k+dim) ;
4631 double pas = std::fabs(domaine_vdf.distance_face(a,b,k)) ;
4632 Lref += 0.25*pas*pas ;
4633 }
4634 }
4635 const double ratio = std::fabs(distance_interface_faces(i_face))/sqrt(Lref) ;
4636 const double tol_distface = 1e-3 ;
4637 const int test1 = ( ratio < tol_distface ) ;
4638 if( test1 )
4639 typeface(i_face) = 0.5 ;
4640 }
4641 }
4642 typefacejoint = typeface ;
4643 typeface.echange_espace_virtuel() ;
4644 for( int i=0 ; i<FACEJOINT.size() ; i++ )
4645 {
4646 typeface(FACEJOINT[i]) = typefacejoint(FACEJOINT[i]) ;
4647 }
4648
4649
4650 //////////////////////////////////////////////////////////////////////////////////////////////
4651 //////////////////////////////////////////////////////////////////////////////////////////////
4652 // Fin du lance de rayon
4653 //////////////////////////////////////////////////////////////////////////////////////////////
4654 //////////////////////////////////////////////////////////////////////////////////////////////
4655
4656
4657 //////////////////////////////////////////////////////////////////////////////////////////////
4658 //---- Correction de la distance entre les faces et l'IBC (hyp: |distance_interface_faces| correcte)
4659 for( i_face=0 ; i_face<nfaces ; i_face++ )
4660 {
4661 if( distance_interface_faces(i_face) > invalid_test )
4662 dist_face_cor(i_face) = (2.*typeface(i_face) - 1.)*std::fabs(distance_interface_faces(i_face)) ;
4663 else
4664 dist_face_cor(i_face) = distance_interface_faces(i_face) ;
4665 }
4666 }
4667 else
4668 {
4669 for( i_face=0 ; i_face<nfaces ; i_face++ )
4670 {
4671 dist_face_cor(i_face) = distance_interface_faces(i_face) ;
4672 }
4673 }
4674 dist_face_cor.echange_espace_virtuel() ;
4675
4676 //////////////////////////////////////////////////////////////////////////////////////////////
4677 ///----- variables pour post-traitement
4678 for( i_face=0 ; i_face<nfaces ; i_face++ )
4679 {
4680 variables_internes_->distance_interface_faces_corrigee->valeurs()(i_face) = dist_face_cor(i_face) ;
4681 variables_internes_->distance_interface_faces_difference->valeurs()(i_face) = dist_face_cor(i_face) - distance_interface_faces(i_face) ;
4682 }
4683
4684 if( variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::ANALYTIQUE
4685 && variables_internes_-> type_distance_calculee == Transport_Interfaces_FT_Disc_interne::DIST_MODIFIEE )
4686 {
4687 int cpt_face_fluide_signefaux = 0 ;
4688 int cpt_face_solide_signefaux = 0 ;
4689 int cpt_face_diphasique_signefaux = 0 ;
4690 int cpt_face_diphasique_signemodifiee = 0 ;
4691 int cpt_face_diphasique_signemodifiee_dnulle = 0 ;
4692 int nfaces_diphasique = 0 ;
4693 int nfaces_fluide = 0 ;
4694 int nfaces_solide = 0 ;
4695
4696 for( i_face=0 ; i_face<nfaces ; i_face++ )
4697 {
4698 if( indicatrice_face( i_face ) == 0. )
4699 nfaces_fluide++ ;
4700 else if( indicatrice_face( i_face ) == 1. )
4701 nfaces_solide++ ;
4702 else
4703 nfaces_diphasique++;
4704
4705 if( indicatrice_face( i_face ) == 0. && dist_face_cor( i_face ) >= 0. )
4706 {
4707 cpt_face_fluide_signefaux++ ;
4708 }
4709 else if( indicatrice_face( i_face ) == 1. && dist_face_cor( i_face ) <= 0. && dist_face_cor( i_face ) > invalid_test )
4710 {
4711 cpt_face_solide_signefaux++ ;
4712 }
4713 else if( indicatrice_face( i_face ) != 1. && indicatrice_face( i_face ) != 0. )
4714 {
4715 int element = -1 ;
4716 if( faces_elem(i_face,0) > -1 )
4717 element = faces_elem(i_face,0) ;
4718 else
4719 element = faces_elem(i_face,1) ;
4720
4721 if( indicatrice( element ) == 0. && dist_face_cor( i_face ) >= 0. )
4722 {
4723 cpt_face_diphasique_signefaux++ ;
4724 }
4725 else if( indicatrice( element ) == 1. && dist_face_cor( i_face ) <= 0. && dist_face_cor( i_face ) > invalid_test )
4726 {
4727 cpt_face_diphasique_signefaux++ ;
4728 }
4729 else
4730 {
4731 if( std::fabs(dist_face_cor(i_face) - distance_interface_faces(i_face)) != 0. )
4732 {
4733 cpt_face_diphasique_signemodifiee++ ;
4734 }
4735 if( dist_face_cor( i_face ) == 0. )
4736 {
4737 cpt_face_diphasique_signemodifiee_dnulle++ ;
4738 }
4739 }
4740 }
4741 }
4742 Cerr <<" -----------------------------------------------------"<< finl ;
4743 Cerr <<" -----------------------------------------------------"<< finl ;
4744 Cerr <<" -----------------------------------------------------"<< finl ;
4745 Cerr <<" Nombre de faces : "<< nfaces <<finl ;
4746 Cerr <<" Nombre de faces fluides : "<<nfaces_fluide<<finl;
4747 Cerr <<" Nombre de faces fluides avec mauvais signe : "<<cpt_face_fluide_signefaux<<finl;
4748 Cerr <<" Nombre de faces solides : "<<nfaces_solide<<finl;
4749 Cerr <<" Nombre de faces solides avec mauvais signe : "<<cpt_face_solide_signefaux<<finl;
4750 Cerr <<" Nombre de faces diphasiques : "<<nfaces_diphasique<<finl;
4751 Cerr <<" Nombre de faces diphasiques avec mauvais signe : "<<cpt_face_diphasique_signefaux<<finl;
4752 Cerr <<" Nombre de faces diphasiques avec signe modifie : "<<cpt_face_diphasique_signemodifiee<<finl;
4753 Cerr <<" Nombre de faces diphasiques avec signe modifie et distance nulle : "<<cpt_face_diphasique_signemodifiee_dnulle<<finl;
4754 Cerr <<" -----------------------------------------------------"<< finl ;
4755 Cerr <<" -----------------------------------------------------"<< finl ;
4756 Cerr <<" -----------------------------------------------------"<< finl ;
4757 }
4758
4759 //on stocke dans v_imp la composante de la vitesse de l'interface correspondant
4760 //au projete du centre de gravite d'une face sur l'interface
4761 DoubleTab v_imp(champ) ;
4762 v_imp = 0. ;
4763 Cerr << " INITIALISATION DE Vimp a Vsolide pour les faces solides "<<finl ;
4764 for ( i_face = 0; i_face < nfaces; i_face++)
4765 {
4766 const double d = dist_face_cor(i_face) ;
4767 if ( d>0. || (indicatrice_face(i_face) == 1. && d < -1.e20) )
4768 {
4769 for (int j = 0; j < dim; j++)
4770 {
4771 const double coord = xv(i_face,j);
4772 parser_x.setVar(j, coord) ;
4773 parser_y.setVar(j, coord) ;
4774 if (dim==3)
4775 parser_z.setVar(j, coord) ;
4776 }
4777 if (zvdf)
4778 {
4779 switch(zvdf->orientation(i_face))
4780 {
4781 case 0:
4782 v_imp(i_face) = parser_x.eval() ;
4783 break ;
4784 case 1:
4785 v_imp(i_face) = parser_y.eval() ;
4786 break ;
4787 case 2:
4788 v_imp(i_face) = parser_z.eval() ;
4789 break ;
4790 }
4791 }
4792 }
4793 }
4794 v_imp.echange_espace_virtuel() ; // CI
4795
4796 if(variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::UNIFORME)
4797 {
4798 //si la vitesse est uniforme on peut calculer directement le gradient ici
4799 Cerr << "Transport_Interfaces_FT_Disc_interne::UNIFORME " << finl;
4800 double vx=0,vy=0,vz=0;
4801 int ix=0,iy=0,iz=0;
4802 for ( i_face = 0; i_face < nfaces; i_face++)
4803 {
4804 // Calcul de la composante normale du gradient du champ:
4805 // gradient normal = (champ - valeur_interface) / distance.
4806
4807 double d = dist_face_cor(i_face) ;
4808 if (indicatrice_face(i_face) == indic_phase && d > invalid_test)
4809 {
4810 //Vitesse imposee evaluee au centre des faces
4811 for (int j = 0; j < dim; j++)
4812 {
4813 const double coord = xv(i_face,j);
4814 parser_x.setVar(j, coord);
4815 parser_y.setVar(j, coord);
4816 if (dimension3)
4817 parser_z.setVar(j, coord);
4818 }
4819
4820 if (zvdf)
4821 {
4822 v_imp(i_face) = 0.;
4823 // PL Ajout de la verification que la vitesse est bien uniforme
4824 switch(zvdf->orientation(i_face))
4825 {
4826 case 0:
4827 v_imp(i_face) = parser_x.eval() ;
4828 check(v_imp,i_face,vx,ix);
4829 break ;
4830 case 1:
4831 v_imp(i_face) = parser_y.eval() ;
4832 check(v_imp,i_face,vy,iy);
4833 break ;
4834 case 2:
4835 v_imp(i_face) = parser_z.eval() ;
4836 check(v_imp,i_face,vz,iz);
4837 break ;
4838 }
4839 gradient(i_face) = (champ(i_face) - v_imp(i_face)) / d ;
4840 }
4841 }
4842 }
4843 }
4844 else if (variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::ANALYTIQUE)
4845 {
4846 // Si la vitesse n'est pas uniforme, on projete les points suceptibles
4847 // d'etre interpoles sur l'interface de facon a calculer un gradient
4848 // correct
4849 Cerr << "Transport_Interfaces_FT_Disc_interne::ANALYTIQUE "<< finl ;
4850
4851 if( variables_internes_->type_indic_faces_ == Transport_Interfaces_FT_Disc_interne::MODIFIEE && variables_internes_-> type_projete_calcule != Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE)
4852 {
4853 double indic_pos=variables_internes_->modified_indic_faces_position;
4854 double indic_thi=variables_internes_->modified_indic_faces_thickness;
4855 if (indic_pos-0.5*indic_thi < -1.)
4856 {
4857 Cerr << "-------------------------------------------------------------------------" << finl;
4858 Cerr << "-------------------------------------------------------------------------" << finl;
4859 Cerr << "The datafile ask to use type_vitesse_imposee=ANALYTIQUE and" << finl;
4860 Cerr << "type_indic_faces modifiee with a too large transition to reach zero" << finl;
4861 Cerr << "There is a big risk that fluid gradients cannot be computed" << finl;
4862 Cerr << "because fluid points (Indic_faces=0) are too far from the interface" << finl;
4863 Cerr << "To fix that, just do one of the following things:" << finl;
4864 Cerr << "If the imposed velocity field is uniform, use type_vitesse_imposee=UNIFORM" << finl;
4865 Cerr << "If not, use \"distance_projete_faces simplifiee\" " << finl;
4866 Cerr << "-------------------------------------------------------------------------" << finl;
4867 Cerr << "-------------------------------------------------------------------------" << finl;
4868 Process::exit();
4869 }
4870
4871 }
4872
4873 if(variables_internes_-> type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE)
4874 {
4875 Cerr << "Transport_Interfaces_FT_Disc_interne::PROJETE_SIMPLIFIE, calcul a partir des distances et normales" << finl;
4876
4877 // Ici, on ne calcule pas de projete avec uzawa, on utilise simplement les quantites deja calculees dans le code
4878 // on a la distance interface-faces d, donc en determinant une normale aux faces n_F, on peut en deduire
4879 // le projete x_P de la facon suivante :
4880 // x_P = x_F - d * N_F
4881 // on determine la normale aux faces comme la moyenne de la normale aux elements.
4882
4883 const DoubleTab& normale_elem = get_normale_interface().valeurs();
4884 for (i_face = 0; i_face < nfaces; i_face++)
4885 {
4886 double d = dist_face_cor(i_face) ;
4887 const int diphasique_tmp = (indicatrice_face(i_face) != 0. &&
4888 (indicatrice_face(i_face) != 1. || (indicatrice_face(i_face) == 1. && d<=0. && d> invalid_test)));
4889 const int diphasique = ( variables_internes_->is_extra_diphasique_solide ? diphasique_tmp : (diphasique_tmp && d <= 0.) ) ;
4890 const int fluide = ( indicatrice_face(i_face) == 0. ) ;
4891 const int solide = ( variables_internes_->is_extra_solide && (d>0. || (indicatrice_face(i_face) == 1. && d<-1.e20)) ) ;
4892 const int monophasique = ( fluide || solide ) ;
4893
4894 if (diphasique || (monophasique && d> invalid_test ))
4895 {
4896 DoubleTab coord_projete(dim) ;
4897 DoubleTab normale_face(dim) ;
4898 DoubleTab coord_face(dim) ;
4899 coord_projete = 0. ;
4900 normale_face = 0. ;
4901 coord_face = 0. ;
4902 double cpt_normale = 0.;
4903 // Coordonnee au centre de la face :
4904 for (int i=0 ; i<dim ; i++)
4905 coord_face(i) = xv(i_face, i) ;
4906 // Normale a l IBC au centre de la face
4907 // calculee avec la moyenne des normales aux elements voisins
4908 for(int i=0 ; i<2; i++)
4909 {
4910 const int elem_voisin = faces_elem(i_face,i) ;
4911 if (elem_voisin > -1)
4912 {
4913 for (int j = 0; j < dim; j++)
4914 normale_face(j) += normale_elem(elem_voisin, j);
4915 cpt_normale += 1. ;
4916 }
4917 }
4918 assert(cpt_normale!=0.);
4919 normale_face /=cpt_normale;
4920 double norme_normale = 0.;
4921 for (int i=0 ; i<dim ; i++)
4922 norme_normale +=normale_face(i)*normale_face(i);
4923 assert(norme_normale!=0.);
4924 normale_face /= sqrt(norme_normale);
4925 // Coordonnee du projete :
4926 for (int i=0 ; i<dim ; i++)
4927 coord_projete(i) = coord_face(i) - d*normale_face(i);
4928 //v_imp au projete :
4929 for (int j = 0; j < dim; j++)
4930 {
4931 parser_x.setVar(j, coord_projete(j)) ;
4932 parser_y.setVar(j, coord_projete(j)) ;
4933 if (dim==3)
4934 parser_z.setVar(j, coord_projete(j)) ;
4935 }
4936 if (zvdf)
4937 {
4938 switch(zvdf->orientation(i_face))
4939 {
4940 case 0:
4941 v_imp(i_face) = parser_x.eval() ;
4942 break ;
4943 case 1:
4944 v_imp(i_face) = parser_y.eval() ;
4945 break ;
4946 case 2:
4947 v_imp(i_face) = parser_z.eval() ;
4948 break ;
4949 }
4950 }
4951 }
4952 }
4953 }
4954 else
4955 {
4956
4957 //------------------------
4958 //Initialisation
4959 //------------------------
4960 // 'exec_planfa7existant = 1' permet d'activer la routine
4961 // 'plan_facette_existant' dans 'RenumFa7' et 'StockageFa7'.
4962 // Pour un element donne, cette routine permet d'eviter de
4963 // selectionner deux facettes de meme plan.
4964 // Basee sur des criteres geometriques, elle peut conduire dans
4965 // certains cas a des differences sequentiel/parallele.
4966 // Son activation est recommandee lorsque le nombre de facettes
4967 // par element est important et qu'une majorite d'entre elles
4968 // a le meme plan.
4969 const int exec_planfa7existant = 0 ;
4970 int nb_facettes = maillage.nb_facettes() ;
4971 // dimfa7 :
4972 // Surement gourmand en allocation memoire pour des maillages fins
4973 // +1 pour s'assurer qu'en cas de doublon num_max_facette
4974 // +nb_facettes_dim!=dimfa7
4975 // La somme des facettes par processeur n'est pas egale au nombre
4976 // de facettes total en sequentiel a cause des doublons.
4977 // Note: Cannot combine mp_sum and mp_max as they are different operations
4978 int dimfa7 = int( Process::mp_sum( double(nb_facettes) ) )+1 ;
4979 int nb_facettes_dim = int( Process::mp_max( double(nb_facettes) ) ) ;
4980 // Nombre max de facettes acceptees et calculees par element
4981 // Le nombre de facette acceptees est choisi des que le maillage
4982 // Lagrangien est significativement plus fin que le maillage Eulerien.
4983 // Dans ce cas, on se retrouve avec un nombre consequent de facettes
4984 // par element (eg. maillage importe d'une CAO)
4985 int nb_fa7_accepted = variables_internes_->nomb_fa7_accepted;
4986 int max_fa7 = nb_fa7_accepted ;
4987 // OutElem : liste des eventuels elements qui contiennent un nombre
4988 // de facettes superieurs a nb_fa7_accepted.
4989 // OutFa7 : liste des facettes considerees comme etant les plus
4990 // representatives de l'IBC.
4991 IntList OutElem, OutFa7 ;
4992
4993 // Remplissage des listes OutElem et OutFa7
4994 calcul_OutElemFa7(maillage,indicatrice,nb_elem,nb_fa7_accepted,OutElem,OutFa7) ;
4995
4996 // Dans la mesure ou le nombre de facettes par element est inferieur a
4997 // nb_fa7_accepted alors on calcule le nombre max de facettes afin
4998 // d'optimiser la dimension des tableaux distribues (voir plus bas)
4999 if( OutElem.est_vide() )
5000 calcul_maxfa7(maillage,indicatrice,nb_elem,max_fa7,exec_planfa7existant) ;
5001
5002 int nb_facettes_in_elem = int( Process::mp_max( double(max_fa7) ) ) ;
5003
5004 // Tableaux distribues pour le stokage des facettes par elements
5005 // nb_elem : nb d'elements reels par processeur
5006 // Tab10i :
5007 // - entrees i= 0,1,2,3 : parametres du plan d'une facette (a,b,c,d)
5008 // Tab11i :
5009 // - entrees i= 0,1,2 : coordonnees du barycentre d'une facette
5010 // Tab12 : numero local de la facette ( < nb_facettes )
5011 // utile pour la renumerotation des facettes virtuelles
5012 DoubleTab Tab100( nb_elem, nb_facettes_in_elem ) ;
5013 DoubleTab Tab101( nb_elem, nb_facettes_in_elem ) ;
5014 DoubleTab Tab102( nb_elem, nb_facettes_in_elem ) ;
5015 DoubleTab Tab103( nb_elem, nb_facettes_in_elem ) ;
5016 DoubleTab Tab110( nb_elem, nb_facettes_in_elem ) ;
5017 DoubleTab Tab111( nb_elem, nb_facettes_in_elem ) ;
5018 DoubleTab Tab112( nb_elem, nb_facettes_in_elem ) ;
5019 IntTab Tab12( nb_elem, nb_facettes_in_elem ) ;
5020 // Tableau distribue stockant le nb de facettes par element
5021 IntTab CptFacette( nb_elem ) ;
5022
5023 // Tableau distribue pour le calul du sommet de facette
5024 // le plus proche du barycentre d'une face
5025 DoubleTab Vertex(nfaces,dim) ;
5026 DoubleTab PPP(nfaces,dim) ;
5027
5028 // Distribution des tableaux (uniquement en parallele)
5029 if( nb_elem < nb_elem_tot )
5030 {
5031 domaine_vf.domaine().creer_tableau_elements(Tab100, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5032 domaine_vf.domaine().creer_tableau_elements(Tab101, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5033 domaine_vf.domaine().creer_tableau_elements(Tab102, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5034 domaine_vf.domaine().creer_tableau_elements(Tab103, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5035 domaine_vf.domaine().creer_tableau_elements(Tab110, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5036 domaine_vf.domaine().creer_tableau_elements(Tab111, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5037 domaine_vf.domaine().creer_tableau_elements(Tab112, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5038 domaine_vf.domaine().creer_tableau_elements(Tab12, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5039 domaine_vf.domaine().creer_tableau_elements(CptFacette, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5040 domaine_vf.creer_tableau_faces(Vertex, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5041 domaine_vf.creer_tableau_faces(PPP, RESIZE_OPTIONS::NOCOPY_NOINIT) ;
5042 }
5043 CptFacette = 0 ;
5044 Tab100 = -1e+30 ;
5045 Tab101 = -1e+30 ;
5046 Tab102 = -1e+30 ;
5047 Tab103 = -1e+30 ;
5048 Tab110 = -1e+30 ;
5049 Tab111 = -1e+30 ;
5050 Tab112 = -1e+30 ;
5051 Tab12 = -1 ;
5052 Vertex = 1.e30 ;
5053 PPP = 1.e30 ;
5054
5055 // Tableau des coordonnees barycentrique des facettes
5056 DoubleTab Barycentre(nb_facettes, 3) ;
5057 Barycentre = 0. ;
5058
5059 Cerr << "STOKAGE DES FACETTES " << finl ;
5060 ArrOfBit fa7(maillage.nb_facettes()) ;
5061 fa7 = 0 ;
5062 StockageFa7(maillage,CptFacette,Tab100,Tab101,Tab102,Tab103,
5063 Tab110,Tab111,Tab112,Tab12,Barycentre,indicatrice,
5064 OutElem,fa7,exec_planfa7existant) ;
5065
5066 // On traite ici des 'OutElem.size()' elements dont le nombre de
5067 // facettes est superieur a nb_fa7_accepted.
5068 if( !OutElem.est_vide() )
5069 {
5070 if( OutFa7.size() != OutElem.size()*nb_fa7_accepted )
5071 {
5072 Cerr << "ERREUR DE DIMENSIONNEMENT " << finl ;
5073 Cerr << " OutFa7.size() "<<OutFa7.size()<<finl ;
5074 Cerr << " OutElem.size()*nb_fa7_accepted "<<OutElem.size()*nb_fa7_accepted<<finl ;
5075 Process::exit() ;
5076 }
5077
5078 // Tableau des numeros de facettes retenues
5079 // dans les 'OutElem.size()' elements.
5080 IntTab TabOutFa7(OutElem.size(),nb_fa7_accepted) ;
5081 for( int i=0 ; i< OutElem.size() ; i++)
5082 {
5083 // Chaque element contient nb_fa7_accepted facettes.
5084 CptFacette( OutElem[i] ) = nb_fa7_accepted ;
5085 for( int j=0 ; j< nb_fa7_accepted ; j++)
5086 {
5087 TabOutFa7(i,j) = OutFa7[j+i*nb_fa7_accepted] ;
5088 }
5089 }
5090 StockageFa7(maillage,Tab100,Tab101,Tab102,Tab103,Tab110,Tab111,Tab112,
5091 Tab12,Barycentre,OutElem,TabOutFa7,fa7) ;
5092 }
5093 // Echange entre les processeurs
5094 Tab100.echange_espace_virtuel() ;
5095 Tab101.echange_espace_virtuel() ;
5096 Tab102.echange_espace_virtuel() ;
5097 Tab103.echange_espace_virtuel() ;
5098 Tab110.echange_espace_virtuel() ;
5099 Tab111.echange_espace_virtuel() ;
5100 Tab112.echange_espace_virtuel() ;
5101 Tab12.echange_espace_virtuel() ;
5102 CptFacette.echange_espace_virtuel() ;
5103 // Numerotation locale des facettes virtuelles (uniquement en parallele)
5104 if( nb_elem < nb_elem_tot )
5105 {
5106 Cerr << " RENUMEROTATION DES FACETTES VIRTUELLES " << finl ;
5107 RenumFa7(Barycentre,Tab110,Tab111,Tab112,Tab12,CptFacette,
5108 nb_facettes,nb_facettes_dim) ;
5109 }
5110
5111 if(variables_internes_-> type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE)
5112 {
5113 // Demarche :
5114 // 1) chaque face diphasique appartient au moins a un element diphasique
5115 // 1) on identifie donc dans ces elements voisins diphasique
5116 // 1) le sommet de facette le plus proche et on le stocke dans
5117 // 1) Vertex.
5118 //
5119 // 2) On parcourt a nouveau les faces diphasiques mais cette fois en regardant les
5120 // 2) elements voisins des elements voisins. Le sommet le plus proche definitif
5121 // 2) pour ces faces est stocke dans PPP.
5122 //
5123 // 3) On parcourt enfin les faces fluides, on determine leurs faces voisines diphasiques
5124 // 3) et a partir de ces dernieres on determine le sommet le plus proche.
5125 // 3) qui est stocke dans PPP.
5126 //
5127 Cerr << " IDENTIFICATICATION DU VERTEX LE PLUS PROCHE POUR LES FACES CONCERNEES PAR LA PROJECTION " << finl ;
5128 Cerr << " CAS DES FACES APPARTENANT A AU MOINS UN ELEMENT TRAVERSE : ETAPE 1 " <<finl ;
5129 PPP_face_interface(maillage,indicatrice,indicatrice_face,Vertex) ;
5131 Cerr << " CAS DES FACES APPARTENANT A AU MOINS UN ELEMENT TRAVERSE : ETAPE 2 " <<finl ;
5132 PPP_face_interface_voisin(indicatrice,indicatrice_face,Vertex,PPP) ;
5134 Cerr << " CAS DES FACES MONOPHASIQUE : ETAPE 3 " <<finl ;
5135 PPP_face_voisin(indicatrice,indicatrice_face,PPP) ;
5137 Cerr << " FIN IDENTIFICATION " << finl ;
5138 }
5139 // Nombre de point projete modifie a partir d'un critere de distance
5140 int nb_proj_modif = 0 ;
5141 int nb_proj_modif_tot = 0 ;
5142 Cerr << "CALCUL DU PROJETE POUR LES FACES QUI APPARTIENNENT " << finl ;
5143 Cerr << "A UN ELEMENT TRAVERSE PAR L INTERFACE" << finl;
5144 projete_point_face_interface(nb_proj_modif,dimfa7,indicatrice_face,indicatrice,dist_face_cor,t,dt,Tab100,
5145 Tab101,Tab102,Tab103,Tab12,CptFacette,v_imp,PPP,parser_x,parser_y,parser_z) ;
5146 nb_proj_modif_tot = Process::check_int_overflow(mp_sum(nb_proj_modif)) ;
5148 Cerr << " Nombre de projete modifie pour les faces diphasiques : "<<nb_proj_modif_tot<<" au temps "<<schema_temps().temps_courant()<<finl ;
5149
5150 //----------------------------------------------------------------
5151 //----------------------------------------------------------------
5152 Cerr << "CALCUL DU PROJETE POUR LES FACES FLUIDE " << finl ;
5153 projete_point_face_fluide(nb_proj_modif,dimfa7,indicatrice_face,indicatrice,dist_face_cor,
5154 t,dt,Tab100,Tab101,Tab102,Tab103,Tab12,CptFacette,v_imp,PPP,parser_x,parser_y,parser_z) ;
5155 v_imp.echange_espace_virtuel() ;
5156 nb_proj_modif_tot = Process::check_int_overflow(mp_sum(nb_proj_modif)) ;
5158 Cerr << " Nombre de projete modifie pour les faces fluides : "<<nb_proj_modif_tot<<" au temps "<<schema_temps().temps_courant()<<finl ;
5159 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face vimp",v_imp);
5160 }
5161 }
5162
5163 for (i_face = 0; i_face < nfaces; i_face++)
5164 {
5165 double d = dist_face_cor(i_face) ;
5166 if (indicatrice_face(i_face) == indic_phase && d > invalid_test)
5167 {
5168 gradient(i_face) = (champ(i_face) - v_imp(i_face))/d ;
5169 }
5170 }
5171 gradient.echange_espace_virtuel();
5172 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face gradient avant etalement",gradient);
5173
5174 // On etale ce gradient par continuite sur une epaisseur de "stencil_value"
5175 // Les iterations de cet algorithme convergent vers une sorte de laplacien=0
5176 // avec condition aux limites de Dirichlet sur les elements de la phase
5177 // "phase".
5178 DoubleTab gradient_old;
5179 Cerr << "Nombre d'iterations de la methode interpoler_vitesse_face = " << stencil_width << finl;
5180 for (int iteration = 0; iteration < stencil_width; iteration++)
5181 {
5182 // Copie de la valeur du gradient: on ne veut pas utiliser les valeurs
5183 // calculees lors de l'iteration courante
5184 gradient_old = gradient;
5185 // La valeur sur une face est la moyenne des valeurs sur les faces
5186 // les plus proches (interpolation 'en croix' : a partir de 4 faces
5187 // voisines en 2D et 6 faces voisines en 3D dans le cas general)
5188 for (i_face = 0; i_face < nfaces; i_face++)
5189 {
5190 const double d = dist_face_cor(i_face) ;
5191 if (indicatrice_face(i_face) != indic_phase && d > invalid_test)
5192 {
5193 // Ne pas toucher au gradient de la phase "phase".
5194 // Iterer sur les autres valeurs.
5195 double somme = 0.;
5196 double coeff = 0.;
5197 const int ori=orientation(i_face);
5198 const int elem0 = faces_elem(i_face, 0);
5199 const int elem1 = faces_elem(i_face, 1);
5200 int elem=-1;
5201 if (elem0 >= 0)
5202 elem=elem0;
5203 else
5204 elem=elem1;
5205
5206 for (int direction=0; direction < dimension; direction++)
5207 {
5208 if (direction==ori)
5209 {
5210 //Dans la direction de la composante de i_face, on ajoute la contribution des 2 faces qui ont un element commun avec i_face
5211 if (elem0 >= 0)
5212 {
5213 const int voisin0 = elem_faces(elem0, ori) + elem_faces(elem0, ori+dimension) - i_face;
5214 if( (elem_faces(elem0, ori) != i_face) && (elem_faces(elem0, ori+dimension) != i_face) )
5215 {
5216 Cerr << "Attention, il y a un probleme sur la numerotation des faces. On calcule en effet" << finl ;
5217 Cerr << "elem_faces(elem0, ori) = " <<elem_faces(elem0, ori)<< finl ;
5218 Cerr << "elem_faces(elem0, ori+dimension) = " <<elem_faces(elem0, ori+dimension)<< finl ;
5219 Cerr << "i_face = " <<i_face<< finl;
5220 Cerr << "tandis qu'au moins un des deux calculs 'elem_faces(elem0, ori)' ou 'elem_faces(elem0, ori+dimension)'"<<finl ;
5221 Cerr << "doit correspondre au nuemro de la face i_face"<<finl ;
5222 Cerr << "Attention, verifier les conditions aux limites."<<finl ;
5223 Cerr << "En effet, le codage suivant ne permet pas de prendre en compte des conditions" << finl ;
5224 Cerr << "de periodicite avec une vitesse solide imposee analytique." << finl ;
5225 Process::exit() ;
5226 }
5227 const double grad0 = gradient_old(voisin0);
5228 if (grad0 > invalid_test)
5229 {
5230 somme += grad0;
5231 coeff++;
5232 }
5233 }
5234 if (elem1 >= 0)
5235 {
5236 const int voisin1 = elem_faces(elem1, ori) + elem_faces(elem1, ori+dimension) - i_face;
5237 if( (elem_faces(elem1, ori) != i_face) && (elem_faces(elem1, ori+dimension) != i_face) )
5238 {
5239 Cerr << "Attention, il y a un probleme sur la numerotation des faces. On calcule en effet" << finl ;
5240 Cerr << "elem_faces(elem1, ori) = " <<elem_faces(elem1, ori)<< finl ;
5241 Cerr << "elem_faces(elem1, ori+dimension) = " <<elem_faces(elem1, ori+dimension)<< finl ;
5242 Cerr << "i_face = " <<i_face<< finl;
5243 Cerr << "tandis qu'au moins un des deux calculs 'elem_faces(elem1, ori)' ou 'elem_faces(elem1, ori+dimension)'"<<finl ;
5244 Cerr << "doit correspondre au nuemro de la face i_face"<<finl ;
5245 Cerr << "Attention, verifier les conditions aux limites."<<finl ;
5246 Cerr << "En effet, le codage suivant ne permet pas de prendre en compte des conditions" << finl ;
5247 Cerr << "de periodicite avec une vitesse solide imposee analytique." << finl ;
5248 Process::exit() ;
5249 }
5250 const double grad1 = gradient_old(voisin1);
5251 if (grad1 > invalid_test)
5252 {
5253 somme += grad1;
5254 coeff++;
5255 }
5256 }
5257 }
5258 else
5259 {
5260 //Dans les autres directions, on ajoute les contributions des faces appartenant aux elements voisins, si elles existent:
5261
5262 //-on identifie les faces de elem (=un des deux elements auxquels appartient i_face) de direction differente de i_face
5263 //-on identifie les elements auxquels appartiennent ces faces
5264 //-pour chaque element voisin, on veut trouver la face la plus proche de i_face : on compare la distance entre les centres des faces
5265 const int face0=elem_faces(elem,direction);
5266 const int face1=elem_faces(elem,direction+dimension);
5267 const int elem_voisin0=faces_elem(face0,0)+faces_elem(face0,1)-elem;
5268 const int elem_voisin1=faces_elem(face1,0)+faces_elem(face1,1)-elem;
5269
5270 double a_carre=0.;
5271 double b_carre=0.;
5272 double grad_voisin0=0.;
5273 double c_carre=0.;
5274 double d_carre=0.;
5275 double grad_voisin1=0.;
5276
5277 if (elem_voisin0 >= 0)
5278 {
5279 for (int compo = 0; compo<dimension; compo++)
5280 {
5281 double c_gravite=xv(i_face,compo);
5282 double c_face_voisin1=xv(elem_faces(elem_voisin0,ori),compo);
5283 double c_face_voisin2=xv(elem_faces(elem_voisin0,ori+dimension),compo);
5284 a_carre+=(c_gravite-c_face_voisin1)*(c_gravite-c_face_voisin1);
5285 b_carre+=(c_gravite-c_face_voisin2)*(c_gravite-c_face_voisin2);
5286 }
5287 if (a_carre<b_carre)
5288 grad_voisin0=gradient_old(elem_faces(elem_voisin0,ori));
5289 else
5290 grad_voisin0=gradient_old(elem_faces(elem_voisin0,ori+dimension));
5291 if (grad_voisin0 > invalid_test)
5292 {
5293 somme += grad_voisin0;
5294 coeff++;
5295 }
5296 }
5297 if (elem_voisin1 >= 0)
5298 {
5299 for (int compo = 0; compo<dimension; compo++)
5300 {
5301 double c_gravite=xv(i_face,compo);
5302 double c_face_voisin3=xv(elem_faces(elem_voisin1,ori),compo);
5303 double c_face_voisin4=xv(elem_faces(elem_voisin1,ori+dimension),compo);
5304 c_carre+=(c_gravite-c_face_voisin3)*(c_gravite-c_face_voisin3);
5305 d_carre+=(c_gravite-c_face_voisin4)*(c_gravite-c_face_voisin4);
5306 }
5307 if (c_carre<d_carre)
5308 grad_voisin1=gradient_old(elem_faces(elem_voisin1,ori));
5309 else
5310 grad_voisin1=gradient_old(elem_faces(elem_voisin1,ori+dimension));
5311 if (grad_voisin1 > invalid_test)
5312 {
5313 somme += grad_voisin1;
5314 coeff++;
5315 }
5316 }
5317 }
5318 }
5319
5320 if (coeff > 0.)
5321 gradient(i_face) = somme / coeff;
5322 }
5323 }
5324 gradient.echange_espace_virtuel();
5325 }
5326
5327 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face gradient",gradient);
5328 // Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face distance_interface_faces",distance_interface_faces);
5329 // On calcule la valeur extrapolee:
5330 for (i_face = 0; i_face < nfaces; i_face++)
5331 {
5332 if (indicatrice_face(i_face) != indic_phase)
5333 {
5334 double d = dist_face_cor(i_face) ;
5335 const double grad = gradient[i_face];
5336 const double indic = indicatrice_face(i_face) ;
5337
5338 const int interpolation = ( d < 0. ) ;
5339 const int extra_diphasique = ( variables_internes_->is_extra_diphasique_solide && indic != 0. && indic != 1. && d > 0. ) ;
5340 const int extra_solide = ( variables_internes_->is_extra_solide && indic == 1. && (d>0. || d < -1.e20) ) ;
5341 const int extrapolation = ( extra_diphasique || extra_solide ) ;
5342 if (variables_internes_-> type_vitesse_imposee == Transport_Interfaces_FT_Disc_interne::UNIFORME)
5343 {
5344 //Vitesse imposee evaluee au centre des faces
5345 for (int j = 0; j < dim; j++)
5346 {
5347 const double coord = xv(i_face,j);
5348 parser_x.setVar(j, coord);
5349 parser_y.setVar(j, coord);
5350 if (dimension3)
5351 parser_z.setVar(j, coord);
5352 }
5353
5354 if (zvdf)
5355 {
5356 v_imp(i_face) = 0. ;
5357 switch(zvdf->orientation(i_face))
5358 {
5359 case 0:
5360 v_imp(i_face) = parser_x.eval();
5361 break;
5362 case 1:
5363 v_imp(i_face) = parser_y.eval();
5364 break;
5365 case 2:
5366 v_imp(i_face) = parser_z.eval();
5367 break;
5368 }
5369 champ( i_face ) = v_imp(i_face) ;
5370
5371
5372 if (grad > invalid_test && d > invalid_test && ( interpolation || extrapolation ) )
5373 {
5374 champ(i_face) += d*grad ;
5375 }
5376 }
5377 }
5378 else
5379 {
5380 // Vitesse non uniforme : il faut projeter utiliser le tableau v_imp
5381 // qui contient la vitesse du projete de i_face sur l'interface
5382
5383 champ(i_face) = v_imp(i_face) ;
5384 if (grad > invalid_test && d > invalid_test && ( interpolation || extrapolation ) )
5385 {
5386 champ(i_face) += d * grad ;
5387 }
5388 }
5389 vitesse_imp_interp_->valeurs()(i_face)= champ( i_face ) ;
5390 }
5391 else
5392 {
5393 vitesse_imp_interp_->valeurs()(i_face)=-3e30;
5394 }
5395 }
5396 champ.echange_espace_virtuel() ;
5397 Debog::verifier("Transport_Interfaces_FT_Disc::interpoler_vitesse_face champ",champ );
5398
5399}
5400
5401// Calcul le nombre de fois que l'on traverse l'IBC
5402void Transport_Interfaces_FT_Disc::calcul_nb_traverse( const DoubleTab& xe, const double dx,
5403 const int dim, const int ori,
5404 Maillage_FT_Disc& maillage, int elem,
5405 int& traverse )
5406
5407{
5408 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
5409 const ArrOfInt& index_elem = intersection.index_elem() ;
5410 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes() ;
5411 const IntTab& facettes = maillage.facettes() ;
5412 //const int nb_som = facettes.line_size() ;
5413 const DoubleTab& sommets = maillage.sommets() ;
5414 //IntTab Som( nb_som ) ;
5415 // Pour un element donne, on parcourt ces facettes
5416 int index = index_elem[elem] ;
5417 const double precision = Objet_U::precision_geom ;
5418 const double tol_theta = 1e-4 ;
5419 double I_sur_arete_fa7 = 0. ;
5420 double I_sur_arete_vertex = 0. ;
5421 int I_dans_fa7 = 0 ;
5422
5423 while (index >= 0 )
5424 {
5425 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
5426 const int i_facette = data.numero_facette_;
5427
5428 // produit scalaire entre un vecteur directeur au rayon et la normale a la facette
5429 // le vecteur de reference est unitaire valant un sur la composante ori.
5430 // Si le produit scalaire est nul alors il n'existe pas de I dans la facette
5431 if( std::fabs( normale_facettes(i_facette,ori) ) > 0. )
5432 {
5433 DoubleTab A(dim), B(dim), C(dim), U(dim), I(dim);
5434 A = 0. ;
5435 B = 0. ;
5436 C = 0. ;
5437 U = 0. ;
5438 I = 0. ;
5439 for(int i = 0 ; i<dim ; i++)
5440 {
5441 I(i) = xe(i) ;
5442 }
5443 I(ori) = 0. ;
5444 for(int i=0 ; i<dim ; i++)
5445 {
5446 U(i) = normale_facettes(i_facette,i) ;
5447 A(i) = sommets(facettes(i_facette, 0),i) ;
5448 B(i) = sommets(facettes(i_facette, 1),i) ;
5449 if( dim == 3 )
5450 C(i) = sommets(facettes(i_facette, 2),i) ;
5451 }
5452
5453 for( int i =0 ; i<dim ; i++)
5454 {
5455 if( i!=ori )
5456 I(ori) += (A(i) - I(i))*U(i)/U(ori) ;
5457 }
5458 I(ori) += A(ori) ;
5459
5460
5461 double FIscalU = (I(ori)-xe(ori))*U(ori) ;
5462 double FI = std::fabs( I(ori)-xe(ori) ) ;
5463 double theta = acos(FIscalU/FI) ;
5464 double theta_rel = std::fabs( theta - (2.0*atan(1.)) ) / (2.0*atan(1.)) ;
5465 double ecart_elem = std::fabs(xe(ori)-I(ori)) ;
5466
5467 if( theta_rel >= tol_theta && ecart_elem <= 0.5*dx )
5468 {
5469 if( dim == 2 )
5470 {
5471 double AIscalAB = (I(0)-A(0))*(B(0)-A(0)) + (I(1)-A(1))*(B(1)-A(1)) ;
5472 double ABscalAB = (B(0)-A(0))*(B(0)-A(0)) + (B(1)-A(1))*(B(1)-A(1)) ;
5473 double xx = AIscalAB / ABscalAB ;
5474
5475 const int test1 = ( std::fabs( xx ) <= precision ) ;
5476 const int test2 = ( std::fabs( xx - 1. ) <= precision ) ;
5477 const int test3 = ( xx > precision ) ;
5478 const int test4 = ( xx < 1.-precision ) ;
5479 if( test1 || test2 )
5480 {
5481 // si I est dans un voisinage d'un vertex
5482 I_sur_arete_vertex += 1./2. ;
5483 }
5484 else if( test3 && test4 )
5485 {
5486 // I est a l'interieur du triangle
5487 I_dans_fa7++;
5488 }
5489 }
5490 else if( dim == 3 )
5491 {
5492 DoubleTab ABvectAC(dim) ;
5493 ABvectAC(0) = (B(1)-A(1))*(C(2)-A(2))-(B(2)-A(2))*(C(1)-A(1)) ;
5494 ABvectAC(1) = (B(2)-A(2))*(C(0)-A(0))-(B(0)-A(0))*(C(2)-A(2)) ;
5495 ABvectAC(2) = (B(0)-A(0))*(C(1)-A(1))-(B(1)-A(1))*(C(0)-A(0)) ;
5496 double ABvectACscalU = ABvectAC(0)*U(0) + ABvectAC(1)*U(1) + ABvectAC(2)*U(2) ;
5497 double AireABC = ABvectACscalU / 2. ;
5498
5499 DoubleTab IBvectIC(dim) ;
5500 IBvectIC(0) = (B(1)-I(1))*(C(2)-I(2))-(B(2)-I(2))*(C(1)-I(1)) ;
5501 IBvectIC(1) = (B(2)-I(2))*(C(0)-I(0))-(B(0)-I(0))*(C(2)-I(2)) ;
5502 IBvectIC(2) = (B(0)-I(0))*(C(1)-I(1))-(B(1)-I(1))*(C(0)-I(0)) ;
5503 double IBvectICscalU = IBvectIC(0)*U(0) + IBvectIC(1)*U(1) + IBvectIC(2)*U(2) ;
5504 double AireIBC = IBvectICscalU / 2. ;
5505
5506 DoubleTab ICvectIA(dim) ;
5507 ICvectIA(0) = (C(1)-I(1))*(A(2)-I(2))-(C(2)-I(2))*(A(1)-I(1)) ;
5508 ICvectIA(1) = (C(2)-I(2))*(A(0)-I(0))-(C(0)-I(0))*(A(2)-I(2)) ;
5509 ICvectIA(2) = (C(0)-I(0))*(A(1)-I(1))-(C(1)-I(1))*(A(0)-I(0)) ;
5510 double ICvectIAscalU = ICvectIA(0)*U(0) + ICvectIA(1)*U(1) + ICvectIA(2)*U(2) ;
5511 double AireICA = ICvectIAscalU / 2. ;
5512
5513 DoubleTab IAvectIB(dim) ;
5514 IAvectIB(0) = (A(1)-I(1))*(B(2)-I(2))-(A(2)-I(2))*(B(1)-I(1)) ;
5515 IAvectIB(1) = (A(2)-I(2))*(B(0)-I(0))-(A(0)-I(0))*(B(2)-I(2)) ;
5516 IAvectIB(2) = (A(0)-I(0))*(B(1)-I(1))-(A(1)-I(1))*(B(0)-I(0)) ;
5517 double IAvectIBscalU = IAvectIB(0)*U(0) + IAvectIB(1)*U(1) + IAvectIB(2)*U(2) ;
5518 double AireIAB = IAvectIBscalU / 2. ;
5519
5520 double alpha = AireIBC/AireABC ;
5521 double beta = AireICA/AireABC ;
5522 double gamma = AireIAB/AireABC ;
5523
5524 int test1 = ( std::fabs(alpha-1.)<=precision && std::fabs(beta)<=precision && std::fabs(gamma)<=precision ) ;
5525 int test2 = ( std::fabs(beta-1.)<=precision && std::fabs(alpha)<=precision && std::fabs(gamma)<=precision ) ;
5526 int test3 = ( std::fabs(gamma-1.)<=precision && std::fabs(alpha)<=precision && std::fabs(beta)<=precision ) ;
5527 int test4 = ( std::fabs(alpha)<=precision && precision<beta && beta<1.-precision && precision<gamma && gamma<1.-precision ) ;
5528 int test5 = ( std::fabs(beta)<=precision && precision<alpha && alpha<1.-precision && precision<gamma && gamma<1.-precision ) ;
5529 int test6 = ( std::fabs(gamma)<=precision && precision<beta && beta<1.-precision && precision<alpha && alpha<1.-precision ) ;
5530 int test7 = ( precision<alpha && alpha<1.-precision) ;
5531 int test8 = ( precision<beta && beta<1.-precision) ;
5532 int test9 = ( precision<gamma && gamma<1.-precision) ;
5533
5534 if( test1 || test2 || test3 )
5535 {
5536 // si I est dans un voisinage d'un vertex
5537 // Dans ce cas, une "infinite" (nombre max de facette dans elem) de facettes peuvent etre concernee.
5538 I_sur_arete_vertex += 1e-5 ;
5539 }
5540 else if( test4 || test5 || test6 )
5541 {
5542 // si I est dans un voisinage d'une arete sans etre un vertex
5543 I_sur_arete_fa7 += 1./2. ;
5544 }
5545 else if( test7 && test8 && test9 )
5546 {
5547 // I est a l'interieur
5548 I_dans_fa7++;
5549 }
5550 }
5551 else
5552 {
5553 Cerr << " attention seules les dimension 2 et 3 sont traitees "<<finl ;
5554 Process::exit() ;
5555 }
5556 }
5557 }
5558 // Iteration des facettes de l'element
5559 index = data.index_facette_suivante_;
5560 }
5561 traverse = int(ceil(I_sur_arete_vertex)) + int(ceil(I_sur_arete_fa7)) + I_dans_fa7 ;
5562}
5563
5564// Methode listant les elements contenant un nombre de facettes superieur a
5565// nb_fa7_accepeted et l'ensemble des facettes associees.
5566void Transport_Interfaces_FT_Disc::calcul_OutElemFa7( Maillage_FT_Disc& maillage, const DoubleTab& indicatrice,
5567 const int nb_elem, int& nb_fa7_accepted,
5568 IntList& OutElem, IntList& OutFa7 )
5569{
5570 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
5571 const ArrOfInt& index_elem = intersection.index_elem() ;
5572 // Calcul de la surface des facettes contenues dans i_elem
5573 const ArrOfDouble& surfaces = maillage.get_update_surface_facettes();
5574
5575 // Parcourt de l'ensemble des elements reels
5576 for (int i_elem = 0; i_elem < nb_elem ; i_elem++)
5577 {
5578 // Test si l'element est traverse par une IBC
5579 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. )
5580 {
5581 int index = index_elem[i_elem] ;
5582 // Listes contenant la surface des facettes et le numero de la facette
5583 // Les 'nb_fa7_accepted' facettes de plus grande surface sont
5584 // considerees ici comme etant les plus representatives.
5585 DoubleList E ;
5586 IntList F ;
5587
5588 // Parcours des facettes traversant l'element i_elem
5589 while (index >= 0 )
5590 {
5591 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
5592 const int i_facette = data.numero_facette_;
5593
5594 // Stokage de la surface de la facette i_facette dans la liste E
5595 E.add(surfaces[i_facette]) ;
5596 // Stokage du numero de la facette dans la liste F
5597 F.add(i_facette) ;
5598 index = data.index_facette_suivante_;
5599 }
5600
5601 // Si le nombre de facette est superieur a nb_fa7_accepted
5602 // alors on choisit les facettes les plus representatives.
5603 // Ici, representative := de plus grande surface
5604 if( F.size() > nb_fa7_accepted )
5605 {
5606 // Stockage de l'element i_elem dans la liste OutElem
5607 OutElem.add_if_not( i_elem ) ;
5608 // Liste des facettes stockees dans i_elem
5609 IntList Fa7Elem ;
5610
5611 // Listing des facettes de plus grande surface
5612 int i = 0 ;
5613 while( i<nb_fa7_accepted )
5614 {
5615 // Recherche de la surface max
5616 double max_data = -1e30 ;
5617 int l=0 ;
5618 int ll = 0 ;
5619 while( l<E.size() )
5620 {
5621 if( E[l]>max_data && !Fa7Elem.contient(F[l]) )
5622 {
5623 max_data = E[l] ;
5624 ll = l ;
5625 }
5626 l++ ;
5627 }
5628 // Ajout de la facette de plus grande surface dans
5629 // la liste OutFa7
5630 Fa7Elem.add( F[ll] ) ;
5631 OutFa7.add( F[ll] ) ;
5632 i++ ;
5633 }
5634 }
5635 }
5636 }
5637}
5638
5639// Calcul du vertex le plus proche pour les faces diphasiques ( etape 1 )
5640void Transport_Interfaces_FT_Disc::PPP_face_interface( Maillage_FT_Disc& maillage, const DoubleTab& indicatrice,
5641 const DoubleTab& indicatrice_face, DoubleTab& Vertex )
5642
5643{
5644 const int dim = Objet_U::dimension;
5645 const Domaine_dis_base& mon_dom_dis = domaine_dis();
5646 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
5647 const IntTab& faces_elem = domaine_vf.face_voisins();
5648 const int nb_elem = domaine_vf.nb_elem() ;
5649 const int nfaces = faces_elem.dimension(0) ;
5650 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
5651 const ArrOfInt& index_elem = intersection.index_elem() ;
5652 const IntTab& facettes = maillage.facettes() ;
5653 const DoubleTabFT& sommets = maillage.sommets() ;
5654 const DoubleTab& xv = domaine_vf.xv();
5655 DoubleTab coord(dim) ;
5656 coord = 0. ;
5657
5658 for( int i_face=0 ; i_face<nfaces ; i_face++ )
5659 {
5660 // Distance face facette
5661 double dist_fa7 = 1e+30 ;
5662 int ppp_calcule = 0 ;
5663
5664 // Parcourt des faces diphasiques
5665 if( indicatrice_face(i_face) == 0.5 )
5666 {
5667 int voisin = -1 ;
5668 if( faces_elem(i_face,0) > -1 )
5669 voisin = faces_elem(i_face,0) ;
5670 else
5671 voisin = faces_elem(i_face,1) ;
5672
5673 // Dans ce cas, i_face coincide avec les facettes
5674 // Le point le plus proche est lui-meme
5675 if( indicatrice(voisin) == 0. || indicatrice(voisin) == 1. )
5676 {
5677 for( int j=0; j<dim; j++)
5678 {
5679 Vertex(i_face,j) = xv(i_face,j) ;
5680 }
5681 ppp_calcule = 1 ;
5682 }
5683 }
5684
5685 if (indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. && ppp_calcule == 0 )
5686 {
5687 // Parcourt des elements voisins traverses physiques
5688 for(int i=0 ; i<2; i++)
5689 {
5690 const int elem_voisin = faces_elem(i_face,i) ;
5691
5692 if( elem_voisin<nb_elem && elem_voisin>-1 && indicatrice(elem_voisin) != 0. && indicatrice(elem_voisin) != 1. )
5693 {
5694 int index = index_elem[elem_voisin] ;
5695 // Parcourt des facettes de l'element
5696 while (index >= 0 )
5697 {
5698 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
5699 const int i_facette = data.numero_facette_;
5700 // Distance min par elements
5701 double dist_min = 1e+30 ;
5702 // Parcourt des sommets des facettes
5703 for( int som=0; som<facettes.dimension(1); som++)
5704 {
5705 // Distance face sommet
5706 double dist_som = 0. ;
5707 for( int j=0; j<dim; j++)
5708 {
5709 // j-ieme coordonnees du sommets som
5710 double sj = sommets(facettes(i_facette, som), j) ;
5711 // j-ieme coordonnees du barycentre de la face
5712 double xj = xv(i_face, j) ;
5713 // Carre de la distance face sommet som
5714 dist_som += (xj - sj)*(xj - sj) ;
5715 }
5716 // Distance face sommet som
5717 dist_som = sqrt(dist_som) ;
5718
5719 // Distance face facette par rapport a distance face sommet de facette
5720 if( dist_som < dist_min )
5721 {
5722 dist_min = dist_som ;
5723 for( int j=0; j<dim; j++)
5724 {
5725 coord(j) = sommets(facettes(i_facette, som), j) ;
5726 }
5727 }
5728 }
5729 // Distance face sommet minimale par rapport a distance face facette
5730 if( dist_min < dist_fa7 )
5731 {
5732 dist_fa7 = dist_min ;
5733 for( int j=0; j<dim; j++)
5734 {
5735 Vertex(i_face,j) = coord(j) ;
5736 }
5737 }
5738 // Ieration des facettes de l'element
5739 index = data.index_facette_suivante_;
5740 }
5741 }
5742 }
5743 }
5744 }
5745}
5746
5747// Calcul du vertex le plus proche des faces diphasiques (etape 2)
5748void Transport_Interfaces_FT_Disc::PPP_face_interface_voisin( const DoubleTab& indicatrice, const DoubleTab& indicatrice_face,
5749 DoubleTab& Vertex, DoubleTab& PPP )
5750
5751{
5752 const int dim = Objet_U::dimension;
5753 const Domaine_dis_base& mon_dom_dis = domaine_dis();
5754 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
5755 const IntTab& faces_elem = domaine_vf.face_voisins();
5756 const IntTab& elem_faces = domaine_vf.elem_faces();
5757 const int nfaces = faces_elem.dimension(0) ;
5758 const DoubleTab& xv = domaine_vf.xv();
5759
5760 for( int i_face=0 ; i_face<nfaces ; i_face++ )
5761 {
5762 double d = 0. ;
5763 double dmin = 0. ;
5764 int ppp_calcule = 0 ;
5765
5766 // Parcourt des faces diphasiques
5767 if( indicatrice_face(i_face) == 0.5 )
5768 {
5769 int voisin = -1 ;
5770 if( faces_elem(i_face,0) > -1 )
5771 voisin = faces_elem(i_face,0) ;
5772 else
5773 voisin = faces_elem(i_face,1) ;
5774
5775 // Dans ce cas, i_face coincide avec les facettes
5776 // Le point le plus proche est lui-meme
5777 // On ne modifie pas Vertex
5778 if( indicatrice(voisin) == 0. || indicatrice(voisin) == 1. )
5779 {
5780 for( int j=0; j<dim; j++)
5781 {
5782 PPP(i_face,j) = xv(i_face,j) ;
5783 }
5784 ppp_calcule = 1 ;
5785 }
5786 }
5787
5788 if (indicatrice_face(i_face) != 0. && indicatrice_face(i_face) != 1. && ppp_calcule == 0 )
5789 {
5790 for( int i=0 ; i<dim ; i++)
5791 {
5792 d += (Vertex(i_face,i)-xv(i_face,i))*(Vertex(i_face,i)-xv(i_face,i)) ;
5793 }
5794 d = sqrt(d) ;
5795 dmin = d ;
5796 for( int k=0 ; k<dim ; k++)
5797 {
5798 PPP(i_face,k) = Vertex(i_face,k) ;
5799 }
5800 // On parcourt les autres faces de mes deux voisins
5801 // On compare le PPP de i_face avec ceux des autres faces.
5802 // Parmi eux, on choisit le plus proche de i_face.
5803 for( int i=0; i<2; i++ )
5804 {
5805 const int elem = faces_elem(i_face,i) ;
5806 // Si cet element voisin existe
5807 if( elem >-1 )
5808 {
5809 // alors on parcourt ses autres faces
5810 for (int face_loc=0 ; face_loc<2*dim ; face_loc++)
5811 {
5812 const int autre_face = elem_faces(elem,face_loc) ;
5813 if (indicatrice_face(autre_face) != 0. && (indicatrice_face(autre_face) != 1.
5814 || (indicatrice_face(autre_face) == 1. && d<0.))) //YG: si indicatrice modifiee
5815 {
5816 double dd = 0. ;
5817 for( int j=0 ; j<dim ; j++)
5818 {
5819 dd += (Vertex(autre_face,j)-xv(i_face,j))*(Vertex(autre_face,j)-xv(i_face,j)) ;
5820 }
5821 dd = sqrt(dd) ;
5822 if( dd <= dmin )
5823 {
5824 dmin = dd ;
5825 for( int k=0 ; k<dim ; k++)
5826 {
5827 PPP(i_face,k) = Vertex(autre_face,k) ;
5828 }
5829 }
5830 }
5831 }
5832 }
5833 }
5834 }
5835 }
5836}
5837
5838// Calcul du vertex le plus proche des faces fluides
5839void Transport_Interfaces_FT_Disc::PPP_face_voisin( const DoubleTab& indicatrice, const DoubleTab& indicatrice_face, DoubleTab& PPP )
5840
5841{
5842 const int dim = Objet_U::dimension;
5843 const Domaine_dis_base& mon_dom_dis = domaine_dis();
5844 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
5845 const IntTab& faces_elem = domaine_vf.face_voisins();
5846 const IntTab& elem_faces = domaine_vf.elem_faces();
5847 const int nfaces = faces_elem.dimension(0) ;
5848 const DoubleTab& xv = domaine_vf.xv();
5849
5850 for( int i_face=0 ; i_face<nfaces ; i_face++ )
5851 {
5852 // Distance min entre la face et sommet le plus proche
5853 double dmin = 1.e30 ;
5854
5855 if (indicatrice_face(i_face) == 0. || indicatrice_face(i_face) == 1.)
5856 {
5857 // On parcourt les autres faces de mes deux voisins
5858 // On compare le PPP de i_face avec ceux des autres faces.
5859 // Parmi eux, on choisit le plus proche de i_face.
5860 for( int ii=0; ii<2; ii++ )
5861 {
5862 const int elem = faces_elem(i_face,ii) ;
5863 // Si cet element voisin existe
5864 if( elem >-1 )
5865 {
5866 // alors on parcourt ses autres faces
5867 for (int face_loc=0 ; face_loc<2*dim ; face_loc++)
5868 {
5869 const int face = elem_faces(elem,face_loc) ;
5870
5871 if (indicatrice_face(face) != 0. && indicatrice_face(face) != 1.)
5872 {
5873 // on identifie les elements auxquels appartient autre_face
5874 for(int i=0 ; i<2; i++)
5875 {
5876 const int elem_voisin = faces_elem(face,i) ;
5877
5878 // On veut que l'element existe, qu'il soit lui-meme
5879 // traverse par une interface
5880 if( elem_voisin>-1 && indicatrice(elem_voisin) != 0. && indicatrice(elem_voisin) != 1. )
5881 {
5882 // alors on parcourt ses autres faces
5883 for (int autre_face_loc=0 ; autre_face_loc<2*dim ; autre_face_loc++)
5884 {
5885 const int autre_face = elem_faces(elem_voisin,autre_face_loc) ;
5886 double dd = 0. ;
5887 for( int j=0 ; j<dim ; j++)
5888 {
5889 dd += (PPP(autre_face,j)-xv(i_face,j))*(PPP(autre_face,j)-xv(i_face,j)) ;
5890 }
5891 dd = sqrt(dd) ;
5892 if( dd <= dmin )
5893 {
5894 dmin = dd ;
5895 for( int k=0 ; k<dim ; k++)
5896 {
5897 PPP(i_face,k) = PPP(autre_face,k) ;
5898 }
5899 }
5900 }
5901 }
5902 }
5903 }
5904 }
5905 }
5906 }
5907 }
5908 }
5909}
5910
5911// Calcul du nombre max de facettes du maillage Lagrangien par element.
5913 const DoubleTab& indicatrice,
5914 const int nb_elem, int& max_fa7,
5915 const int exec_planfa7existant)
5916{
5917 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
5918 const ArrOfInt& index_elem = intersection.index_elem() ;
5919 max_fa7 = -1 ;
5920
5921 // Parcourt des elements reels
5922 for (int i_elem = 0; i_elem < nb_elem ; i_elem++)
5923 {
5924 // Test si l'element est traverse par une IBC
5925 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. )
5926 {
5927 int index = index_elem[i_elem] ;
5928 int cpt = 0 ;
5929 // Liste des parametres du plan de la facette i_facette
5930 DoubleList A, B, C, D ;
5931
5932 // Pour un element, on parcourt les facettes qui le traversent
5933 while (index >= 0 )
5934 {
5935 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
5936 const int i_facette = data.numero_facette_;
5937
5938 int test_liste = 0 ; // test_liste vaut 1 si le plan de i_facette existe
5939 // Calcul des parametres du plan de la facette
5940 // (sauf pour la premiere car les listes sont vides )
5941 if( !(A.est_vide()) && exec_planfa7existant == 1 )
5942 plan_facette_existant( maillage, A, B, C, D, i_facette, test_liste ) ;
5943
5944 // Test si i_facette est la premiere facette parcourue
5945 // ou si le plan qui la traverse n'existe pas encore
5946 if( test_liste==0 )
5947 {
5948 if( exec_planfa7existant == 1 )
5949 {
5950 double aa=0., bb=0., cc=0., dd=0. ;
5951 calcul_eq_plan_facette( i_facette, aa, bb, cc, dd ) ;
5952 // Stokage des parametres du plan de la facette.
5953 // Listes utilisees dans plan_facette_existant
5954 A.add(aa) ;
5955 B.add(bb) ;
5956 C.add(cc) ;
5957 D.add(dd) ;
5958 }
5959 cpt++ ;
5960 }
5961
5962 index = data.index_facette_suivante_;
5963 }
5964 // Calcul du nombre max de facettes retenues par element
5965 if( cpt > max_fa7 )
5966 max_fa7 = cpt ;
5967 }
5968 }
5969}
5970
5971// Renumerotation des facettes virtuelles
5972void Transport_Interfaces_FT_Disc::RenumFa7( DoubleTab& Barycentre, DoubleTab& Tab110,
5973 DoubleTab& Tab111, DoubleTab& Tab112,
5974 IntTab& Tab12, IntTab& CptFacette,
5975 const int nb_facettes,
5976 const int nb_facettes_dim )
5977{
5978 //double eps = 1e-20 ;
5979 const double eps = Objet_U::precision_geom ;
5980
5981 int nn = Tab110.dimension(0) ;
5982 int nn_tot = Tab110.dimension_tot(0) ;
5983 for (int i_elem = nn; i_elem < nn_tot ; i_elem++)
5984 {
5985
5986 for( int cpt=0 ; cpt < CptFacette(i_elem) ; cpt++ )
5987 {
5988 int bary_trouve = 0 ;
5989 int ii = 0 ;
5990 while( ii < nb_facettes && bary_trouve==0 )
5991 {
5992 bool test_0 = (Barycentre(ii,0)-Tab110(i_elem,cpt))*(Barycentre(ii,0)-Tab110(i_elem,cpt))<eps ;
5993 bool test_1 = (Barycentre(ii,1)-Tab111(i_elem,cpt))*(Barycentre(ii,1)-Tab111(i_elem,cpt))<eps ;
5994 bool test_2 = (Barycentre(ii,2)-Tab112(i_elem,cpt))*(Barycentre(ii,2)-Tab112(i_elem,cpt))<eps ;
5995
5996 if( test_0 && test_1 && test_2 )
5997 {
5998 bary_trouve = 1 ;
5999 Tab12( i_elem, cpt ) = ii ;
6000 }
6001 ii++ ;
6002 }
6003 if( bary_trouve==0 && ii==nb_facettes )
6004 {
6005
6006 // On renumerote localement ssi le numero de la facette virtuelle
6007 // existe dans la numerotation des facettes reelles.
6008 if( Tab12( i_elem, cpt ) < nb_facettes )
6009 Tab12( i_elem, cpt )+=nb_facettes_dim ;
6010 }
6011 }
6012 }
6013}
6014
6016 IntTab& CptFacette, DoubleTab& Tab100,
6017 DoubleTab& Tab101, DoubleTab& Tab102,
6018 DoubleTab& Tab103, DoubleTab& Tab110,
6019 DoubleTab& Tab111, DoubleTab& Tab112,
6020 IntTab& Tab12, DoubleTab& Barycentre,
6021 const DoubleTab& indicatrice,
6022 IntList& OutElem, ArrOfBit& fa7,
6023 const int exec_planfa7existant )
6024{
6025 const Intersections_Elem_Facettes& intersection = maillage.intersections_elem_facettes();
6026 const ArrOfInt& index_elem = intersection.index_elem() ;
6027 int nn = Tab100.dimension(0) ;
6028 int nn_tot = Tab100.dimension_tot(0) ;
6029
6030 // Matrice de booleen evitant de calculer deux fois le meme barycentre
6031 fa7=0;
6032 for (int i_elem = 0; i_elem < nn ; i_elem++)
6033 {
6034 if( indicatrice(i_elem) != 0. && indicatrice(i_elem) != 1. && !OutElem.contient(i_elem) )
6035 {
6036
6037 int index = index_elem[i_elem] ;
6038 CptFacette(i_elem) = 0 ;
6039 int cpt = 0 ;
6040 // Les listes sont vides pour la premieres facettes de chaque element
6041 DoubleList A, B, C, D ;
6042 while (index >= 0 )
6043 {
6044 const Intersections_Elem_Facettes_Data& data = intersection.data_intersection(index);
6045 const int i_facette = data.numero_facette_;
6046
6047
6048 int test_liste = 0 ; // si test_liste=1 le plan de i_facette existe
6049 if( !(A.est_vide()) && exec_planfa7existant == 1 )
6050 plan_facette_existant( maillage, A, B, C, D, i_facette, test_liste ) ;
6051
6052 // Test si i_facette est la premiere facette parcourue
6053 // ou si le plan qui la traverse n'existe pas encore
6054 if( test_liste==0 )
6055 {
6056 // Calcul des parametres du plan de la facette
6057 calcul_eq_plan_facette(maillage,i_facette,Tab100(i_elem,cpt),Tab101(i_elem,cpt),
6058 Tab102(i_elem,cpt),Tab103(i_elem,cpt)) ;
6059 if( exec_planfa7existant == 1 )
6060 {
6061 A.add(Tab100(i_elem,cpt)) ;
6062 B.add(Tab101(i_elem,cpt)) ;
6063 C.add(Tab102(i_elem,cpt)) ;
6064 D.add(Tab103(i_elem,cpt)) ;
6065 }
6066 Tab12(i_elem,cpt) = i_facette ;
6067
6068 // Calcul de l'octree de la facette ( seulement en parallele )
6069 if( nn < nn_tot )
6070 {
6071 // Calcul des coordonnees barycentriques de i_facette
6072 if( !fa7.testsetbit(i_facette) )
6073 {
6074 BaryFa7(maillage,i_facette,Barycentre) ;
6075 }
6076 // Stokage des coordonnees barycentriques de i_facette
6077 Tab110(i_elem,cpt) = Barycentre(i_facette,0) ;
6078 Tab111(i_elem,cpt) = Barycentre(i_facette,1) ;
6079 Tab112(i_elem,cpt) = Barycentre(i_facette,2) ;
6080 }
6081 cpt++ ;
6082 }
6083 index = data.index_facette_suivante_;
6084 }
6085 // Nombre de facettes dans l'element
6086 CptFacette(i_elem) = cpt ;
6087 if( cpt > Tab12.line_size() )
6088 {
6089 Cerr<<"Attention, seulement "<< cpt << " facettes ont ete stokees "<< finl ;
6090 Cerr<<"dans l'element "<< i_elem << " qui en contient plus."<< finl ;
6091 Cerr<<"Regarder la finesse du maillage Lagrangien par rapport au maillage Eulerien" <<finl ;
6092 Process::exit() ;
6093 }
6094 }
6095 }
6096}
6097
6099 DoubleTab& Tab101, DoubleTab& Tab102, DoubleTab& Tab103,
6100 DoubleTab& Tab110,DoubleTab& Tab111, DoubleTab& Tab112,
6101 IntTab& Tab12, DoubleTab& Barycentre, IntList& OutElem,
6102 IntTab& TabOutFa7, ArrOfBit& fa7 )
6103{
6104 int cpt_elem = 0 ;
6105 int nn = Tab100.dimension(0) ;
6106 int nn_tot = Tab100.dimension_tot(0) ;
6107 while( cpt_elem < OutElem.size() )
6108 {
6109 for( int k=0 ; k<TabOutFa7.line_size() ; k++ )
6110 {
6111 const int i_facette = TabOutFa7(cpt_elem,k) ;
6112 calcul_eq_plan_facette(maillage,i_facette,Tab100( OutElem[cpt_elem],k),
6113 Tab101(OutElem[cpt_elem],k),Tab102(OutElem[cpt_elem],k),
6114 Tab103(OutElem[cpt_elem],k)) ;
6115 Tab12(OutElem[cpt_elem],k) = i_facette ;
6116
6117 // Calcul de l'octree de la facette ( seulement en parallele )
6118 if( nn < nn_tot )
6119 {
6120 // Calcul des coordonnees barycentriques de i_facette
6121 if( !fa7.testsetbit(i_facette) )
6122 {
6123 BaryFa7(maillage,i_facette,Barycentre) ;
6124 }
6125 // Stokage des coordonnees barycentriques de i_facette
6126 Tab110(OutElem[cpt_elem],k) = Barycentre(i_facette,0) ;
6127 Tab111(OutElem[cpt_elem],k) = Barycentre(i_facette,1) ;
6128 Tab112(OutElem[cpt_elem],k) = Barycentre(i_facette,2) ;
6129 }
6130 }
6131 cpt_elem++ ;
6132 }
6133}
6134
6135// Calcul des coordonees barycentriques des facettes
6136void Transport_Interfaces_FT_Disc::BaryFa7( Maillage_FT_Disc& maillage, const int i_facette, DoubleTab& Bary )
6137{
6138 const DoubleTabFT& sommets = maillage.sommets() ;
6139 const IntTab& facettes = maillage.facettes() ;
6140 const int dim = Objet_U::dimension ;
6141 IntTab Som( facettes.line_size() ) ;
6142 DoubleTab CoordSom( facettes.line_size(), dim ) ;
6143
6144 // Calcul des coordonnees de chaque sommets
6145 for ( int i=0 ; i<facettes.line_size() ; i ++ )
6146 {
6147 Bary(i_facette,i) = 0. ;
6148 Som(i) = facettes(i_facette, i) ;
6149 for ( int j = 0 ; j < dim ; j++ )
6150 {
6151 CoordSom(i,j) = sommets(Som(i),j) ;
6152 }
6153 }
6154 // Calcul des coordonees barycentriques
6155 for ( int k = 0 ; k< dim ; k++ )
6156 {
6157 for( int l = 0 ; l< facettes.line_size() ; l++ )
6158 {
6159 Bary(i_facette,k) += CoordSom(l,k) / double(facettes.line_size()) ;
6160 }
6161 }
6162 if( dim == 2 )
6163 Bary(i_facette,2) = 0. ;
6164}
6165
6166// Methode determinant si le plan passant par la facette i_facette existe
6168 DoubleList B,DoubleList C,DoubleList D,
6169 const int i_facette,int& test_liste )
6170{
6171 assert( A.size() == B.size() ) ;
6172 assert( A.size() == C.size() ) ;
6173 assert( A.size() == D.size() ) ;
6174 const DoubleTabFT& sommets = maillage.sommets() ;
6175 const IntTab& facettes = maillage.facettes() ;
6176 double x1, y1, z1 = 0. ;
6177 double x2, y2, z2 = 0. ;
6178 double x3 = 0., y3 = 0., z3 = 0. ;
6179 double plan3 = 0. ;
6180 const int s1 = facettes(i_facette, 0) ;
6181 x1 = sommets(s1,0) ;
6182 y1 = sommets(s1,1) ;
6183 const int s2 = facettes(i_facette, 1) ;
6184 x2 = sommets(s2,0) ;
6185 y2 = sommets(s2,1) ;
6186 double eps = 1e-20 ;
6187
6188 // const double eps = Objet_U::precision_geom ;
6189
6190 if (Objet_U::dimension == 3)
6191 {
6192 z1 = sommets(s1,2) ;
6193 z2 = sommets(s2,2) ;
6194 const int s3 = facettes(i_facette, 2) ;
6195 x3 = sommets(s3,0) ;
6196 y3 = sommets(s3,1) ;
6197 z3 = sommets(s3,2) ;
6198 }
6199
6200 int i=0 ;
6201 while( i< A.size() && test_liste==0 )
6202 {
6203 double plan1 = D[i] + A[i] * x1 + B[i] * y1 + C[i] * z1 ;
6204 double plan2 = D[i] + A[i] * x2 + B[i] * y2 + C[i] * z2 ;
6205 if(Objet_U::dimension == 3)
6206 plan3 = D[i] + A[i] * x3 + B[i] * y3 + C[i] * z3 ;
6207
6208
6209 if( std::fabs(plan1)<eps && std::fabs(plan2)<eps && std::fabs(plan3)<eps )
6210 test_liste= 1 ;
6211 i++ ;
6212 }
6213}
6214
6215// Calcul des parametres du plan de la facette. Utile pour l'algorithme d'Uzawa.
6217 double& a,double& b,double& c,double& d )
6218{
6219 const DoubleTabFT& normale_facettes = maillage.get_update_normale_facettes() ;
6220 const DoubleTabFT& sommets = maillage.sommets() ;
6221 const IntTab& facettes = maillage.facettes() ;
6222
6223 c = 0. ;
6224 double x, y, z = 0. ;
6225 double inverse_norme = 0. ;
6226
6227 const int s1 = facettes(i_facette, 0) ;
6228
6229 a = normale_facettes(i_facette, 0) ;
6230 b = normale_facettes(i_facette, 1) ;
6231 x = sommets(s1,0) ;
6232 y = sommets(s1,1) ;
6233
6234 if (Objet_U::dimension == 3)
6235 {
6236 c = normale_facettes(i_facette, 2) ;
6237 z = sommets(s1,2) ;
6238 }
6239 inverse_norme = 1. / sqrt( a*a + b*b + c*c ) ;
6240
6241 a *= inverse_norme ;
6242 b *= inverse_norme ;
6243 c *= inverse_norme ;
6244 d = - (a * x + b * y + c * z) ;
6245}
6246
6247// Calcul des parametres du plan de la facette. Utile pour l'algorithme d'Uzawa.
6249 double& b,double& c,double& d )
6250{
6251 Maillage_FT_Disc& maillage = maillage_interface() ;
6252 const DoubleTabFT& normale_facettes = maillage.get_update_normale_facettes() ;
6253 const DoubleTabFT& sommets = maillage.sommets() ;
6254 const IntTab& facettes = maillage.facettes() ;
6255
6256 c = 0. ;
6257 double x, y, z = 0. ;
6258 double inverse_norme = 0. ;
6259
6260 const int s1 = facettes(i_facette, 0) ;
6261
6262 a = normale_facettes(i_facette, 0) ;
6263 b = normale_facettes(i_facette, 1) ;
6264 x = sommets(s1,0) ;
6265 y = sommets(s1,1) ;
6266
6267 if (Objet_U::dimension == 3)
6268 {
6269 c = normale_facettes(i_facette, 2) ;
6270 z = sommets(s1,2) ;
6271 }
6272 inverse_norme = 1. / sqrt( a*a + b*b + c*c ) ;
6273
6274 a *= inverse_norme ;
6275 b *= inverse_norme ;
6276 c *= inverse_norme ;
6277 d = - (a * x + b * y + c * z) ;
6278}
6279
6280void Transport_Interfaces_FT_Disc::calcul_tolerance_projete_diphasique( const int i_face, const int ori, const int voisin0,
6281 const int voisin1, const DoubleTab& indicatrice, double& tol )
6282{
6283 const int dim = Objet_U::dimension;
6284 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6285 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
6286 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis) ;
6287 const IntTab& elem_faces = domaine_vf.elem_faces();
6288 int voisin = 0 ;
6289 DoubleTab L(dim) ;
6290 L = 0. ;
6291 tol = 0. ;
6292 if( voisin0 > -1 && indicatrice(voisin0) != 0. && indicatrice(voisin0) != 1. )
6293 {
6294 voisin = voisin0 ;
6295 const int face_voisine = elem_faces(voisin0,ori) + elem_faces(voisin0,ori+dim) - i_face ;
6296 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6297 }
6298 if( voisin1 > -1 && indicatrice(voisin1) != 0. && indicatrice(voisin1) != 1. )
6299 {
6300 voisin = voisin1 ;
6301 const int face_voisine = elem_faces(voisin1,ori) + elem_faces(voisin1,ori+dim) - i_face ;
6302 double xx = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6303 L(ori) = std::max( L(ori), xx ) ;
6304 }
6305
6306 for( int k = 0 ; k<dim ; k++ )
6307 {
6308 if( k != ori )
6309 {
6310 const int face0 = elem_faces(voisin,k) ;
6311 const int face1 = elem_faces(voisin,k+dim) ;
6312 L(k) = std::fabs(domaine_vdf.distance_face(face0,face1,k))/2. ;
6313 }
6314 }
6315 for( int k = 0 ; k<dim ; k++ )
6316 {
6317 tol += L(k)*L(k) ;
6318 }
6319 tol = sqrt(tol) ;
6320}
6321
6322void Transport_Interfaces_FT_Disc::calcul_tolerance_projete_monophasique( const int i_face, const int ori, const int voisin0,
6323 const int voisin1, const DoubleTab& indicatrice_face,
6324 const DoubleTab& indicatrice, double& tol )
6325{
6326 const int dim = Objet_U::dimension ;
6327 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6328 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis) ;
6329 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis) ;
6330 const IntVect& orientation = domaine_vdf.orientation() ;
6331 const IntTab& elem_faces = domaine_vf.elem_faces() ;
6332 const IntTab& faces_elem = domaine_vf.face_voisins() ;
6333
6334 //------------------------------------------------------------------------------------------------
6335 //------------------------------------------------------------------------------------------------
6336 //------------------------------------------------------------------------------------------------
6337 // cas longitudinal
6338 DoubleTab L(dim) ;
6339 L = 0. ;
6340 double tol0 = 0. ;
6341 if( voisin0 > -1 )
6342 {
6343 const int face_voisine = elem_faces(voisin0,ori) + elem_faces(voisin0,ori+dim) - i_face ;
6344 if( indicatrice_face(face_voisine) != 0. && indicatrice_face(face_voisine) != 1. )
6345 {
6346 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6347
6348 const int voisin_voisin = faces_elem(face_voisine,0) + faces_elem(face_voisine,1) - voisin0 ;
6349 if( voisin_voisin > -1 )
6350 {
6351 const int face_voisine_voisine = elem_faces(voisin_voisin,ori) + elem_faces(voisin_voisin,ori+dim) - face_voisine ;
6352 L(ori) += std::fabs(domaine_vdf.distance_face(face_voisine,face_voisine_voisine,ori)) ;
6353 }
6354 for( int k = 0 ; k<dim ; k++ )
6355 {
6356 if( k != ori )
6357 {
6358 const int face0 = elem_faces(voisin0,k) ;
6359 const int face1 = elem_faces(voisin0,k+dim) ;
6360 L(k) = std::fabs(domaine_vdf.distance_face(face0,face1,k))/2. ;
6361 }
6362 }
6363 for( int k = 0 ; k<dim ; k++ )
6364 {
6365 tol0 += L(k)*L(k) ;
6366 }
6367 tol0 = sqrt(tol0) ;
6368 }
6369 }
6370 double tol1 = 0. ;
6371 L = 0. ;
6372 if( voisin1 > -1 )
6373 {
6374 const int face_voisine = elem_faces(voisin1,ori) + elem_faces(voisin1,ori+dim) -i_face ;
6375 if( indicatrice_face(face_voisine) != 0. && indicatrice_face(face_voisine) != 1. )
6376 {
6377 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6378
6379 const int voisin_voisin = faces_elem(face_voisine,0) + faces_elem(face_voisine,1) - voisin1 ;
6380 if( voisin_voisin > -1 )
6381 {
6382 const int face_voisine_voisine = elem_faces(voisin_voisin,ori) + elem_faces(voisin_voisin,ori+dim) - face_voisine ;
6383 L(ori) += std::fabs(domaine_vdf.distance_face(face_voisine,face_voisine_voisine,ori)) ;
6384 }
6385 for( int k = 0 ; k<dim ; k++ )
6386 {
6387 if( k != ori )
6388 {
6389 const int face0 = elem_faces(voisin1,k) ;
6390 const int face1 = elem_faces(voisin1,k+dim) ;
6391 L(k) = std::fabs(domaine_vdf.distance_face(face0,face1,k))/2. ;
6392 }
6393 }
6394 for( int k = 0 ; k<dim ; k++ )
6395 {
6396 tol1 += L(k)*L(k) ;
6397 }
6398 tol1 = sqrt(tol1) ;
6399 }
6400 }
6401 double tol_long = std::max(tol0,tol1) ;
6402
6403
6404 //------------------------------------------------------------------------------------------------
6405 //------------------------------------------------------------------------------------------------
6406 //------------------------------------------------------------------------------------------------
6407 // cas transverse
6408 L = 0. ;
6409 int voisin = 1 ;
6410 if( voisin0 > -1 )
6411 {
6412 voisin = voisin0 ;
6413 const int face_voisine = elem_faces(voisin0,ori) + elem_faces(voisin0,ori+dim) - i_face ;
6414 L(ori) = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6415 }
6416 if( voisin1 > -1 )
6417 {
6418 voisin = voisin1 ;
6419 const int face_voisine = elem_faces(voisin1,ori) + elem_faces(voisin1,ori+dim) - i_face ;
6420 double xx = std::fabs(domaine_vdf.distance_face(i_face,face_voisine,ori)) ;
6421 L(ori) = std::max( L(ori), xx ) ;
6422 }
6423
6424 DoubleTab xx_max(dim) ;
6425 xx_max = 0. ;
6426 for (int i=0 ; i<2*dim ; i++)
6427 {
6428 const int autre_face = elem_faces(voisin,i) ;
6429 const int face_voisine = elem_faces(voisin,ori) + elem_faces(voisin,ori+dim) - i_face ;
6430
6431 if( autre_face != i_face && autre_face != face_voisine
6432 && indicatrice_face(autre_face) != 0. && indicatrice_face(autre_face) != 1. )
6433 {
6434 const int voisin_voisin = faces_elem(autre_face,0) + faces_elem(autre_face,1) - voisin ;
6435 const int ori_face = orientation[autre_face] ;
6436 const int autre_face_voisine = elem_faces(voisin_voisin,ori_face) + elem_faces(voisin_voisin,ori_face+dim) - autre_face ;
6437 double xx = std::fabs(domaine_vdf.distance_face(autre_face,autre_face_voisine,ori_face)) ;
6438 if( xx_max(ori_face) < xx )
6439 xx_max(ori_face) = xx ;
6440 }
6441 }
6442
6443 DoubleTab TOL_TMP(dim-1) ;
6444 TOL_TMP = 0. ;
6445 int cpt = 0 ;
6446 for(int k=0 ; k<dim ; k++)
6447 {
6448 if( k != ori )
6449 {
6450 for(int l=0 ; l<dim ; l++)
6451 {
6452 if( l != k && l != ori )
6453 {
6454 const int face0 = elem_faces(voisin,k) ;
6455 const int face1 = elem_faces(voisin,k+dim) ;
6456 double yy = 0.5*std::fabs(domaine_vdf.distance_face(face0,face1,k)) ;
6457 double a = 0.5*yy + xx_max(k) ;
6458 const int face3 = elem_faces(voisin,l) ;
6459 const int face4 = elem_faces(voisin,l+dim) ;
6460 double b = 0.5*std::fabs(domaine_vdf.distance_face(face3,face4,l)) ;
6461 TOL_TMP(cpt) = L(ori)*L(ori) + a*a + b*b ;
6462 cpt++ ;
6463 }
6464 }
6465 }
6466 }
6467 double tol_trans = TOL_TMP(0) ;
6468 if( dim == 3 )
6469 tol_trans = std::max(tol_trans,TOL_TMP(1)) ;
6470 tol_trans = sqrt( tol_trans ) ;
6471 //------------------------------------------------------------------------------------------------
6472 //------------------------------------------------------------------------------------------------
6473 //------------------------------------------------------------------------------------------------
6474 tol = std::max(tol_long,tol_trans) ;
6475}
6476
6477// Verification du projete
6478void Transport_Interfaces_FT_Disc::verifprojete( const int monophasique,const double Lref, double d, const DoubleTab& x,
6479 const DoubleTab& V, DoubleTab& coord_projete, int& cpt )
6480{
6481 const int dim = coord_projete.dimension(0) ;
6482 const double dist_IBC = std::fabs(d) ;
6483 const double precision = Objet_U::precision_geom ;
6484 double dist_proj = 0. ;
6485 int projete_modifie = 0 ;
6486 cpt = 0 ;
6487
6488 DoubleTab coord_projete_old(dim) ;
6489 coord_projete_old = coord_projete ;
6490
6491 for (int j = 0; j < dim ; j++)
6492 {
6493 dist_proj += (x(j) - coord_projete(j))*(x(j) - coord_projete(j)) ;
6494 }
6495 dist_proj = sqrt( dist_proj ) ;
6496 double dist_proj_old = dist_proj ;
6497
6498 const double facsec = 0.5 ;
6499 const int test0 = ( dist_proj < precision ) ;
6500 const int test1 = ( std::fabs( dist_IBC - dist_proj ) > facsec*dist_IBC ) ;
6501 const int test2 = ( dist_proj > (1.+facsec)*Lref ) ;
6502
6503 if( monophasique )
6504 {
6505 if( test0 || (test1 && test2) )
6506 {
6507 // on modifie le projete en prenant le vertex lagrangien le plus proche
6508 for (int j = 0; j < dim ; j++)
6509 {
6510 coord_projete(j) = V(j) ;
6511 }
6512 projete_modifie = 1 ;
6513 cpt++ ;
6514 }
6515 }
6516 else
6517 {
6518 const int test = ( dist_IBC >= (1.-facsec)*Lref ) ;
6519
6520 if( (test0 && test) || (test1 && test2) )
6521 {
6522 // on modifie le projete en prenant le vertex lagrangien le plus proche
6523 for (int j = 0; j < dim ; j++)
6524 {
6525 coord_projete(j) = V(j) ;
6526 }
6527 projete_modifie = 1 ;
6528 cpt++ ;
6529 }
6530 }
6531
6532 if( projete_modifie == 1 )
6533 {
6534 dist_proj = 0. ;
6535 for (int j = 0; j < dim ; j++)
6536 {
6537 dist_proj += (x(j) - coord_projete(j))*(x(j) - coord_projete(j)) ;
6538 }
6539 dist_proj = sqrt( dist_proj ) ;
6540
6541 Cerr << " ------------------------------------------------------- "<<finl;
6542 Cerr << " le projete "<<finl;
6543 for(int i=0; i<dim; i++)
6544 {
6545 Cerr <<" X("<<i<<") = "<<coord_projete_old(i)<<finl ;
6546 }
6547 Cerr << " situe a une distance "<<dist_proj_old<<" du barycentre de la face "<<finl ;
6548 for(int i=0; i<dim; i++)
6549 {
6550 Cerr <<" Y("<<i<<") = "<<x(i)<<finl ;
6551 }
6552 Cerr << " a ete modifie en "<<finl ;
6553 for(int i=0; i<dim; i++)
6554 {
6555 Cerr <<" X("<<i<<") = "<<coord_projete(i)<<finl ;
6556 }
6557 Cerr << "situe a une distance "<<dist_proj<<" du barycentre de face "<<finl ;
6558 Cerr << "distance a l'IBC : "<<dist_IBC<<finl ;
6559 Cerr << "Longueur de reference : "<<Lref<<finl ;
6560 Cerr << " ------------------------------------------------------- "<<finl;
6561 }
6562}
6563
6564// Algorithme d'Uzawa calculant les coordonnees du projete du centre de gravite
6565// d'une face 'i_face' sur l'interface.
6566void Transport_Interfaces_FT_Disc::uzawa(const double d, const DoubleTab& C,
6567 const DoubleTab& x, const DoubleTab& f,
6568 DoubleTab& x_ibc) const
6569{
6570 double rho = 0. ;
6571 const int nb_lignes = C.dimension(0) ;
6572 const int nb_colonnes = C.line_size() ;
6573 assert(x_ibc.dimension(0) == nb_colonnes) ;
6574 assert(f.dimension(0) == nb_lignes) ;
6575 assert(x.dimension(0) == nb_colonnes) ;
6576
6577 // Calcul du pas rho :
6578 // Definition et initialisation des normes induites ||.||_1 et||.||_inf
6579 double norme1 = 0. ;
6580 double norme_infty = 0. ;
6581
6582 for (int j=0; j<nb_colonnes; j++)
6583 {
6584 double norme1_int = 0. ;
6585 for (int i=0; i<nb_lignes; i++)
6586 {
6587 norme1_int += std::fabs( C(i,j) ) ;
6588 }
6589 norme1 = std::max( norme1 , norme1_int ) ;
6590 }
6591
6592 for (int i=0; i<nb_lignes; i++)
6593 {
6594 double norme_infty_int = 0.;
6595 for (int j=0; j<nb_colonnes; j++)
6596 {
6597 norme_infty_int += std::fabs( C(i,j) ) ;
6598 }
6599 norme_infty = std::max( norme_infty , norme_infty_int ) ;
6600 }
6601 rho = 1. / ( norme1 * norme_infty ) ; //car ||A||_2^2 <= ||A||_1 ||A||_infty
6602
6603 // Definition et initialisation d'un multiplicateur de Lagrange
6604 DoubleTab lambda(nb_lignes) ;
6605 lambda = 0. ;
6606
6607 double distance = 1. ;
6608 double distance_old = 0. ;
6609 double deplacement_relatif = 1.;
6610 int nb_iter = 0 ;
6611
6612 double err_uzawa = variables_internes_->seuil_uzawa ;
6613 int nb_iter_max = variables_internes_->nb_iter_uzawa ;
6614 // On arrete l'algorithme des que le carre de la distance (projete,origine)
6615 // a l'etape k moins le carre de la distance (projete,origine) a l'etape k-1
6616 // est inferieur en valeur absolue au seuil 'err_uzawa'.
6617 // Pour des raisons de temps CPU, l'algorithme s'arrete egalement si
6618 // le nombre d'iterations est superieur a 'nb_iter_max'.
6619 // En pratique, les valeurs par defaut sont 'err_uzawa=1e-8' et 'nb_iter_max=30'.
6620 // Dans certains cas, par exemple pour des maillages tres grossiers, il a ete
6621 // observe que ce choix conduit a quelques differences sequentiel/parallele.
6622 // On recommande alors de diminuer le seuil et d'augmenter le nombre
6623 // d'iteration pour ameliorer la convergence de l'algorithme, au risque d'augmenter
6624 // le temps CPU.
6625 x_ibc = 0. ;
6626 while( deplacement_relatif > err_uzawa && nb_iter <= nb_iter_max )
6627 {
6628 // Calcul de la solution a l'etape k
6629 x_ibc = 0. ;
6630 distance_old = distance ;
6631 for (int i=0; i<x_ibc.dimension(0); i++)
6632 {
6633 for (int j=0; j<lambda.dimension(0); j++)
6634 {
6635 x_ibc(i) -= 0.5 * C(j,i) * lambda(j) ;
6636 }
6637 x_ibc(i) += x[i] ;
6638 }
6639
6640 // Calcul du multiplicateur de lagrange a l'etape k+1
6641 for (int i=0; i<lambda.dimension(0); i++)
6642 {
6643 //Parametre xx = C*x_ibc-f
6644 double xx = 0. ;
6645
6646 for (int j=0; j<x_ibc.dimension(0); j++)
6647 {
6648 xx += C(i,j)*x_ibc(j) ;
6649 }
6650 xx -= f(i) ;
6651 if ( d > 0 )
6652 {
6653 // cote solide
6654 lambda(i) = std::max( lambda(i) + rho * xx , 0. ) ;
6655 }
6656 else
6657 {
6658 //cote fluide
6659 lambda(i) = std::min( lambda(i) + rho * xx , 0. ) ;
6660 }
6661 }
6662 // Calcul et mise a jour de la condition du while
6663 distance = ( x_ibc(0) - x[0] ) * ( x_ibc(0) - x[0] )
6664 + ( x_ibc(1) - x[1] ) * ( x_ibc(1) - x[1] ) ;
6665 if (Objet_U::dimension==3)
6666 distance += ( x_ibc(2) - x[2] ) * ( x_ibc(2) - x[2] ) ;
6667
6668 deplacement_relatif = std::fabs(distance - distance_old) ;
6669 nb_iter++ ;
6670
6671 }
6672
6673}
6674
6675void Transport_Interfaces_FT_Disc::projete_point_face_fluide( int& nb_proj_modif,const int dimfa7,
6676 const DoubleTab& indicatrice_face, const DoubleTab& indicatrice,
6677 const DoubleTab& dist_face,const double t,const double dt,
6678 DoubleTab& Tab100,DoubleTab& Tab101,DoubleTab& Tab102,DoubleTab& Tab103,
6679 IntTab& Tab12,IntTab& CptFacette,DoubleTab& v_imp,DoubleTab& Vertex,Parser& parser_x, Parser& parser_y, Parser& parser_z )
6680{
6681 const int dim = Objet_U::dimension;
6682 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6683 const Domaine_VDF * zvdf = 0;
6684 if (sub_type(Domaine_VDF, mon_dom_dis))
6685 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis) ;
6686 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
6687 const IntVect& orientation = domaine_vdf.orientation();
6688 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
6689 const IntTab& elem_faces = domaine_vf.elem_faces();
6690 const IntTab& faces_elem = domaine_vf.face_voisins();
6691 const int nfaces = faces_elem.dimension(0) ;
6692 const DoubleTab& xv = domaine_vf.xv();
6693 const double invalid_test = -1.e30;
6694
6695 Cerr << "CALCUL DU PROJETE POUR LES FACES FLUIDE ET d > invalid_test" << finl ;
6696
6697 for (int i_face = 0; i_face < nfaces; i_face++)
6698 {
6699 double d = dist_face(i_face) ;
6700 if (indicatrice_face(i_face) == 0. && d > invalid_test)
6701 {
6702 DoubleList mat_0, mat_1, mat_2, mat_3 ;
6703 ArrOfBit fa7(dimfa7);
6704 fa7=0;
6705 int nb_facettes_to_uzawa = 0 ;
6706 // On travaille sur les elements voisins de chaque face 'i_face'
6707 for( int ii=0; ii<2; ii++ )
6708 {
6709 const int elem = faces_elem(i_face,ii) ;
6710 // Si cet element voisin existe
6711 if( elem >-1 )
6712 {
6713 // alors on parcourt ses autres faces
6714 for (int face_loc=0 ; face_loc<2*dim ; face_loc++)
6715 {
6716 const int autre_face = elem_faces(elem,face_loc) ;
6717
6718 if (indicatrice_face(autre_face) != 0. && indicatrice_face(autre_face) != 1.)
6719 {
6720 // on identifie les elements auxquels appartient autre_face
6721 // et qui sont traverses par l'interface
6722 for(int ii2=0 ; ii2<2; ii2++)
6723 {
6724 const int elem_voisin = faces_elem(autre_face,ii2) ;
6725
6726 // On veut que l'element existe, qu'il soit lui-meme
6727 // traverse par une interface
6728 if( elem_voisin>-1 && indicatrice(elem_voisin) != 0.
6729 && indicatrice(elem_voisin) != 1. )
6730 {
6731
6732 for( int i=0 ; i< CptFacette(elem_voisin) ; i++)
6733 {
6734 if( !fa7.testsetbit( Tab12(elem_voisin,i) ) )
6735 {
6736 nb_facettes_to_uzawa++ ;
6737 mat_0.add( Tab100(elem_voisin,i) ) ;
6738 mat_1.add( Tab101(elem_voisin,i) ) ;
6739 mat_2.add( Tab102(elem_voisin,i) ) ;
6740 mat_3.add( Tab103(elem_voisin,i) ) ;
6741 }
6742 }
6743 }
6744 }
6745 }
6746 }
6747 }
6748 }
6749 if( nb_facettes_to_uzawa > 0 )
6750 {
6751 DoubleTab matrice_plans(nb_facettes_to_uzawa, dim) ;
6752 DoubleTab x(dim) ;
6753 DoubleTab secmem(nb_facettes_to_uzawa) ;
6754
6755 for( int i_facette=0 ; i_facette<nb_facettes_to_uzawa ; i_facette++ )
6756 {
6757 matrice_plans(i_facette,0) = mat_0[i_facette] ;
6758 matrice_plans(i_facette,1) = mat_1[i_facette] ;
6759 if (dim==3)
6760 matrice_plans(i_facette,2) = mat_2[i_facette] ;
6761 secmem[i_facette] = -mat_3[i_facette] ;
6762 }
6763
6764 for (int i_coord=0; i_coord<dim; i_coord++)
6765 {
6766 x(i_coord) = xv(i_face,i_coord) ;
6767 }
6768
6769 // Calcul des coordonnees du projete 'coord_projete'
6770 DoubleTab coord_projete(dim) ;
6771 coord_projete = 0. ;
6772 uzawa(d,matrice_plans,x,secmem,coord_projete) ;
6773
6774 if (variables_internes_->type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE)
6775 {
6776 DoubleTab V(dim) ;
6777 for (int i_coord=0; i_coord<dim; i_coord++)
6778 {
6779 V(i_coord) = Vertex(i_face,i_coord) ;
6780 }
6781 int cpt = 0 ;
6782 double Lref =0. ;
6783 const int ori = orientation[i_face] ;
6784 const int voisin0 = faces_elem(i_face,0) ;
6785 const int voisin1 = faces_elem(i_face,1) ;
6786 const int monophasique = 1 ;
6787 calcul_tolerance_projete_monophasique(i_face,ori,voisin0,voisin1,indicatrice_face,indicatrice,Lref) ;
6788 verifprojete(monophasique,Lref,d,x,V,coord_projete,cpt) ;
6789 if( cpt > 0 )
6790 nb_proj_modif++ ;
6791 }
6792
6793 //Calcul de la vitesse du projete
6794 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE)
6795 {
6796 for (int j = 0; j < dim; j++)
6797 {
6798 parser_x.setVar(j, coord_projete(j)) ;
6799 parser_y.setVar(j, coord_projete(j)) ;
6800 if (dim==3)
6801 parser_z.setVar(j, coord_projete(j)) ;
6802 }
6803 if (zvdf)
6804 {
6805 switch(zvdf->orientation(i_face))
6806 {
6807 case 0:
6808 v_imp(i_face) = parser_x.eval() ;
6809 break ;
6810 case 1:
6811 v_imp(i_face) = parser_y.eval() ;
6812 break ;
6813 case 2:
6814 v_imp(i_face) = parser_z.eval() ;
6815 break ;
6816 }
6817 }
6818 }
6819 else if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE )
6820 {
6821 ArrOfDouble v(dim) ;
6822 v = variables_internes_->loi_horaire_->vitesse(t+dt,coord_projete);
6823 if (zvdf)
6824 v_imp(i_face)=v[zvdf->orientation(i_face)];
6825 }
6826 }
6827 }
6828 }
6829}
6830
6831void Transport_Interfaces_FT_Disc::projete_point_face_interface( int& nb_proj_modif, const int dimfa7, const DoubleTab& indicatrice_face,
6832 const DoubleTab& indicatrice, const DoubleTab& dist_face,
6833 const double t, const double dt, DoubleTab& Tab100,
6834 DoubleTab& Tab101, DoubleTab& Tab102,DoubleTab& Tab103,
6835 IntTab& Tab12,IntTab& CptFacette, DoubleTab& v_imp,
6836 DoubleTab& Vertex,Parser& parser_x, Parser& parser_y,
6837 Parser& parser_z )
6838{
6839 const int dim = Objet_U::dimension;
6840 const Domaine_dis_base& mon_dom_dis = domaine_dis();
6841 const Domaine_VDF * zvdf = 0 ;
6842 if (sub_type(Domaine_VDF, mon_dom_dis))
6843 zvdf = &ref_cast(Domaine_VDF, mon_dom_dis);
6844 const Domaine_VDF& domaine_vdf = ref_cast(Domaine_VDF, mon_dom_dis);
6845 const IntVect& orientation = domaine_vdf.orientation();
6846 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
6847 const IntTab& elem_faces = domaine_vf.elem_faces();
6848 const IntTab& faces_elem = domaine_vf.face_voisins();
6849 const int nfaces = faces_elem.dimension(0) ;
6850 const DoubleTab& xv = domaine_vf.xv() ;
6851 const double invalid_test = -1.e30;
6852
6853 for( int i_face=0 ; i_face<nfaces ; i_face++ )
6854 {
6855 double d = dist_face(i_face) ;
6856 const int diphasique_tmp = (indicatrice_face(i_face) != 0. &&
6857 (indicatrice_face(i_face) != 1. || (indicatrice_face(i_face) == 1. && d<=0. && d> invalid_test)));
6858 const int diphasique = ( variables_internes_->is_extra_diphasique_solide ? diphasique_tmp : (diphasique_tmp && d <= 0.) ) ;
6859 const int fluide = ( indicatrice_face(i_face) == 0. ) ;
6860 const int solide = ( variables_internes_->is_extra_solide && (d>0. || (indicatrice_face(i_face) == 1. && d<-1.e20)) ) ;
6861 const int monophasique = ( fluide || solide ) ;
6862
6863 if (diphasique || (monophasique && d> invalid_test ))
6864 {
6865 DoubleList mat_0, mat_1, mat_2, mat_3 ;
6866 ArrOfBit fa7(dimfa7);
6867 fa7=0;
6868 int nb_facettes_to_uzawa = 0 ;
6869
6870 // Coordonnes du projet 'coord_projete'
6871 DoubleTab coord_projete(dim) ;
6872 coord_projete = 0. ;
6873 int projete_calcule = 0 ;
6874
6875 // Si la face a une indicatrice de 0.5 celui implique
6876 // qu'elle est parfaitement traverse par au moins une facette.
6877 // Dans ce cas, le projet du barycentre de la face sur le
6878 // plan des facettes est lui-mme.
6879 if( indicatrice_face(i_face) == 0.5 )
6880 {
6881 int voisin = -1 ;
6882 if( faces_elem(i_face,0) > -1 )
6883 voisin = faces_elem(i_face,0) ;
6884 else
6885 voisin = faces_elem(i_face,1) ;
6886
6887 if( indicatrice(voisin) == 0. || indicatrice(voisin) == 1. )
6888 {
6889 for( int j=0 ; j<dim ; j++)
6890 {
6891 coord_projete(j)=xv(i_face,j) ;
6892 }
6893 projete_calcule = 1 ;
6894 }
6895 }
6896
6897 if( projete_calcule == 0 )
6898 {
6899 if( d == 0. )
6900 {
6901 for( int j=0 ; j<dim ; j++)
6902 {
6903 coord_projete(j)=xv(i_face,j) ;
6904 }
6905 }
6906 else
6907 {
6908 // on identifie les elements auxquels appartient i_face
6909 // et qui sont traverses par l'interface
6910 for(int ii=0 ; ii<2; ii++)
6911 {
6912 const int elem_voisin = faces_elem(i_face,ii) ;
6913
6914
6915 // On veut que l'element existe, qu'il soit lui-meme
6916 // traversepar une interface
6917 // YG : ce test a ete scinde en deux. Dans le cas d une indicatrice
6918 // modifiee, il peut arriver qu aucun des voisins ait une indicatrice
6919 // element !=0. Pour autant, on a envie de regarder les voisins des
6920 // voisins pour chercher des facettes. Idem pour le cas monophasique!
6921 if( elem_voisin>-1)
6922 {
6923 if (indicatrice(elem_voisin) != 0. && indicatrice(elem_voisin) != 1. )
6924 {
6925 for( int i=0 ; i< CptFacette(elem_voisin) ; i++)
6926 {
6927 if( !fa7.testsetbit( Tab12(elem_voisin,i) ) )
6928 {
6929 nb_facettes_to_uzawa++ ;
6930 mat_0.add( Tab100(elem_voisin,i) ) ;
6931 mat_1.add( Tab101(elem_voisin,i) ) ;
6932 mat_2.add( Tab102(elem_voisin,i) ) ;
6933 mat_3.add( Tab103(elem_voisin,i) ) ;
6934 }
6935 }
6936 }
6937 // On identifie ensuite les elements voisins (elem_voisin_voisin)
6938 // traverses par l'IBC.
6939 for(int j=0 ; j<2*dim ; j++)
6940 {
6941 const int elem_voisin_voisin = faces_elem(elem_faces(elem_voisin,j),0)
6942 + faces_elem(elem_faces(elem_voisin,j),1) - elem_voisin ;
6943
6944 if( elem_voisin_voisin>-1 && indicatrice(elem_voisin_voisin) != 0.
6945 && indicatrice(elem_voisin_voisin) != 1.
6946 && elem_voisin_voisin!=faces_elem(i_face,0)
6947 && elem_voisin_voisin!=faces_elem(i_face,1) )
6948 {
6949 for( int i=0 ; i< CptFacette(elem_voisin_voisin) ; i++)
6950 {
6951 if( !fa7.testsetbit( Tab12(elem_voisin_voisin,i) ) )
6952 {
6953 nb_facettes_to_uzawa++ ;
6954 mat_0.add( Tab100(elem_voisin_voisin,i) ) ;
6955 mat_1.add( Tab101(elem_voisin_voisin,i) ) ;
6956 mat_2.add( Tab102(elem_voisin_voisin,i) ) ;
6957 mat_3.add( Tab103(elem_voisin_voisin,i) ) ;
6958 }
6959 }
6960 }
6961 }
6962 }
6963 }
6964
6965 if( nb_facettes_to_uzawa == 0 && diphasique )
6966 {
6967 Cerr << "erreur concernant la face : "<< i_face << " I_f = "<<indicatrice_face(i_face)<<finl ;
6968 Cerr << "aucune facette detecte "<< finl ;
6969 Process::exit() ;
6970 }
6971 else if (nb_facettes_to_uzawa >0)
6972 {
6973
6974 DoubleTab matrice_plans(nb_facettes_to_uzawa, dim) ;
6975 DoubleTab x(dim) ;
6976 DoubleTab secmem(nb_facettes_to_uzawa) ;
6977
6978 for( int i_facette=0 ; i_facette<nb_facettes_to_uzawa ; i_facette++ )
6979 {
6980 matrice_plans(i_facette,0) = mat_0[i_facette] ;
6981 matrice_plans(i_facette,1) = mat_1[i_facette] ;
6982 if (dim==3)
6983 matrice_plans(i_facette,2) = mat_2[i_facette] ;
6984 secmem[i_facette] = -mat_3[i_facette] ;
6985 }
6986 for (int i_coord=0; i_coord<dim; i_coord++)
6987 {
6988 x(i_coord) = xv(i_face,i_coord) ;
6989 }
6990 coord_projete = 0. ;
6991 uzawa(d,matrice_plans,x,secmem,coord_projete) ;
6992
6993 if(variables_internes_-> type_projete_calcule == Transport_Interfaces_FT_Disc_interne::PROJETE_MODIFIE)
6994 {
6995 DoubleTab V(dim) ;
6996 for (int i_coord=0; i_coord<dim; i_coord++)
6997 {
6998 V(i_coord) = Vertex(i_face,i_coord) ;
6999 }
7000 int cpt = 0 ;
7001 double Lref = 0. ;
7002 const int ori = orientation[i_face] ;
7003 const int voisin0 = faces_elem(i_face,0) ;
7004 const int voisin1 = faces_elem(i_face,1) ;
7005 const int monophasique2 = 0 ;
7006 calcul_tolerance_projete_diphasique(i_face,ori,voisin0,voisin1,indicatrice,Lref) ;
7007 verifprojete(monophasique2,Lref,d,x,V,coord_projete,cpt) ;
7008 if( cpt > 0 )
7009 nb_proj_modif++ ;
7010 }
7011 }
7012 }
7013 }
7014
7015 const int test = (diphasique || fluide || solide ) ;
7016
7017
7018 if(test)
7019 {
7020 // Calcul de la vitesse du projete
7021 if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::VITESSE_IMPOSEE)
7022 {
7023 for (int j = 0; j < dim; j++)
7024 {
7025 parser_x.setVar(j, coord_projete(j)) ;
7026 parser_y.setVar(j, coord_projete(j)) ;
7027 if (dim==3)
7028 parser_z.setVar(j, coord_projete(j)) ;
7029 }
7030 if (zvdf)
7031 {
7032 switch(zvdf->orientation(i_face))
7033 {
7034 case 0:
7035 v_imp(i_face) = parser_x.eval() ;
7036 break ;
7037 case 1:
7038 v_imp(i_face) = parser_y.eval() ;
7039 break ;
7040 case 2:
7041 v_imp(i_face) = parser_z.eval() ;
7042 break ;
7043 }
7044 }
7045 }
7046 else if (variables_internes_->methode_transport == Transport_Interfaces_FT_Disc_interne::LOI_HORAIRE )
7047 {
7048 ArrOfDouble v(dim);
7049 v = variables_internes_->loi_horaire_->vitesse(t+dt,coord_projete);
7050 if (zvdf)
7051 v_imp(i_face)=v[zvdf->orientation(i_face)];
7052 }
7053 }
7054 }
7055 }
7056}
7057
7058/*! @brief Deplace le maillage a l'aide du champ de vitesse impose entre l'instant maillage.
7059 *
7060 * temps() et l'instant "temps".
7061 * La nouvelle position des sommets est obtenue par integration des lignes de courant de ce champ,
7062 * par un schema RK3 (en un pas de temps) qui prend en compte la dependance en temps des vitesses imposees.
7063 * On "nettoie" et on change le temps du maillage. Pas de remaillage. maillage MINIMAL en sortie.
7064 *
7065 */
7066static void deplacer_maillage_ft_v_impose(Noms expression_vitesse,
7067 Maillage_FT_Disc& maillage, double temps)
7068{
7069 const double dt = temps - maillage.temps();
7070 Parser parser_x, parser_y, parser_z;
7071 init_parser_v_impose(expression_vitesse,
7072 parser_x, parser_y, parser_z, temps);
7073
7074 const DoubleTab& sommets = maillage.sommets();
7075 const int dim = sommets.dimension(1);
7076 const int dimension3 = (dim == 3);
7077 int i;
7078 const int nb_sommets = maillage.nb_sommets();
7079 DoubleTabFT deplacement(nb_sommets, dim);
7080 for (i = 0; i < nb_sommets; i++)
7081 {
7082 const double x0 = sommets(i, 0);
7083 const double y0 = sommets(i, 1);
7084 const double z0 = dimension3 ? sommets(i, 2) : 0.;
7085 double x = x0, y = y0, z = z0;
7086 integrer_vitesse_imposee(parser_x, parser_y, parser_z,
7087 temps, dt, x, y, z);
7088 deplacement(i, 0) = x - x0;
7089 deplacement(i, 1) = y - y0;
7090 if (dimension3)
7091 deplacement(i, 2) = z - z0;
7092 }
7093 maillage.transporter(deplacement);
7094 maillage.nettoyer_elements_virtuels();
7095 maillage.changer_temps(temps);
7096}
7097
7098// Calcul d'une vitesse de deplacement minimisant les deplacements relatifs
7099// des sommets d'interface dans le repere local (donc minimisant les remaillages locaux)
7100// On veut que, dans le repere mobile associe au centre de gravite de l'interface,
7101// le deplacement tangentiel soit nul.
7102void Transport_Interfaces_FT_Disc::calculer_vitesse_repere_local(const Maillage_FT_Disc& maillage, DoubleTab& deplacement,DoubleTab& Positions,DoubleTab& Vitesses) const
7103{
7104 // const Maillage_FT_Disc & maillage = maillage_interface();
7105 //vitesse des centres d'aire
7106 const int nb_facettes=maillage.nb_facettes();
7107 const IntTab& facettes=maillage.facettes ();
7108 const int dim3 = (deplacement.line_size() == 3);
7109 ArrOfInt compo_connexe_facettes(nb_facettes); // Init a zero
7110 int n = search_connex_components_local_FT(maillage, compo_connexe_facettes);
7111 int nb_compo_tot=compute_global_connex_components_FT(maillage, compo_connexe_facettes, n);
7112
7113 DoubleTabFT normale;
7114 calculer_normale_sommets_interface(maillage, normale);
7115 Positions.resize(nb_compo_tot,dimension);
7116 Vitesses.resize(nb_compo_tot,dimension);
7117
7118 calculer_vmoy_composantes_connexes(maillage, compo_connexe_facettes, nb_compo_tot,
7119 deplacement, Vitesses, Positions);
7120
7121 // Calcul de la composante connexe des sommets
7122 // Attention un sommet peut n'etre rattache a aucune facette sur le meme processeur !
7123 // (il faudrait calculer les compo connexes sur les sommets, et ensuite passer aux faces
7124 // ce serait plus simple, voire calculer les deux en meme temps)
7125 IntVect compo_sommets;
7126 maillage.creer_tableau_sommets(compo_sommets, RESIZE_OPTIONS::NOCOPY_NOINIT);
7127 compo_sommets = -1;
7128 {
7129 const int dim = deplacement.dimension(1);
7130 for (int iface = 0; iface < nb_facettes; iface++)
7131 {
7132 const int compo = compo_connexe_facettes[iface];
7133 for (int j = 0; j < dim; j++)
7134 compo_sommets[facettes(iface, j)] = compo;
7135 }
7136 // On prend le max sur tous les processeurs qui partagent le sommet pour les sommets isoles
7137 // (max calcule uniquement pour les sommets reels, sommets virtuels faux)
7139 // Inutile de synchroniser, on utilise uniquement les sommets reels
7140 }
7141
7142 const int nb_sommets_tot = compo_sommets.size_totale();
7143 for (int som = 0; som < nb_sommets_tot; som++)
7144 {
7145 if (maillage.sommet_virtuel(som))
7146 {
7147 // Valeur pipo pour dire qu'on initialise pas
7148 deplacement(som, 0) = 100.;
7149 deplacement(som, 1) = 100.;
7150 continue;
7151 }
7152
7153 const int compo = compo_sommets[som];
7154
7155 // (v-vmoy) doit etre normal a l'interface
7156 // Donc on fait v_corrige = v_initial - composante_tangentielle_de(v_initial-vmoy)
7157 // Demonstration que (v_corrige - vmoy) est normal a l'interface :
7158 // On note ct() = composante_tangentielle_de()
7159 // ct(v_corrige - vmoy)
7160 // = ct(v_corrige) - ct(vmoy) car ct est lineaire
7161 // = ct(v_initial - ct(v_initial) + ct(vmoy)) - ct(vmoy) car ct est lineaire
7162 // = ct(v_initial) - ct(v_initial) + ct(vmoy) - ct(vmoy) cat ct(ct(x)) = ct(x) et linearite
7163 // = 0
7164
7165 // v_corrige = cn(v_initial - vmoy) + vmoy
7166 // v_corrige = cn(v_initial) - cn(vmoy) + vmoy
7167 // v_corrige = cn(v_initial) + ct(vmoy)
7168 // v_corrige = v_initial - ct(v_inital) + ct(vmoy)
7169 // v_corrige = v_initial - ct(v_initial - vmoy)
7170
7171 double nx = 0., ny = 0., nz = 0.;
7172 double vi_x = 0., vi_y = 0., vi_z = 0.;
7173
7174 nx = normale(som, 0);
7175 ny = normale(som, 1);
7176
7177 vi_x = deplacement(som, 0);
7178 vi_y = deplacement(som, 1);
7179 if (dim3)
7180 {
7181 vi_z = deplacement(som, 2);
7182 nz=normale(som, 2);
7183 }
7184
7185 double prodscal =
7186 (vi_x - Vitesses(compo, 0)) * nx
7187 + (vi_y - Vitesses(compo, 1)) * ny;
7188 if (dim3)
7189 prodscal += (vi_z - Vitesses(compo, 2)) * nz;
7190 double norme_carre = nx * nx + ny * ny + nz * nz;
7191
7192 int is_solid_particle = get_is_solid_particle() ? 1 : 0;
7193 if (norme_carre != 0.)
7194 {
7195 prodscal /= norme_carre;
7196 deplacement(som, 0) = nx * prodscal* (1-is_solid_particle) + Vitesses(compo, 0);
7197 deplacement(som, 1) = ny * prodscal* (1-is_solid_particle) + Vitesses(compo, 1);
7198 if (dim3)
7199 deplacement(som, 2) = nz * prodscal* (1-is_solid_particle) + Vitesses(compo, 2); // BugFix reported from baltik TCL on 2020/10/26
7200 }
7201 }
7202}
7203
7204// This method is called by mettre_a_jour(), so it is done in a loop that depends on the order of equations.
7205// NS is forced as first, always.
7206// Therefore, NS has turned the wheel (tourner la roue) before getting here.
7207// To make a really explicit scheme, we want to use u^n, not u^n+1.
7208// Because of the wheel turns in equation(0).mettre_a_jour() (which is NS), u^n is currently in .futur() and NOT in .present() (or .valeur() which is synonymous)
7210{
7211 DoubleTab& deplacement = variables_internes_->deplacement_sommets;
7212 const Navier_Stokes_std& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
7213 // Method is called by mettre_a_jour()
7214 // The option explicit_u_NS_ = 0 enables corresponds to the historical scheme in TrioCFD, which was apparently semi-implicit.
7215 // Set to explicit_u_NS_ = 1, you get a real explicit scheme.
7216 // WARNING : read comment above method explaining why "explicit" should use ".futur()"!!!
7217 // This option affects the calculation directly in calculer_vitesse_transport_interpolee
7218 const Champ_base& champ_vitesse = eqn_hydraulique.inconnue();
7220 // Calcul de la vitesse de deplacement des sommets par interpolation
7221 // (deplacement contient en fait la vitesse en m/s)
7222 int flag = 1;
7223 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
7224 {
7225 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
7227 flag=0;
7228 }
7230 maillage,
7231 deplacement, 1 /* recalculer le champ de vitesse L2 */,
7232 flag /* Interpolation Multi-lineaire en VDF */,
7233 true /* la_roue_de_vitesse_a_deja_tournee */);
7234
7235#if DEBUG_CONSERV_VOLUME
7236 int n = maillage.nb_sommets();
7237 double dmin=0.;
7238 double dmax=0.;
7239 double dmean = 0.;
7240 DoubleTab norm_deplacement(n);
7241 if (n>0)
7242 {
7243 for (int i=0; i<n; i++)
7244 {
7245 double x = 0.;
7246 for (int j=0; j<deplacement.dimension(1); j++)
7247 x += deplacement(i,j)*deplacement(i,j);
7248 norm_deplacement[i] = sqrt(x);
7249 dmean +=sqrt(x);
7250 }
7251 dmean /=n;
7252 dmin = min_array(norm_deplacement);
7253 dmax = max_array(norm_deplacement);
7254 }
7255#endif
7256 // On recupere et ajoute a deplacement le saut de vitesse a l'interface si changement de phase
7258 true /* la_roue_de_vitesse_a_deja_tournee */);
7259
7260#if DEBUG_CONSERV_VOLUME
7261 if (n>0)
7262 {
7263 double dmean_wpch = 0.;
7264 for (int i=0; i<n; i++)
7265 {
7266 double x = 0.;
7267 for (int j=0; j<deplacement.dimension(1); j++)
7268 x += deplacement(i,j)*deplacement(i,j);
7269 norm_deplacement[i] = sqrt(x);
7270 dmean_wpch +=sqrt(x);
7271 }
7272 dmean_wpch /=n;
7273 double dmin_wpch = min_array(norm_deplacement);
7274 double dmax_wpch = max_array(norm_deplacement);
7275 Cerr << "Interfacial_velocity before/after pch [min/mean/max]. Time: "
7277 << " Without-pch: " << dmin << " " << dmean<< " " << dmax
7278 << " With-pch: " << dmin_wpch << " " << dmean_wpch << " " << dmax_wpch
7279 << " [Warning, values invalid in //] " << finl;
7280 }
7281#endif
7282
7283 if (interpolation_repere_local_)
7284 {
7285 DoubleTab Positions,Vitesses;
7286
7287 calculer_vitesse_repere_local(maillage, deplacement,Positions,Vitesses);
7288 assert(Positions.dimension(0)==Vitesses.dimension(0));
7290 {
7291 ofstream fout;
7292 fout.open("composantes_connexes.txt",ios::app);
7293 fout << "TEMPS: " << temps << std::endl;
7294 const int nb_bulles=Positions.dimension(0);
7295
7296 for(int bulle=0; bulle<nb_bulles; bulle++)
7297 {
7298 fout << "composante " << bulle << " position " ;
7299 for (int i=0; i <Positions.dimension(1); i++) fout << " " << Positions(bulle,i);
7300 fout << " vitesse " ;
7301 for (int i=0; i <Vitesses.dimension(1); i++) fout << " " << Vitesses(bulle,i);
7302 fout << std::endl;
7303 }
7304 fout.close();
7305 }
7306 }
7307
7308 const double delta_t = temps - maillage.temps();
7309 // Calcul du deplacement :
7310 deplacement *= delta_t;
7311
7312// Debug GB 2020.03.20 Conservation de volume
7313#if DEBUG_CONSERV_VOLUME
7314 double volume_avt = remaillage_interface().calculer_volume_mesh(maillage);
7315#endif
7316 if (variables_internes_->VOFlike_correction_volume > 0)
7317 {
7318 // Transport avec correction du volume des phases :
7319 // Sauvegarde de la position actuelle des sommets :
7320 DoubleTabFT position_precedente = maillage.sommets();
7321 maillage.preparer_tableau_avant_transport(position_precedente,
7322 maillage.desc_sommets());
7323 // Calcul de la variation de volume exacte a obtenir a partir du
7324 // champ de vitesse eulerien :
7325 ArrOfDoubleFT var_volume;
7326 {
7327 // Desole pour le ref_cast_non_const, il y a probablement plus propre mais je ne sais pas faire.
7328 // En l'etat, 'ns' doit etre non-const car il fait appel a get_update...normale et get_compute_indicatrice_faces
7329 // qui modifient l'objet Transport_... dans lequel nous sommes!
7330 Navier_Stokes_FT_Disc& ns = ref_cast_non_const(Navier_Stokes_FT_Disc, eqn_hydraulique);
7331
7332 DoubleVect dI_dt;
7334 // Here, the velocity given is either explicit or semi-impli depending on the choice for : explicit_u_NS_
7335 const DoubleTab& val_champ_vitesse = (bool)(explicit_u_NS_) ? champ_vitesse.futur() : champ_vitesse.valeurs();
7336 ns.calculer_dI_dt(dI_dt, val_champ_vitesse);
7337 dI_dt.echange_espace_virtuel();
7338#if DEBUG_CONSERV_VOLUME
7339 const int nb_elem = domaine_dis().nb_elem();
7340 double sum_before_rm = 0.;
7341 double sum_before_rm_dvol = 0.;
7342 for (int i = 0; i < nb_elem; i++)
7343 sum_before_rm +=-dI_dt[i]; // It's already homogeneous to *volumes[i];
7344
7345 sum_before_rm_dvol +=sum_before_rm*delta_t;
7346#endif
7347 // if (!ns.is_shift_secmem2_activated()) even modifiee is used, the indicatrice at cell-face is not exactly well reconstructed
7348 // still need ramasse_miettes to get good dI_dt
7349 // ONEDAY, indicatrice at cell-face are well construire, this can be comment
7350 ramasse_miettes(maillage, variables_internes_->tmp_flux->valeurs(), dI_dt);
7351 transfert_conservatif_eulerien_vers_lagrangien_sommets(maillage, dI_dt, var_volume);
7352
7353#if DEBUG_CONSERV_VOLUME
7354 double sum = 0.;
7355 for (int i = 0; i < nb_elem; i++)
7356 sum +=-dI_dt[i]; // It's already homogeneous to *volumes[i];
7357
7358 const double dvoldt_totale = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7359 const double sum_dvol =sum*delta_t;
7360 Cerr << " time " << temps << " sum_dI_dt " << sum << " sum_dvol " << sum_dvol
7361 << " sum_before_rm_dI_dt " << sum_before_rm << " sum_before_rm_dvol " << sum_before_rm_dvol
7362 << " V_lagrangien= " << dvoldt_totale <<finl;
7363#endif
7364 }
7365 // var_volume est une derivee par rapport au temps.
7366 // calcul de l'integrale pendant le pas de temps ...
7367 // et changement de signe car on veut la variation de volume de la phase 0
7368 // (et non celle de la phase 1)
7369 var_volume *= -delta_t;
7370// Debug GB 2019.02.08 Conservation de volume
7371#if DEBUG_CONSERV_VOLUME
7372 double dvol_theo_depl = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7373#endif
7374 maillage.preparer_tableau_avant_transport(var_volume,
7375 maillage.desc_sommets());
7376 // Transport avec le deplacement interpole :
7378 maillage.transporter(deplacement);
7379 maillage.update_tableau_apres_transport(position_precedente,
7380 maillage.nb_sommets(),
7381 maillage.desc_sommets());
7382 maillage.update_tableau_apres_transport(var_volume,
7383 maillage.nb_sommets(),
7384 maillage.desc_sommets());
7385
7386 // Calcul de la variation de volume obtenue par ce deplacement :
7387 ArrOfDoubleFT var_volume_deplacement;
7389 position_precedente,
7390 var_volume_deplacement);
7391#if DEBUG_CONSERV_VOLUME
7392 double volume_apres = remaillage_interface().calculer_volume_mesh(maillage);
7393 double dvol_reel_depl = remaillage_interface().calculer_somme_dvolume(maillage, var_volume_deplacement);
7394 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_repere_local " << finl
7395 << " volume avt= " << volume_avt << finl
7396 << " apres= " << volume_apres << finl
7397 << " dvol_theo_depl= " << dvol_theo_depl << finl
7398 << " dvol_reel_depl= " << dvol_reel_depl << finl
7399 << finl;
7400#endif
7401 // Calcul de la variation de volume de la phase 0 a imposer lors de la correction
7402 // de volume :
7403 var_volume -= var_volume_deplacement;
7404
7405 // Si volume de phase_1 imposee : on calcule une deuxieme correction
7406 if (variables_internes_->volume_impose_phase_1 > 0.)
7407 {
7408 DoubleVect values(3);
7409 values=0.;
7410// volume_phase_1 -> values(0)
7411// volume_sous_domaine -> values(1)
7412// volume_phase_0 -> values(2)
7413 if (variables_internes_->nom_domaine_volume_impose_ == "??")
7414 values(0) = calculer_integrale_indicatrice(indicatrice_->valeurs(), values(2));
7415 else
7416 {
7417 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
7418 const DoubleVect& volumes = domaine_vf.volumes();
7419 const Sous_Domaine& sous_domaine = domaine_dis().domaine().ss_domaine(variables_internes_->nom_domaine_volume_impose_);
7420 const int nb_elem_sous_domaine = sous_domaine.nb_elem_tot();
7421 const DoubleTab& indic = indicatrice_->valeurs();
7422 const int nb_elem = domaine_vf.nb_elem();
7423 for (int i = 0; i < nb_elem_sous_domaine; i++)
7424 {
7425 const int elem = sous_domaine[i];
7426 if (elem < nb_elem)
7427 {
7428 values(0) += indic(elem) * volumes(elem);
7429 values(1) += volumes(elem);
7430 values(2) += (1.-indic(elem)) * volumes(elem);
7431 }
7432 }
7433 mp_sum_for_each_item(values);
7434 /* Cerr << "Volume_sous_domaine " << variables_internes_->nom_domaine_volume_impose_ <<
7435 mp_sum(volume_sous_domaine) << finl;
7436 volume_phase_1 = mp_sum(volume_phase_1); */
7437 Cerr << "Volume_sous_domaine " << variables_internes_->nom_domaine_volume_impose_ <<
7438 values(1) << finl;
7439
7440 }
7441 const double erreur_volume = variables_internes_->volume_impose_phase_1 - values(0);
7442 Journal() << "Transport_Interfaces_FT_Disc::mettre_a_jour "
7443 << "correction_volume_impose_phase_1= " << erreur_volume << finl;
7444 // Calcul de la correction de volume a imposer a chaque sommet
7445 // Surface totale d'interface:
7446 double surface_tot = 0.;
7447 {
7448 int i;
7449 const int nb_facettes = maillage.nb_facettes();
7450 const ArrOfDouble& surfaces = maillage.get_update_surface_facettes();
7451
7452 for (i = 0; i < nb_facettes; i++)
7453 surface_tot += surfaces[i];
7454
7455 surface_tot = mp_sum(surface_tot) * 3.;
7456 if (surface_tot > 0.)
7457 {
7458 const double inv_surface_tot = 1. / surface_tot;
7459 const IntTab& facettes = maillage.facettes();
7460 const int nb_som_facette = facettes.dimension(1);
7461 for (i = 0; i < nb_facettes; i++)
7462 {
7463 int j;
7464 const double dvolume = erreur_volume * surfaces[i] * inv_surface_tot;
7465 for (j = 0; j < nb_som_facette; j++)
7466 {
7467 int isom = facettes(i,j);
7468 // var_volume est la variation de volume de phase 0, donc signe "moins"
7469 var_volume[isom] -= dvolume;
7470 }
7471 }
7472 }
7473 }
7474 }
7475 // Correction de volume :
7476 // GB. 2019.05.13. Pourquoi utiliser iterations_correction_volume pour le nombre de lissage de dvol?
7477 // remaillage_interface().lisser_dvolume(maillage, var_volume,
7478 // variables_internes_->iterations_correction_volume);
7479 // 2019.05.13. Nouveau code :
7480 remaillage_interface().lisser_dvolume(maillage, var_volume,
7481 variables_internes_->nb_lissage_correction_volume);
7482
7483#if DEBUG_CONSERV_VOLUME
7484 double volume_before = remaillage_interface().calculer_volume_mesh(maillage);
7485 double dvol_total_before = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7486 Cerr << " dvol_error_before= " << dvol_total_before << " Volume_before= " << volume_before << " time " << temps << finl;
7487#endif
7488 // GB. 2019.05.13. Pourquoi utiliser nb_iter_bary_volume_seul_ plutot que iterations_correction_volume?
7489 //remaillage_interface().corriger_volume(maillage, var_volume);
7490 // 2019.05.13. Nouveau code :
7491 remaillage_interface().corriger_volume_(maillage, var_volume,
7492 variables_internes_->nb_iterations_correction_volume);
7493#if DEBUG_CONSERV_VOLUME
7494 double volume_after = remaillage_interface().calculer_volume_mesh(maillage);
7495 double dvol_total_after = remaillage_interface().calculer_somme_dvolume(maillage, var_volume);
7496 Cerr << " dvol_error_after= " << dvol_total_after << " Volume_after= " << volume_after << " time " << temps << finl;
7497#endif
7498 }
7499 else
7500 {
7501#if DEBUG_CONSERV_VOLUME
7502 // Sauvegarde de la position actuelle des sommets :
7503 DoubleTabFT position_precedente = maillage.sommets();
7504 maillage.preparer_tableau_avant_transport(position_precedente,
7505 maillage.desc_sommets());
7506#endif
7507 // Transport par interpolation de vitesse seule :
7509 maillage.transporter(deplacement);
7510#if DEBUG_CONSERV_VOLUME
7511 // Calcul de la variation de volume obtenue par ce deplacement :
7512 ArrOfDoubleFT var_volume_deplacement;
7514 position_precedente,
7515 var_volume_deplacement);
7516
7517 maillage.update_tableau_apres_transport(position_precedente,
7518 maillage.nb_sommets(),
7519 maillage.desc_sommets());
7520 double volume_apres = remaillage_interface().calculer_volume_mesh(maillage);
7521 double dvol_reel_depl = remaillage_interface().calculer_somme_dvolume(maillage, var_volume_deplacement);
7522 Cerr << "Transport_Interfaces_FT_Disc::calculer_vitesse_repere_local " << finl
7523 << " volume avt= " << volume_avt << finl
7524 << " apres= " << volume_apres << finl;
7525// pas calcule Cerr << " dvol_theo_depl= " << dvol_theo_depl << finl;
7526 Cerr << " dvol_reel_depl= " << dvol_reel_depl << finl
7527 << " dt= " << delta_t << finl;
7528#endif
7529 }
7531 maillage.changer_temps(temps);
7532
7533 if (collision_model_ && nb_particles_tot_>1)
7535
7536 maillage.compute_gravity_center_fa7();
7537}
7538
7539void Transport_Interfaces_FT_Disc::ajouter_contribution_saut_vitesse(DoubleTab& deplacement, const bool la_roue_de_vitesse_a_deja_tournee) const
7540{
7541 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
7542 const Champ_base *u0_ptr = 0;
7543
7544 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
7545 {
7546 // assert(la_roue_de_vitesse_a_deja_tournee); // TODO : supprimer le param car il n'est jamais usite en false
7547 // Je ne vois pas qui tourne le roue pour delta_u??? // TODO Supprimer le champ_inc
7548 // On recupere le saut de vitesse a l'interface (changement de phase)
7549 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
7550 u0_ptr = ns.get_delta_vitesse_interface();
7551 if (u0_ptr)
7552 {
7553 const Champ_base& u0 = *u0_ptr;
7554 DoubleTabFT d2(deplacement);
7555 // If ns.get_new_mass_source() == 0, we use a standard multi-linear interpolation.
7556 // If ns.get_new_mass_source() == 1, we use the new method (1D-interpolation of each velocity component in its direction)
7559 d2, 1 /* recalculer le champ de vitesse L2 */,
7560 1-ns.get_new_mass_source(),
7561 la_roue_de_vitesse_a_deja_tournee);
7562
7563 const int n = d2.dimension(0);
7564 const int dim = d2.line_size();
7565 for (int i = 0; i < n; i++)
7566 {
7567 for (int j = 0; j < dim; j++)
7568 {
7569 const double depl2 = d2(i,j);
7570 deplacement(i,j) -= depl2;
7571 }
7572 }
7573 }
7574 }
7575}
7576
7578{
7579 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
7580 const DoubleTab& indicatrice = get_indicatrice().valeurs();
7581 const int nb_compo = topologie_interface().calculer_composantes_connexes_pour_suppression(domaine_vf, indicatrice, num_compo);
7582 return nb_compo;
7583}
7584
7585double Transport_Interfaces_FT_Disc::suppression_interfaces(const IntVect& num_compo, const ArrOfInt& flags_compo_a_supprimer)
7586{
7588 const double volume = topologie_interface().suppression_interfaces(num_compo,
7589 flags_compo_a_supprimer, maillage,
7590 variables_internes_->indicatrice_cache->valeurs());
7591 return volume;
7592}
7593
7595{
7596 bool indic_updated = false;
7598 return false;
7599
7600 const Sous_Domaine& sous_domaine = domaine_dis().domaine().ss_domaine(suppression_interfaces_sous_domaine_);
7602 indic_updated = true;
7603 const DoubleTab& indicatrice = get_indicatrice().valeurs();
7604 // Construction de la liste des elements de la sous-domaine contenant la phase a supprimer
7605 ArrOfInt liste_elems_sous_domaine;
7606 int i;
7607 const double phase_continue = topologie_interface().get_phase_continue();
7608
7609 const int nb_elems_sous_domaine = sous_domaine.nb_elem_tot();
7610 for (i = 0; i < nb_elems_sous_domaine; i++)
7611 {
7612 const int i_elem = sous_domaine[i];
7613 const double indic = indicatrice[i_elem];
7614 if (indic != phase_continue)
7615 liste_elems_sous_domaine.append_array(i_elem);
7616 }
7617 const int sz_liste_elems_sous_domaine = liste_elems_sous_domaine.size_array();
7618 if (mp_sum(sz_liste_elems_sous_domaine) > 0)
7619 {
7620 IntVect num_compo;
7621 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
7622 const int nb_compo = topologie_interface().calculer_composantes_connexes_pour_suppression(domaine_vf, indicatrice, num_compo);
7623 // Tableau initialise a zero:
7624 ArrOfInt flags_compo_a_supprimer(nb_compo);
7625 for (i = 0; i < sz_liste_elems_sous_domaine; i++)
7626 {
7627 const int elem = liste_elems_sous_domaine[i];
7628 const int compo = num_compo[elem];
7629 flags_compo_a_supprimer[compo] = 1;
7630 }
7631 mp_sum_for_each_item(flags_compo_a_supprimer);
7633 topologie_interface().suppression_interfaces(num_compo, flags_compo_a_supprimer, maillage,
7634 variables_internes_->indicatrice_cache->valeurs());
7635
7636 if (max_array(flags_compo_a_supprimer))
7637 {
7639 indic_updated = true;
7640 // Parcours de toutes les equations du probleme,
7641 // Pour les equations "temperature FT" on appelle la methode "suppression_interfaces"
7642 Probleme_base& pb = probleme();
7643 const int n = pb.nombre_d_equations();
7644 for (int ii = 0; ii < n; ii++)
7645 {
7646 Equation_base& eq = pb.equation(ii);
7648 {
7651 const int i_phase_continue = (phase_continue < 0.5) ? 0 : 1;
7652 eq_temp.suppression_interfaces(num_compo, flags_compo_a_supprimer,
7653 i_phase_continue /* phase qui remplace l'ancienne */);
7654 }
7655 }
7656 }
7657 }
7658 return indic_updated;
7659}
7660
7661//Integration des trajectoires de particules
7662// La methode est une version simplifiee de deplacer_maillage_ft_v_fluide(...)
7663// -Interpolation du champ de vitesse de l equation de qdm
7664// -Calcul du deplacement a appliquer aux particules
7665// -Transport des particules en fonction du deplacement calcule
7666// -Mise a jour du temps de l objet ensemble de points meme si t<t_debut_integr
7667// Rq : t_debut_integr est fixe par defaut a t_init mais peut etre specifie par l utilisateur
7669{
7670 Cerr<<"The method Transport_Interfaces_FT_Disc::integrer_ensemble_lagrange"<<finl;
7671 Cerr<<"must be overloaded."<<finl;
7672 Process::exit();
7673}
7674
7676{
7677 Process::Journal() << "Transport_Interfaces_FT_Disc::mettre_a_jour " << le_nom() << " temps= "<< temps << finl;
7678 // Effectue le deplacement de l'interface:
7679 bool is_indic_up_to_date = mettre_a_jour_deplacement(temps);
7680
7681 // Remaillage de l'interface:
7682 const int mtag = maillage_interface().get_mesh_tag();
7684 // L'indicatrice ne peut etre "encore" a jour a l'issu du remaillage que si celui-ci n'a pas change le mesh_tag!
7685 is_indic_up_to_date = (mtag == maillage_interface().get_mesh_tag()) && is_indic_up_to_date;
7686
7687 // Effectue la mise a jour de l'inconnue, des indicatrices et de tous les champs auxiliaires:
7688 bool update_indic = !is_indic_up_to_date;
7689 mettre_a_jour_hors_deplacement(temps, true, update_indic);
7690}
7691
7693{
7694 deplacer_maillage(temps);
7695 bool is_indicatrice_up_to_date = injecter_supprimer_interfaces(temps);
7696 return is_indicatrice_up_to_date;
7697}
7698
7700{
7702 switch (variables_internes_->methode_transport)
7703 {
7705 {
7706 deplacer_maillage_ft_v_impose(variables_internes_->expression_vitesse_imposee, maillage, temps);
7707 break;
7708 }
7710 {
7712 break;
7713 }
7715 {
7716 // Le deplacement de l'interface est donne par l'expression de la loi horaire
7717 const double dt = temps - maillage.temps();
7718 // Le temps auquel est evalue la vitesse:
7719 // pour obtenir un deplacement precis a l'ordre 2, on evalue la vitesse au temps suivant:
7720 const double t = maillage.temps() + dt * 0.5;
7722 {
7723 Cerr << "Transport_Interfaces_FT_Disc::mettre_a_jour imposed motion by a time law at t:" << t << finl;
7724 }
7725 const int nb_sommets = maillage.nb_sommets();
7726 DoubleTabFT deplacement(nb_sommets, Objet_U::dimension);
7727
7728 const DoubleTab& sommets = maillage.sommets();
7729
7730 const int dim = Objet_U::dimension;
7731 ArrOfDouble coord(dim);
7732 ArrOfDouble coord_barycentre(dim); // Coordonnes du barycentre des points de l'interface
7733 int nb_sommets_reels=0;
7734 for (int i = 0; i < nb_sommets; i++)
7735 {
7736 // Determination si le sommet de l'interface est reel ou virtuel
7737 int est_un_sommet_reel=0;
7738 if (!maillage.sommet_virtuel(i))
7739 {
7740 nb_sommets_reels++;
7741 est_un_sommet_reel=1;
7742 }
7743 // Coordonnees coord du ieme sommet de l'interface a l'instant t
7744 for (int j = 0; j < dim; j++)
7745 {
7746 double pos = sommets(i, j);
7747 coord[j] = pos;
7748 if (est_un_sommet_reel)
7749 coord_barycentre[j] += pos;
7750 }
7751 // Calcul de ses nouvelles coordonnees a t+dt
7752 coord = variables_internes_->loi_horaire_->position(t+dt,t,coord);
7753
7754 // Calcul du tableau deplacement
7755 for (int j = 0; j < dim; j++)
7756 deplacement(i, j) = coord[j] - sommets(i,j);
7757 }
7758 // Calcul du barycentre des noeuds de l'interface
7759 // en tenant compte du parallelisme
7760 nb_sommets_reels=Process::check_int_overflow(mp_sum(nb_sommets_reels));
7761 /* for (int j = 0; j < dim; j++)
7762 {
7763 coord_barycentre(j)=mp_sum(coord_barycentre(j))/nb_sommets_reels;
7764 } */
7765 mp_sum_for_each_item(coord_barycentre);
7766 for (int j = 0; j < dim; j++)
7767 {
7768 coord_barycentre[j]=coord_barycentre[j]/nb_sommets_reels;
7769 }
7770 // Impression eventuelle de la loi horaire et du centre de gravite "discret" de l'interface
7771 if (schema_temps().limpr())
7772 variables_internes_->loi_horaire_->imprimer(schema_temps(),coord_barycentre);
7773
7774 maillage.transporter(deplacement);
7775 maillage.nettoyer_elements_virtuels();
7776 maillage.completer_maillage();
7777 maillage.changer_temps(temps);
7778 break;
7779 }
7780 default:
7781 Cerr << "Error for the method Transport_Interfaces_FT_Disc::mettre_a_jour :\n"
7782 << " the requested transport mehod is not developped" << finl;
7783 Process::exit();
7784 }
7785}
7786
7788{
7790 maillage.nettoyer_elements_virtuels();
7791 maillage.completer_maillage();
7792 maillage.changer_temps(temps);
7793}
7794
7796{
7797 bool indic_updated = injecter_interfaces_par_ajout_phase(temps);
7798 indic_updated = injecter_interfaces_pour_TCL(temps) || indic_updated;
7799
7800// Traitement des domaines de suppression
7801 indic_updated = test_suppression_interfaces_sous_domaine() || indic_updated;
7802 return indic_updated;
7803}
7804
7806{
7807 bool indic_updated = false;
7808 // injection des interfaces
7809 if (variables_internes_->injection_interfaces_temps_.size_array() > 0)
7810 {
7811 const ArrOfDouble& tps = variables_internes_->injection_interfaces_temps_;
7812 const int n = tps.size_array();
7813 const Noms& expr = variables_internes_->injection_interfaces_expressions_;
7814 assert(expr.size() == n);
7815 // Recherche du prochain temps d'injection:
7816 const double last_time = variables_internes_->injection_interfaces_last_time_;
7817 int i;
7818 for (i = 0; i < n; i++)
7819 if (tps[i] > last_time)
7820 break;
7821 for (; i < n && tps[i] <= temps; i++)
7822 {
7823 variables_internes_->injection_interfaces_last_time_=tps[i];
7824 // On essaye d'injecter l'interface
7825 Maillage_FT_Disc maillage_tmp;
7826 maillage_tmp.associer_equation_transport(*this);
7827 Maillage_FT_Disc::AjoutPhase phase = variables_internes_->injection_interfaces_phase_[i]
7829 DoubleTab sauvegarde(variables_internes_->indicatrice_cache->valeurs());
7830 const int ok = marching_cubes().construire_iso(expr[i],
7831 0., maillage_tmp,
7832 variables_internes_->indicatrice_cache->valeurs(),
7833 phase,
7834 variables_internes_->distance_interface_sommets);
7835
7836
7837
7838 Cerr << "Injection_interface time " << temps << " " << expr[i];
7839 if (ok)
7840 {
7841 maillage_interface().ajouter_maillage(maillage_tmp);
7843 indic_updated = true;
7844 double unused_vol_phase_0 = 0.;
7845 const double volume_phase_1_old = calculer_integrale_indicatrice(sauvegarde, unused_vol_phase_0);
7846 unused_vol_phase_0= 0.;
7847 const double volume_phase_1 = calculer_integrale_indicatrice(variables_internes_->indicatrice_cache->valeurs(), unused_vol_phase_0);
7848 double volume = volume_phase_1-volume_phase_1_old;
7849 // pow(-1,1-phase) ne compile pas avec xlC sur AIX car n'a que pow(double,int)
7850 volume*=pow(-1.,1-phase);
7851 Cerr << " volume " << volume << finl;
7852 }
7853 else
7854 {
7855 Cerr << " failure: collision" << finl;
7856 variables_internes_->indicatrice_cache->valeurs() = sauvegarde;
7857 indic_updated = false;
7858 }
7859 }
7860 if (i == n)
7861 {
7862 Cerr << "The injection list is fulfilled !"
7863 << " (if it is wished, add an interface at a large time in the file)"
7864 << finl;
7865 barrier();
7866 Process::exit();
7867 }
7868 }
7869 return indic_updated;
7870}
7871
7873{
7874 bool indic_updated = false;
7875 Probleme_base& pb = probleme();
7876 if (sub_type(Probleme_FT_Disc_gen,pb))
7877 {
7878 Probleme_FT_Disc_gen& pb_ft = ref_cast_non_const(Probleme_FT_Disc_gen, pb);
7879 // injection des interfaces with temperature of activation
7880 if (pb_ft.tcl().reinjection_tcl() && pb_ft.tcl().ready_inject_tcl())
7881 {
7882 const double thetac = pb_ft.tcl().thetaC_tcl();
7883 const double Rc = pb_ft.tcl().Rc_inject();
7884
7885 // const Nom expr = "x^2+(y-8e-05*cos(50.0*pi/180.0))^2-8e-05^2";
7886 const Nom expr = Nom("x^2+(y-") + Nom(Rc)
7887 + Nom("*cos(") + Nom(thetac)
7888 + Nom("*pi/180.0))^2-") + Nom(Rc)
7889 + Nom("^2");
7890
7891 // On essaye d'injecter l'interface
7892 Maillage_FT_Disc maillage_tmp;
7893 maillage_tmp.associer_equation_transport (*this);
7894
7895 // By default, inject vapeur, phase 0
7897 0 ?
7899
7900 DoubleTab sauvegarde (
7901 variables_internes_->indicatrice_cache.valeur ().valeurs ());
7902
7903 const int ok = marching_cubes ().construire_iso (
7904 expr, 0., maillage_tmp,
7905 variables_internes_->indicatrice_cache.valeur ().valeurs (), phase,
7906 variables_internes_->distance_interface_sommets);
7907
7908 Cerr << "Injection_interface time " << temps << " " << expr;
7909 if (ok)
7910 {
7911 maillage_interface().ajouter_maillage (maillage_tmp);
7913 indic_updated = true;
7914 double unused_vol_phase_0 = 0.;
7915 const double volume_phase_1_old = calculer_integrale_indicatrice (
7916 sauvegarde, unused_vol_phase_0);
7917 unused_vol_phase_0 = 0.;
7918 const double volume_phase_1 = calculer_integrale_indicatrice (
7919 variables_internes_->indicatrice_cache.valeur ().valeurs (),
7920 unused_vol_phase_0);
7921 double volume = volume_phase_1 - volume_phase_1_old;
7922 // pow(-1,1-phase) ne compile pas avec xlC sur AIX car n'a que pow(double,int)
7923 volume *= pow (-1., 1 - phase);
7924 Cerr << " volume " << volume << finl;
7925
7926 Schema_Temps_base& sch_tps = schema_temps();
7927 const double t_present_ = sch_tps.temps_courant();
7928 double& t_injection_ = pb_ft.tcl().t_injection();
7929 t_injection_ = t_present_;
7930 }
7931 else
7932 {
7933 Cerr << " failure: collision" << finl;
7934 variables_internes_->indicatrice_cache.valeur ().valeurs () =
7935 sauvegarde;
7936 indic_updated = false;
7937 }
7938 }
7939 }
7940
7941 // PARA re_injection bublle seed
7942 const int n = pb.nombre_d_equations();
7943 for (int ii = 0; ii < n; ii++)
7944 {
7945 Equation_base& eq = pb.equation(ii);
7947 {
7950
7951
7952 if (eq_temp.is_reinject_activated() && eq_temp.ready_injection())
7953 {
7954 const double thetac = eq_temp.get_thetaC();
7955 const double Rc = eq_temp.get_Rc_inject();
7956
7957 // const Nom expr = "x^2+(y-8e-05*cos(50.0*pi/180.0))^2-8e-05^2";
7958 const Nom expr = Nom("x^2+(y-") + Nom(Rc)
7959 + Nom("*cos(") + Nom(thetac)
7960 + Nom("*pi/180.0))^2-") + Nom(Rc)
7961 + Nom("^2");
7962
7963 // On essaye d'injecter l'interface
7964 Maillage_FT_Disc maillage_tmp;
7965 maillage_tmp.associer_equation_transport (*this);
7966
7967 // By default, inject vapeur, phase 0
7969 0 ?
7971
7972 DoubleTab sauvegarde (
7973 variables_internes_->indicatrice_cache.valeur ().valeurs ());
7974
7975 const int ok = marching_cubes ().construire_iso (
7976 expr, 0., maillage_tmp,
7977 variables_internes_->indicatrice_cache.valeur ().valeurs (), phase,
7978 variables_internes_->distance_interface_sommets);
7979
7980 Cerr << "Injection_interface time " << temps << " " << expr;
7981 if (ok)
7982 {
7983 maillage_interface().ajouter_maillage (maillage_tmp);
7985 indic_updated = true;
7986 double unused_vol_phase_0 = 0.;
7987 const double volume_phase_1_old = calculer_integrale_indicatrice (
7988 sauvegarde, unused_vol_phase_0);
7989 unused_vol_phase_0 = 0.;
7990 const double volume_phase_1 = calculer_integrale_indicatrice (
7991 variables_internes_->indicatrice_cache.valeur ().valeurs (),
7992 unused_vol_phase_0);
7993 double volume = volume_phase_1 - volume_phase_1_old;
7994 // pow(-1,1-phase) ne compile pas avec xlC sur AIX car n'a que pow(double,int)
7995 volume *= pow (-1., 1 - phase);
7996 Cerr << " volume " << volume << finl;
7997 const Probleme_base& pb2 = get_probleme_base();
7998 if (sub_type(Probleme_FT_Disc_gen,pb2))
7999 {
8000 Probleme_FT_Disc_gen& pb_ft = ref_cast_non_const(Probleme_FT_Disc_gen, pb);
8001 // injection des interfaces with temperature of activation
8002 if (pb_ft.tcl().lissage_tcl())
8003 {
8004 Schema_Temps_base& sch_tps = schema_temps();
8005 const double t_present_ = sch_tps.temps_courant();
8006 double& t_injection_ = pb_ft.tcl().t_injection();
8007 t_injection_ = t_present_;
8008 }
8009 }
8010 }
8011 else
8012 {
8013 Cerr << " failure: collision" << finl;
8014 variables_internes_->indicatrice_cache.valeur ().valeurs () =
8015 sauvegarde;
8016 indic_updated = false;
8017 }
8018 }
8019
8020 }
8021 }
8022 return indic_updated;
8023}
8024
8025void Transport_Interfaces_FT_Disc::mettre_a_jour_hors_deplacement(double temps, const bool update_statio
8026 , const bool update_indic)
8027{
8028 // The Eulerian fields normal and distance should be updated first (before indicatrice!!)
8029 // because the indicatrice calculation partly relies on the distance calculation.
8030 // Update normal and distance and indicatrice
8031 // Attention: get_indicatrice renvoie une ref a indicatrice_cache.
8032 // C'est ici qu'on copie le contenu de indicatrice_cache dans indicatrice :
8033 if (update_indic)
8035 // TODO GB 2024 : mettre_a_jour ferait un echange_EV en plus de changer temps. Mais l'echange EV est deja fait dans le update donc pas necessaire.
8036 variables_internes_->distance_interface->changer_temps(temps);
8037 variables_internes_->normale_interface->changer_temps(temps);
8038 indicatrice_->valeurs() = get_indicatrice().valeurs();
8039
8040 variables_internes_->indicatrice_cache->changer_temps(temps);
8041 indicatrice_->changer_temps(temps);
8042
8043 if (update_statio)
8045
8046 // Beaucoup de monde utilise l'indic aux faces. On la calcule tout le temps (tant pis si c'est pas perf-ideal)
8048 indicatrice_faces_->changer_temps(temps);
8049 // TODO: GB2024
8050 // if (???) variables_internes_->vitesse_filtree.changer_temps(temps);
8051 // if (???) variables_internes_->tmp_flux.changer_temps(temps);
8052 // if (???) variables_internes_->index_element.changer_temps(temps);
8053 // if (???) variables_internes_->nelem_par_direction.changer_temps(temps);
8054 // if (???) variables_internes_->distance_interface_faces.changer_temps(temps);
8055 // if (???) variables_internes_->distance_interface_faces_corrigee.changer_temps(temps);
8056 // if (???) variables_internes_->distance_interface_faces_difference.changer_temps(temps);
8057 // if (???) vitesse_imp_interp_.changer_temps(temps);
8058
8059 {
8060 double volume_phase_0 = 0.;
8061 const double volume_phase_1 = calculer_integrale_indicatrice(indicatrice_->valeurs(), volume_phase_0);
8063 {
8064 Cerr << "Volume_phase_0 " << Nom(volume_phase_0, "%20.14g") << " time " << temps << finl;
8065 Cerr << "Volume_phase_1 " << Nom(volume_phase_1, "%20.14g") << " time " << temps << finl;
8066 }
8067 }
8068
8070 // Affichage de la surface totale d'interfaces dans le fichier .err
8071 // Affichage du centre de gravite des phases 0 et 1
8072 {
8073 // Calcul de la somme des surfaces des facettes reelles:
8074 //const Maillage_FT_Disc& maillage = maillage_interface();
8075 const ArrOfDouble& surfaces = maillage.get_update_surface_facettes();
8076 const int nb_facettes = maillage.nb_facettes();
8077 double s = 0.;
8078 int i;
8079 for (i = 0; i < nb_facettes; i++)
8080 {
8081 const int virt = maillage.facette_virtuelle(i);
8082 if (! virt)
8083 s += surfaces[i];
8084 }
8085 const double s_tot = mp_sum(s);
8087 {
8088 Cerr << "Surface_Totale_Interface " << le_nom()
8089 << " t= " << temps << " surface= " << s_tot << finl;
8090 }
8091 // Calcul du centre de gravite des phases 0 et 1 a partir de l'indicatrice
8092 // indicatrice de phase:
8093 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
8094 const DoubleTab& indic = indicatrice_->valeurs();
8095 // centre de gravite des elements euleriens:
8096 const DoubleTab& xp = domaine_vf.xp();
8097 // volumes des elements euleriens:
8098 const DoubleVect& volumes = domaine_vf.volumes();
8099
8100 const int nb_elem = domaine_vf.nb_elem();
8101 const int dim = xp.line_size();
8102 DoubleTrav values(3,dim);
8103 values=0.;
8104 // somme des volumes des phases:
8105// v0_tot -> values(2,0)
8106// v1_tot -> values(2,1)
8107 // centre de gravite de la phase 0:
8108// g0[j] -> values(0,j)
8109 // phase 1:
8110// g1[j] -> values(1,j)
8111 assert(indic.dimension(0) == nb_elem); // indicatrice aux elements
8112 // Boucle sur les elements reels
8113 for (i = 0; i < nb_elem; i++)
8114 {
8115 const double ind = indic(i);
8116 const double v = volumes(i);
8117 const double v1 = ind * v;
8118 const double v0 = (1. - ind) * v;
8119 values(2,0) += v0;
8120 values(2,1) += v1;
8121 int j;
8122 for (j = 0; j < dim; j++)
8123 {
8124 const double x = xp(i,j);
8125 values(0,j) += v0 * x;
8126 values(1,j) += v1 * x;
8127 }
8128 }
8129 // Somme sur tous les processeurs et calcul du centre de gravite
8130 double mp_g0[3] = {0., 0., 0.};
8131 double mp_g1[3] = {0., 0., 0.};
8132
8133 mp_sum_for_each_item(values);
8134 {
8135 int j;
8136 /* mp_vtot0 = mp_sum(v0_tot);
8137 mp_vtot1 = mp_sum(v1_tot);
8138 if (mp_vtot0 > 0.)
8139 for (j = 0; j < dim; j++)
8140 mp_g0[j] = mp_sum(g0[j]) / mp_vtot0;
8141 if (mp_vtot1 > 0.)
8142 for (j = 0; j < dim; j++)
8143 mp_g1[j] = mp_sum(g1[j]) / mp_vtot1; */
8144 if (values(2,0) > 0.)
8145 {
8146 {
8147 for ( j = 0; j<dim; j++)
8148 mp_g0[j] = values(0,j) / values(2,0);
8149 }
8150 if (values(2,1) > 0.)
8151 for ( j = 0; j<dim; j++)
8152 mp_g1[j] = values(1,j) / values(2,1);
8153 }
8154 }
8155 // Affichage
8156 if (je_suis_maitre())
8157 {
8158 Cerr << "Centre_gravite_phases " << le_nom() << " t= " << temps;
8159 Cerr << " phase0: " << mp_g0[0] << " " << mp_g0[1] << " " << mp_g0[2] ;
8160 Cerr << " phase1: " << mp_g1[0] << " " << mp_g1[1] << " " << mp_g1[2] << finl;
8161 }
8162 }
8163 //GB : Calcul de la surface d'interfaces par element
8164 {
8165 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
8166 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
8167 const ArrOfInt& index_elem = intersections.index_elem();
8168 DoubleTab& surface = variables_internes_->surface_interface->valeurs();
8169 const int nb_elements = surface.dimension(0);
8170 for (int element = 0; element < nb_elements; element++)
8171 {
8172 int index = index_elem[element];
8173 double surface_totale = 0.;
8174 // Boucle sur les faces qui traversent l'element:
8175 while (index >= 0)
8176 {
8177 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
8178 surface_totale += data.fraction_surface_intersection_ * surface_facettes[data.numero_facette_];
8179 index = data.index_facette_suivante_;
8180 }
8181 surface[element] = surface_totale;
8182 }
8183 surface.echange_espace_virtuel();
8184 variables_internes_->surface_interface->mettre_a_jour(temps);
8185 }
8186 // Fin de GB
8187
8188 //TF : Gestion de l avancee en temps de la derivee
8190 //Fin de TF
8192 {
8193 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
8194 if (sub_type(Navier_Stokes_FT_Disc,eqn_hydraulique))
8195 {
8196 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
8197 ns.compute_particles_eulerian_id_number(collision_model_);
8199 }
8200
8201 // the mesh has changed, we need to recompute the data located to the fa7
8202 post_process_hydro_forces_.drop_the_flag();
8203 post_process_hydro_forces_Stokes_.drop_the_flag();
8204 post_process_hydro_forces_.drop_the_flag_heat_transfer();
8205
8206 if (schema_temps().limpr())
8207 {
8209 if (post_process_hydro_forces_.get_is_compute_forces())
8210 post_process_hydro_forces_.compute_hydrodynamic_forces();
8211 if (post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
8212 post_process_hydro_forces_Stokes_.compute_hydrodynamic_forces();
8213 if (post_process_hydro_forces_.get_is_compute_heat_transfer())
8214 post_process_hydro_forces_.compute_heat_transfer();
8215 }
8216
8217 }
8218
8219}
8220
8221// Deplace les sommets de l'interface du deplacement prescrit (vitesse * coeff)
8222// ou coeff est homogene a un temps en secondes.
8223// On met a jour le tableau vitesse en fonction des sommets qui sont
8224// passes d'un processeur a l'autre.
8225void Transport_Interfaces_FT_Disc::transporter_sans_changement_topologie(DoubleTab& vitesse, const double coeff,const double temps)
8226{
8228 DoubleTabFT deplacement(vitesse);
8229 deplacement *= coeff;
8230
8231 maillage.preparer_tableau_avant_transport(vitesse,
8232 maillage.desc_sommets());
8233
8234 maillage.transporter(deplacement);
8235
8236 // attention, creation de sommets virtuels... on fait update_...
8237 // seulement a la fin.
8238 maillage.parcourir_maillage();
8239
8240 maillage.update_tableau_apres_transport(vitesse,
8241 maillage.nb_sommets(),
8242 maillage.desc_sommets());
8243 //ajout pour postraiter ss pas de tps RK3_FT
8244 maillage.changer_temps(temps);
8246 indicatrice_->valeurs()=get_indicatrice().valeurs();
8247 variables_internes_->indicatrice_cache->changer_temps(temps);
8248 indicatrice_->changer_temps(temps);
8249 variables_internes_->distance_interface->changer_temps(temps);
8250 variables_internes_->normale_interface->changer_temps(temps);
8251}
8252
8253
8254// ************************************************************************
8255// ************************************************************************
8256// Un tas de routines vides ou presque qui ne font rien ou pas grand chose
8257// ************************************************************************
8258// ************************************************************************
8259
8261{
8262 // Si on veut creer un probleme contenant uniquement une equation Transport,
8263 // il faut un milieu sinon ca plante dans pb_base::discretiser !
8264 ref_milieu_ = un_milieu;
8265}
8266
8268{
8269 equation_ns_=ns;
8270}
8271
8273{
8274 if (!ref_milieu_)
8275 {
8276 Cerr << "You forgot to associate the diphasic fluid to the problem named " << probleme().le_nom() << finl;
8277 Process::exit();
8278 }
8279 return ref_milieu_.valeur();
8280}
8281
8283{
8284 if (!ref_milieu_)
8285 {
8286 Cerr << "You forgot to associate the diphasic fluid to the problem named " << probleme().le_nom() << finl;
8287 Process::exit();
8288 }
8289 return ref_milieu_.valeur();
8290}
8291
8293{
8294 return 0;
8295}
8296
8298{
8299 assert(0);
8300 Process::exit();
8301 throw;
8302}
8303
8305{
8306 assert(0);
8307 Process::exit();
8308 throw;
8309}
8310
8312{
8313 return indicatrice_;
8314}
8315
8317{
8318 return indicatrice_;
8319}
8320
8322{
8323 return variables_internes_->marching_cubes_;
8324}
8325
8327{
8328 return variables_internes_->marching_cubes_;
8329}
8330
8332{
8333 return variables_internes_->maillage_interface;
8334}
8335
8337{
8338 return variables_internes_->maillage_interface;
8339}
8341{
8342 return variables_internes_->remaillage_interface_;
8343}
8344
8346{
8347 return variables_internes_->remaillage_interface_;
8348}
8350{
8351 return variables_internes_->topologie_interface_;
8352}
8353
8355{
8356 return variables_internes_->topologie_interface_;
8357}
8358
8360{
8361 return variables_internes_->doubletab_pos;
8362}
8363
8365{
8366 return variables_internes_->intvect_elements;
8367}
8368
8370{
8371 return variables_internes_->deplacement_sommets;
8372}
8373
8375{
8376 return variables_internes_->proprietes_particules_;
8377}
8378
8380{
8381 return variables_internes_->proprietes_particules_;
8382}
8383
8385{
8386 return variables_internes_->maillage_inject_;
8387}
8388
8390{
8391 return variables_internes_->maillage_inject_;
8392}
8393
8395{
8396 return variables_internes_->proprietes_inject_;
8397}
8398
8400{
8401 return variables_internes_->proprietes_inject_;
8402}
8403
8405{
8406 proprietes_particules().nettoyer(som_utilises);
8407}
8408
8409/*! @brief for PDI IO: retrieve name and type and dimensions of the indicatrice tag
8410 *
8411 */
8413{
8414 std::vector<YAML_data> data = Equation_base::data_a_sauvegarder();
8415 std::vector<YAML_data> dvi = variables_internes_->data_a_sauvegarder();
8416 data.insert(data.end(), dvi.begin(), dvi.end());
8417 return data;
8418}
8419
8420/*! @brief
8421 *
8422 */
8424{
8425 int bytes = Equation_base::sauvegarder(os);
8426 {
8427 int special, afaire;
8428 const int format_xyz = EcritureLectureSpecial::is_ecriture_special(special, afaire);
8429 double temps=inconnue().temps();
8430 Nom mon_ident("variables_internes_transport");
8431 mon_ident += Nom(temps,"%e");
8432 variables_internes_->set_time(temps);
8433 if (format_xyz)
8434 {
8436 {
8437 os << mon_ident << finl;
8438 os << variables_internes_->que_suis_je() << finl;
8439 }
8440 }
8442 {
8443 os << mon_ident << finl;
8444 os << variables_internes_->que_suis_je() << finl;
8445 }
8446 bytes += variables_internes_->sauvegarder(os);
8448 {
8449 Cerr << "Backup of collision model" << finl;
8450 if (collision_model_) bytes += collision_model_.valeur().sauvegarder(os);
8451 // we save particles position and velocity as these data
8452 // are required for the computation of contact forces
8453 Cerr << "Backup of particles position and velocity" << finl;
8454 if (format_xyz)
8455 {
8457 {
8458 for (int i=0; i<particles_position_collision_.dimension(0); i++)
8459 for (int j=0; j<particles_position_collision_.dimension(1); j++)
8461 for (int i=0; i<particles_velocity_collision_.dimension(0); i++)
8462 for (int j=0; j<particles_velocity_collision_.dimension(1); j++)
8464 }
8465 }
8467 {
8468 Cerr << "Backup of collision model not supported with pdi format" << finl;
8469 Process::exit();
8470 }
8471 else
8472 {
8474 bytes += 8 * particles_position_collision_.size_array();
8476 bytes += 8 * particles_velocity_collision_.size_array();
8477 }
8478 }
8479 }
8480 os.flush();
8481
8482 return bytes;
8483}
8484
8486{
8487 Cerr << "Transport_Interfaces_FT_Disc::reprendre" << finl;
8489 {
8491 {
8492 Nom id, type_name;
8493 is >> id >> type_name;
8494 if ( (! id.debute_par("variables_internes_transport"))
8495 || type_name != variables_internes_->que_suis_je())
8496 {
8497 Cerr << "Error for the method Transport_Interfaces_FT_Disc::reprendre" << finl;
8498 Cerr << variables_internes_->que_suis_je() <<" was expected."<< finl;
8499 Process::exit();
8500 }
8501 }
8502 variables_internes_->maillage_interface.associer_equation_transport(*this);
8503 const Nom& restart_fname = get_probleme_base().restart_filename();
8504 variables_internes_->set_restart_fname(restart_fname);
8505 variables_internes_->set_time(schema_temps().temps_courant());
8506 variables_internes_->reprendre(is);
8507 variables_internes_->injection_interfaces_last_time_ = schema_temps().temps_courant();
8509 {
8510 if (collision_model_) collision_model_.valeur().reprendre(is);
8511 const int nb_particles_tot=collision_model_.valeur().get_nb_particles_tot();
8512 particles_position_collision_.resize(nb_particles_tot,dimension);
8513 particles_velocity_collision_.resize(nb_particles_tot,dimension);
8514 const int format_xyz = EcritureLectureSpecial::is_lecture_special();
8515 if (format_xyz)
8516 {
8517 for (int i=0; i<particles_position_collision_.dimension(0); i++)
8518 for (int j=0; j<particles_position_collision_.dimension(1); j++)
8520 for (int i=0; i<particles_velocity_collision_.dimension(0); i++)
8521 for (int j=0; j<particles_velocity_collision_.dimension(1); j++)
8523 return 1;
8524 }
8525 else if (TRUST_2_PDI::is_PDI_restart())
8526 {
8527 Cerr << "Backup of collision model not supported with pdi format" << finl;
8528 Process::exit();
8529 }
8530 else
8531 {
8534 }
8535 const Domaine& domain = domaine_dis().domaine();
8537 }
8538 }
8539 return 1;
8540}
8541
8543{
8544 return probleme_base_.valeur();
8545}
8546
8548{
8549 return variables_internes_->parcours_interface_;
8550}
8551
8553{
8554 return variables_internes_->connectivite_frontieres_;
8555}
8556
8558{
8559 return variables_internes_->algorithmes_transport_.valeur();
8560}
8561
8562
8563void Transport_Interfaces_FT_Disc::fill_map_post_FT(Transport_Interfaces_FT_Disc::
8564 my_map& map_post, DoubleTab *ftab) const
8565{
8566 const Motcle som = "sommets";
8567 const Motcle elem = "elements";
8568 const Motcle bi = "elements et sommets";
8569 const DoubleTab dummytab;
8570
8571 map_post.emplace(Postraitement_base::demande_description, map_element_post_FT(bi,&Transport_Interfaces_FT_Disc::
8572 fill_ftab_vertices_curvature, ftab, dummytab));
8573 map_post.emplace("courbure", map_element_post_FT(som,&Transport_Interfaces_FT_Disc::
8574 fill_ftab_vertices_curvature, ftab, dummytab));
8575 map_post.emplace("vitesse", map_element_post_FT (som,&Transport_Interfaces_FT_Disc::
8576 fill_ftab_velocity, ftab, dummytab));
8577 map_post.emplace("vitesse_repere_local", map_element_post_FT (som,&Transport_Interfaces_FT_Disc::
8579 map_post.emplace("normale_unitaire", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8580 fill_ftab_normal_unit, ftab, dummytab));
8581 map_post.emplace("pressure", map_element_post_FT(elem,&Transport_Interfaces_FT_Disc::
8582 fill_ftab_pressure, ftab, dummytab));
8583 map_post.emplace("pressure_force", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8584 fill_ftab_pressure_force, ftab, dummytab));
8585 map_post.emplace("friction_force", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8586 fill_ftab_friction_force, ftab, dummytab));
8587
8588 map_post.emplace("sigma_xx", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8589 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_xx_fa7()));
8590 map_post.emplace("sigma_xy", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8591 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_xy_fa7()));
8592 map_post.emplace("sigma_xz", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8593 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_xz_fa7()));
8594 map_post.emplace("sigma_yx", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8595 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_yx_fa7()));
8596 map_post.emplace("sigma_yy", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8597 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_yy_fa7()));
8598 map_post.emplace("sigma_yz", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8599 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_yz_fa7()));
8600 map_post.emplace("sigma_zx", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8601 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_zx_fa7()));
8602 map_post.emplace("sigma_zy", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8603 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_zy_fa7()));
8604 map_post.emplace("sigma_zz", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8605 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_sigma_zz_fa7()));
8606 map_post.emplace("pressure_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8607 fill_ftab_Stokes_pressure_interp, ftab, dummytab));
8608 map_post.emplace("pressure_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8609 fill_ftab_Stokes_pressure_th, ftab, dummytab));
8610 map_post.emplace("pressure_force_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8612 map_post.emplace("pressure_force_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8614 map_post.emplace("friction_force_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8616 map_post.emplace("friction_force_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8618
8619 map_post.emplace("sigma_xx_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8620 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_xx_fa7()));
8621 map_post.emplace("sigma_xy_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8622 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_xy_fa7()));
8623 map_post.emplace("sigma_xz_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8624 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_xz_fa7()));
8625 map_post.emplace("sigma_yx_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8626 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_yx_fa7()));
8627 map_post.emplace("sigma_yy_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8628 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_yy_fa7()));
8629 map_post.emplace("sigma_yz_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8630 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_yz_fa7()));
8631 map_post.emplace("sigma_zx_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8632 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_zx_fa7()));
8633 map_post.emplace("sigma_zy_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8634 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_zy_fa7()));
8635 map_post.emplace("sigma_zz_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8636 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_sigma_zz_fa7()));
8637
8638 map_post.emplace("sigma_xx_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8640 map_post.emplace("sigma_xy_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8642 map_post.emplace("sigma_xz_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8644 map_post.emplace("sigma_yy_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8646 map_post.emplace("sigma_yz_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8648 map_post.emplace("sigma_zz_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8650
8651 map_post.emplace("dUdx_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8652 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdx_P1()));
8653 map_post.emplace("dUdy_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8654 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdy_P1()));
8655 map_post.emplace("dUdz_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8656 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdz_P1()));
8657 map_post.emplace("dVdx_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8658 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdx_P1()));
8659 map_post.emplace("dVdy_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8660 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdy_P1()));
8661 map_post.emplace("dVdz_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8662 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdz_P1()));
8663 map_post.emplace("dWdx_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8664 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdx_P1()));
8665 map_post.emplace("dWdy_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8666 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdy_P1()));
8667 map_post.emplace("dWdz_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8668 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdz_P1()));
8669
8670 map_post.emplace("dUdx_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8671 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdx_P2()));
8672 map_post.emplace("dUdy_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8673 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdy_P2()));
8674 map_post.emplace("dUdz_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8675 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dUdz_P2()));
8676 map_post.emplace("dVdx_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8677 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdx_P2()));
8678 map_post.emplace("dVdy_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8679 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdy_P2()));
8680 map_post.emplace("dVdz_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8681 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dVdz_P2()));
8682 map_post.emplace("dWdx_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8683 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdx_P2()));
8684 map_post.emplace("dWdy_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8685 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdy_P2()));
8686 map_post.emplace("dWdz_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8687 fill_ftab_scalar, ftab, post_process_hydro_forces_.get_dWdz_P2()));
8688
8689 map_post.emplace("dUdx_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8690 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P1()));
8691 map_post.emplace("dUdy_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8692 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdy_P1()));
8693 map_post.emplace("dUdz_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8694 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P1()));
8695 map_post.emplace("dVdx_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8696 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdx_P1()));
8697 map_post.emplace("dVdy_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8698 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdy_P1()));
8699 map_post.emplace("dVdz_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8700 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P1()));
8701 map_post.emplace("dWdx_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8702 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P1()));
8703 map_post.emplace("dWdy_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8704 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P1()));
8705 map_post.emplace("dWdz_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8706 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P1()));
8707
8708 map_post.emplace("dUdx_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8709 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P2()));
8710 map_post.emplace("dUdy_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8711 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdy_P2()));
8712 map_post.emplace("dUdz_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8713 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P2()));
8714 map_post.emplace("dVdx_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8715 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdx_P2()));
8716 map_post.emplace("dVdy_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8717 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdy_P2()));
8718 map_post.emplace("dVdz_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8719 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P2()));
8720 map_post.emplace("dWdx_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8721 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P2()));
8722 map_post.emplace("dWdy_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8723 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P2()));
8724 map_post.emplace("dWdz_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8725 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P2()));
8726
8727 map_post.emplace("dUdx_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8728 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P1_Stokes_th()));
8729 map_post.emplace("dUdz_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8730 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P1_Stokes_th()));
8731 map_post.emplace("dVdz_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8732 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P1_Stokes_th()));
8733 map_post.emplace("dWdx_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8734 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P1_Stokes_th()));
8735 map_post.emplace("dWdy_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8736 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P1_Stokes_th()));
8737 map_post.emplace("dWdz_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8738 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P1_Stokes_th()));
8739
8740 map_post.emplace("dUdx_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8741 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdx_P2_Stokes_th()));
8742 map_post.emplace("dUdz_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8743 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dUdz_P2_Stokes_th()));
8744 map_post.emplace("dVdz_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8745 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dVdz_P2_Stokes_th()));
8746 map_post.emplace("dWdx_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8747 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdx_P2_Stokes_th()));
8748 map_post.emplace("dWdy_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8749 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdy_P2_Stokes_th()));
8750 map_post.emplace("dWdz_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8751 fill_ftab_scalar, ftab, post_process_hydro_forces_Stokes_.get_dWdz_P2_Stokes_th()));
8752
8753 map_post.emplace("U_P1", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8754 fill_ftab_vector, ftab, post_process_hydro_forces_.get_U_P1()));
8755 map_post.emplace("U_P2", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8756 fill_ftab_vector, ftab, post_process_hydro_forces_.get_U_P2()));
8757 map_post.emplace("U_P1_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8758 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P1()));
8759 map_post.emplace("U_P2_Stokes_th_interp", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8760 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P2()));
8761 map_post.emplace("U_P1_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8762 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P1_Stokes_th()));
8763 map_post.emplace("U_P2_Stokes_th", map_element_post_FT (elem,&Transport_Interfaces_FT_Disc::
8764 fill_ftab_vector, ftab, post_process_hydro_forces_Stokes_.get_U_P2_Stokes_th()));
8765 map_post.emplace("heat_transfer", map_element_post_FT(elem, &Transport_Interfaces_FT_Disc::fill_ftab_scalar,
8767
8768}
8769
8770/*! @brief Cherche le champ discret aux interfaces dont le nom est "champ", et verifie qu'il peut etre postraite a la localisation demandee (loc).
8771 *
8772 * Si oui on renvoie 1 et, si ftab est non nul, on remplit le champ ftab
8773 * avec le champ demande.
8774 * Si non, on renvoie 0.
8775 * (la fonction est appelee avec ftab=0 lors de la lecture du postraitement,
8776 * car on n'a pas besoin de la valeur du champ, on veut seulement verifier
8777 * qu'il existe).
8778 *
8779 */
8781{
8782 int res = 1;
8783
8784 const Motcle som = "sommets"; // post-processing at the vertices only
8785 const Motcle elem = "elements"; // post-processing at the element only
8786 const Motcle bi = "elements et sommets"; // post-processing at both location
8787
8788 Transport_Interfaces_FT_Disc::my_map map_post;
8789 fill_map_post_FT(map_post,ftab);
8790
8791 Motcle the_key="key";
8792 Motcle the_loc="loc";
8793 map_element_post_FT::func_type the_function=&Transport_Interfaces_FT_Disc::fill_ftab_scalar;
8794 DoubleTab the_tab_values;
8795 bool elem_found=false;
8796
8797 // I didn't manage to use std::map::find properly, so I loop on map_post to find the element
8798 for (const auto& [key, value] : map_post)
8799 {
8800 if (key==champ)
8801 {
8802 the_key=key;
8803 the_loc=value.location_;
8804 the_function=value.function_;
8805 the_tab_values=value.values_;
8806 elem_found=true;
8807 break;
8808 }
8809 }
8810
8812 {
8813 Cerr<<"The real fields to be post-processed are :"<<finl;
8814 int i=0;
8815 for (const auto& [key, value] : map_post)
8816 {
8817 Cerr << " Fields("<<i<<") : " << key << ", Location : ";
8818
8819 Cerr << value.location_ << finl;
8820 i++;
8821 }
8822 res = 0;
8823 }
8824 else if (!elem_found) // existing field?
8825 res = 0; // inexisting field
8826 else if (! (the_loc==bi
8827 || (the_loc==som && loc==Postraitement_base::SOMMETS)
8828 || (the_loc==elem && loc==Postraitement_base::ELEMENTS)) ) // authorized location?
8829 res = 0; // unauthorized location
8830 else
8831 {
8832 if (ftab)
8833 {
8834 if(post_process_hydro_forces_.get_is_compute_forces())
8835 post_process_hydro_forces_.compute_hydrodynamic_forces();
8836 if(post_process_hydro_forces_.get_is_compute_forces_Stokes_th())
8837 post_process_hydro_forces_Stokes_.compute_hydrodynamic_forces();
8838 if (post_process_hydro_forces_.get_is_compute_heat_transfer())
8839 post_process_hydro_forces_.compute_heat_transfer();
8840 (this->*the_function)(ftab,the_tab_values);
8841 }
8842 res = 1;
8843 }
8844
8845 return res;
8846}
8847
8848/*! @brief Voir l'autre get_champ_post_FT.
8849 *
8850 * Cette fonction est specifique aux champs d'entiers.
8851 *
8852 */
8854{
8855 int res = 1;
8856
8857 const Motcle som = "sommets"; //postraitement possible uniquement aux sommets
8858 const Motcle elem = "elements"; //postraitement possible uniquement aux elements
8859 const Motcle bi = "elements et sommets"; //postraitement possible aux sommets et aux elements
8860 const int nb_champs = 5;
8861 Motcles fields(nb_champs);
8862 {
8864 fields[1] = "pe"; // PE owner
8865 fields[2] = "numero"; // numero local du sommet/element
8866 fields[3] = "pe_local"; // PE local
8867 fields[4] = "compo_connexe";
8868 }
8869 Motcles localisations(nb_champs);
8870 {
8871 localisations[0] = bi;
8872 localisations[1] = bi;
8873 localisations[2] = bi;
8874 localisations[3] = bi;
8875 localisations[4] = elem;
8876 }
8877
8878 int rank=fields.search(champ), i;
8879
8880 if (rank==0)
8881 {
8882 Cerr<<"The integer fields to be post-processed are:"<<finl;
8883 for (i=1 ; i<nb_champs ; i++)
8884 {
8885 Cerr << " Fields("<<i<<") : "<< fields[i] << " # Localisations : " << localisations[i] << finl;
8886 }
8887 res = 0;
8888 }
8889 else if (rank==-1)
8890 {
8891 //champ inexistant
8892 res = 0;
8893 }
8894 else if (! (localisations[rank]==bi
8895 || (localisations[rank]==som && loc==Postraitement_base::SOMMETS)
8896 || (localisations[rank]==elem && loc==Postraitement_base::ELEMENTS)) ) //test localisation autorisee ?
8897 {
8898 //localisation non autorisee
8899 res = 0;
8900 }
8901 else
8902 {
8903 if (itab) // Pointeur non nul : calculer le champ
8904 {
8905
8907 const int n =
8909 ? maillage.nb_sommets()
8910 : maillage.nb_facettes();
8911 int i2;
8912 itab->resize(n);
8913
8914 switch (rank )
8915 {
8916 case 1:
8917 {
8919 {
8920 //TMP : tant que IntTabFt et IntTab n'ont pas fusionne :
8921 //*itab = maillage_interface_->sommet_PE_owner();
8922 const ArrOfInt& pe_som = maillage.sommet_PE_owner();
8923 for (i2=0 ; i2<n ; i2++)
8924 {
8925 (*itab)(i2) = pe_som[i2];
8926 }
8927 }
8928 else
8929 {
8930 ArrOfIntFT pe_fac;
8931 maillage.facette_PE_owner(pe_fac);
8932 for (i2=0 ; i2<n ; i2++)
8933 {
8934 (*itab)(i2) = pe_fac[i2];
8935 }
8936 }
8937 break;
8938 }
8939 case 2:
8940 {
8941 for (i2=0 ; i2<n ; i2++)
8942 {
8943 (*itab)(i2) = i2;
8944 }
8945 break;
8946 }
8947 case 3:
8948 {
8949 (*itab) = Process::me();
8950 break;
8951 }
8952 case 4:
8953 {
8954 maillage.intersections_elem_facettes();
8955 ArrOfIntFT compo(maillage.nb_facettes());
8956 compo = 0;
8957 int n2 = search_connex_components_local_FT(maillage, compo);
8958 compute_global_connex_components_FT(maillage, compo, n2);
8959 const int nbf = maillage.nb_facettes();
8960 for (int ii = 0; ii < nbf; ii++)
8961 (*itab)[ii] = compo[ii];
8962
8963 break;
8964 }
8965 default:
8966 Cerr << "Transport_Interfaces_FT_Disc::get_champ_post_FT : unexpected case" << finl;
8967 assert(0);
8968 Process::exit();
8969 }
8970 }
8971 }
8972 return res;
8973}
8974
8975/*! @brief Renvoie le maillage stocke specialement pour le postraitement (si on veut postraiter un etat intermediaire.
8976 *
8977 * ..)
8978 *
8979 */
8981{
8982 //return variables_internes_->maillage_pour_post;
8983 return maillage_interface();
8984}
8985
8987{
8988 return variables_internes_->n_iterations_distance;
8989}
8990
8991
8992/*! @brief Renvoi de la distance signee entre l'interface et les sommets du maillage eulerien.
8993 *
8994 * Si cette distance n'a pas encore ete calculee, appel a calculer_distance_interface_sommets.
8995 * C'est un DoubleTab parce qu'il n'existe pas (encore) de champ aux sommets en VDF ...
8996 *
8997 */
8999{
9000 // Si le tag du maillage et le tag du champ sont identiques, inutile de recalculer:
9001 const int tag = maillage_interface().get_mesh_tag();
9002 if (tag == variables_internes_->distance_sommets_cache_tag)
9003 {
9004 return variables_internes_->distance_interface_sommets;
9005 }
9006 variables_internes_->distance_sommets_cache_tag = tag;
9007 assert(tag == variables_internes_->distance_normale_cache_tag);
9008 const DoubleTab& dist_elem = get_distance_interface().valeurs();
9009 const DoubleTab& normale_elem = get_normale_interface().valeurs();
9010 DoubleTab& dist_som = variables_internes_->distance_interface_sommets;
9011 calculer_distance_interface_sommets(dist_elem, normale_elem, dist_som);
9012 return dist_som;
9013}
9014
9015/*! @brief Calcule dist_som, la distance entre l'interface et les sommets du maillage eulerien a partir de dist_elem et normale_elem,
9016 *
9017 * distance et normale a l'interface aux centres des elements euleriens.
9018 * Pour un element, on evalue la distance entre chaque sommet de l'element et l'interface
9019 * comme :
9020 * d = d1 + d2,
9021 * d2 = normale scalaire (position_sommet - centre_element)
9022 * d1 est la distance entre l'interface et le centre de l'element,
9023 * normale est la normale a l'interface evaluee au centre de l'element
9024 * Ensuite, la distance entre un sommet et l'interface est la moyenne de toutes
9025 * les distances calculee a l'aide des elements adjacents a ce sommet.
9026 * La distance est invalide au-dela d'une certaine epaisseur autour de l'interface
9027 * (voir iterations de lissage dans calculer_distance_interface).
9028 * Dans ce cas on met une distance de +1e30 si l'indicatrice est >0.5,
9029 * sinon on met -1e30 (ce choix permet d'utiliser la fonction
9030 * distance dans les marching-cubes sans avoir a calculer une vraie distance partout).
9031 * Parametre : dist_elem
9032 * Signification : tableau contenant pour chaque element reel et virtuel la distance
9033 * entre l'interface et le centre de l'element (calculee par
9034 * calculer_distance_interface). L'espace virtuel doit etre a jour.
9035 * Parametre : normale_elem
9036 * Signification : idem pour la normale a l'interface
9037 * Parametre : dist_som
9038 * Signification : tableau ou on stocke le resultat du calcul. Le tableau doit
9039 * avoir la bonne taille et un descripteur adequat (voir "discretiser",
9040 * a priori un tableau avec une epaisseur de joint de zero et uniquement
9041 * des items communs).
9042 *
9043 */
9045 const DoubleTab& dist_elem,
9046 const DoubleTab& normale_elem,
9047 DoubleTab& dist_som) const
9048{
9049 static const double distance_sommets_invalides = -1.e30;
9050
9051 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
9052 const IntTab& elem_som = domaine_vf.domaine().les_elems();
9053 const DoubleTab& xp = domaine_vf.xp();
9054 const DoubleTab& coord_som = domaine_vf.domaine().les_sommets();
9055
9056 const int nb_sommets = dist_som.dimension_tot(0);
9057 ArrOfInt ncontrib(nb_sommets);
9058 ncontrib = 0;
9059 dist_som = 0.;
9060
9061 const int dim = Objet_U::dimension;
9062 double centre[3] = {0., 0., 0.};
9063 double normale[3] = {0., 0., 0.};
9064 // Calcul de SOMME(d1+d2) pour tous les elements voisins de chaque sommet :
9065 int elem, i;
9066 const int nb_elem_tot = dist_elem.dimension_tot(0);
9067 const int nb_som_elem = elem_som.line_size();
9068
9069 for (elem = 0; elem < nb_elem_tot; elem++)
9070 {
9071 const double d1 = dist_elem(elem);
9072 // Si la distance est invalide, on passe:
9073 if (d1 < distance_sommets_invalides)
9074 continue;
9075 // Centre de l'element et normale a l'interface pour cet element :
9076 for (i = 0; i < dim; i++)
9077 {
9078 centre[i] = xp(elem, i);
9079 normale[i] = normale_elem(elem, i);
9080 }
9081 // Boucle sur les sommets de l'element
9082 for (i = 0; i < nb_som_elem; i++)
9083 {
9084 const int som = elem_som(elem, i);
9085 // dist_som ne contient que des sommets reels en general.
9086 // si le sommet n'est pas dans dist_som, on ne calcule pas.
9087 if (som < nb_sommets)
9088 {
9089 double d2 = 0.;
9090 int j;
9091 for (j = 0; j < dim; j++)
9092 {
9093 double position_sommet = coord_som(som, j);
9094 d2 += (position_sommet - centre[j]) * normale[j];
9095 }
9096 dist_som(som) += d1 + d2;
9097 ++(ncontrib[som]);
9098 }
9099 }
9100 }
9101 // Division par le nombre d'elements voisins
9102 const double valeur_invalide = distance_sommets_invalides * 1.1;
9103#ifdef __INTEL_COMPILER
9104#pragma novector // Desactive vectorisation sur Intel car crash sinon
9105#endif
9106 for (i = 0; i < nb_sommets; i++)
9107 {
9108 const int n = ncontrib[i];
9109 if (n > 0)
9110 dist_som(i) /= n;
9111 else
9112 dist_som(i) = valeur_invalide;
9113 }
9114 dist_som.echange_espace_virtuel();
9115 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_distance_interface_sommets",dist_som);
9116}
9117
9118/*! @brief Calcul d'un champ scalaire aux elements contenant une distance signee entre le centre de l'element et l'interface.
9119 *
9120 * La distance est positive dans
9121 * la phase 1 et negative dans la phase 0.
9122 * On calcule aussi un champ vectoriel aux elements contenant une normale
9123 * a l'interface. Ce champ est evalue en resolvant moralement
9124 * laplacien(normale) = gradient(indicatrice)
9125 * ou gradient(indicatrice) est le gradient de l'indicatrice continue
9126 * c'est a dire un dirac localise a la surface de l'interface.
9127 * Pour l'instant, cette normale est calculee de facon approchee avec quelques
9128 * iterations d'un lisseur. Le support est donc limite au voisinage de l'interface.
9129 * Pour les autres elements, la distance vaut -1.e30
9130 * Precondition : le maillage doit etre parcouru
9131 *
9132 */
9134 const Maillage_FT_Disc& maillage,
9135 DoubleTab& distance_elements,
9136 DoubleTab& normale_elements,
9137 const int n_iter) const
9138{
9139 statistics().create_custom_counter("Calculer_distance_interface",3,"FrontTracking");
9140 statistics().begin_count("Calculer_distance_interface",statistics().get_last_opened_counter_level()+1);
9141
9142 static const double distance_sommets_invalides = -1.e30;
9143
9144 // Coordonnees des sommets du maillage eulerien:
9145 const Domaine_dis_base& mon_dom_dis = domaine_dis();
9146 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, mon_dom_dis);
9147 const DoubleTab& centre_element = domaine_vf.xp();
9148
9149 // Tableau contenant une approximation de la normale aux sommets du maillage
9150 // eulerien :
9151 distance_elements = distance_sommets_invalides * 1.1;
9152 normale_elements = 0.;
9153
9154 const int nb_elem = mon_dom_dis.domaine().nb_elem();
9155 const int dim = Objet_U::dimension;
9156
9157 // Calcul de la distance pour l'epaisseur 0 (sommets des elements traverses par
9158 // l'interface). Pour chaque element, on calcule le plan passant par
9159 // le centre de gravite des portions de facettes et dont la normale est
9160 // la moyenne des normales aux portions de facettes, ponderees par la surface
9161 // des portions de facettes. La distance interface/element est la distance
9162 // entre ce plan et le centre de l'element.
9163 {
9164 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
9165 const ArrOfInt& index_elem = intersections.index_elem();
9166 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
9167 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
9168 const IntTab& facettes = maillage.facettes();
9169 const DoubleTab& sommets = maillage.sommets();
9170 // Boucle sur les elements
9171 for (int elem = 0; elem < nb_elem; elem++)
9172 {
9173 int index = index_elem[elem];
9174 // Moyenne ponderee des normales aux facettes qui traversent l'element
9175 double normale[3] = {0., 0., 0.};
9176 // Centre de gravite de l'intersection facettes/element
9177 double centre[3] = {0., 0., 0.};
9178 // Somme des poids
9179 double surface_tot = 0.;
9180 // Boucle sur les facettes qui traversent cet element
9181 while (index >= 0)
9182 {
9184 intersections.data_intersection(index);
9185
9186 const int num_facette = data.numero_facette_;
9187#ifdef AVEC_BUG_SURFACES
9188 const double surface = data.surface_intersection_;
9189#else
9190 const double surface = data.fraction_surface_intersection_ * surface_facettes[num_facette];
9191#endif
9192 surface_tot += surface;
9193 for (int i = 0; i < dim; i++)
9194 {
9195 normale[i] += surface * normale_facettes(num_facette, i);
9196 // Calcul du centre de gravite de l'intersection facette/element
9197 double g_i = 0.; // Composante i de la coordonnee du centre de gravite
9198 for (int j = 0; j < dim; j++)
9199 {
9200 const int som = facettes(num_facette, j);
9201 const double coord = sommets(som, i);
9202 const double coeff = data.barycentre_[j];
9203 g_i += coord * coeff;
9204 }
9205 centre[i] += surface * g_i;
9206 }
9207 index = data.index_facette_suivante_;
9208 }
9209 if (surface_tot > 0.)
9210 {
9211 // La normale stockee n'est pas normee : norme a peu pres egale a la surface
9212 // d'interface qui a servi a la calculer.
9213 // centre = somme(centre[facette] * surface) / somme(surface)
9214 const double inverse_surface_tot = 1. / surface_tot;
9215 double norme = 0.;
9216 int j;
9217 for (j = 0; j < dim; j++)
9218 {
9219 norme += normale[j] * normale[j];
9220 normale_elements(elem, j) = normale[j];
9221 centre[j] *= inverse_surface_tot;
9222 }
9223 if (norme > 0)
9224 {
9225 double i_norme = 1./sqrt(norme);
9226 double distance = 0.;
9227 for (j = 0; j < dim; j++)
9228 {
9229 double n_j = normale[j] * i_norme; // normale normee
9230 distance += (centre_element(elem, j) - centre[j]) * n_j;
9231 }
9232 distance_elements(elem) = distance;
9233 }
9234 }
9235 }
9236 normale_elements.echange_espace_virtuel();
9237 distance_elements.echange_espace_virtuel();
9238 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_distance_interface",normale_elements);
9239 Debog::verifier("Transport_Interfaces_FT_Disc::calculer_distance_interface",distance_elements);
9240 }
9241
9242 DoubleTab terme_src(normale_elements);
9243 DoubleTab tmp(normale_elements);
9244
9245 const IntTab& face_voisins = domaine_vf.face_voisins();
9246 const IntTab& elem_faces = domaine_vf.elem_faces();
9247 const int nb_elem_voisins = elem_faces.line_size();
9248
9249 // Calcul d'une normale aux elements :
9250 int iteration;
9251 for (iteration = 0; iteration < n_iter; iteration++)
9252 {
9253 // Iteration du lisseur : moralement on fait
9254 // normale = normale + (terme_source - laplacien(normale)) * facteur
9255 // qui converge vers
9256 // laplacien(normale) = terme_source
9257 // mais le laplacien est pipo : en pratique on fait juste :
9258 // normale = moyenne(normale sur les elem voisins) + terme_source
9259
9260 const double un_sur_ncontrib = 1. / (1. + nb_elem_voisins);
9261 int elem, i, k;
9262 for (elem = 0; elem < nb_elem; elem++)
9263 {
9264 // La moyenne du vecteur normal sur les voisins:
9265 double n[3] = {0., 0., 0.};
9266 for (i = 0; i < dim; i++)
9267 n[i] = normale_elements(elem, i);
9268 for (k = 0; k < nb_elem_voisins; k++)
9269 {
9270 // On cherche l'element voisin par la face k
9271 const int face = elem_faces(elem, k);
9272 const int e_voisin = face_voisins(face, 0) + face_voisins(face, 1) - elem;
9273 if (e_voisin >= 0) // Si on n'est pas au bord...
9274 for (i = 0; i < dim; i++)
9275 n[i] += normale_elements(e_voisin, i);
9276 }
9277 for (i = 0; i < dim; i++)
9278 tmp(elem, i) = terme_src(elem, i) + n[i] * un_sur_ncontrib;
9279 }
9280 normale_elements = tmp;
9281 normale_elements.echange_espace_virtuel();
9282 }
9283 // On normalise la normale, et on cree une liste des elements pour lesquels
9284 // la normale est connue :
9285 ArrOfIntFT liste_elements;
9286 {
9287 int elem;
9288 for (elem = 0; elem < nb_elem; elem++)
9289 {
9290 double nx = normale_elements(elem, 0);
9291 double ny = normale_elements(elem, 1);
9292 double nz = (dim==3) ? normale_elements(elem, 2) : 0.;
9293 double norme2 = nx*nx + ny*ny + nz*nz;
9294 if (norme2 > 0.)
9295 {
9296 double i_norme = 1. / sqrt(norme2);
9297 normale_elements(elem, 0) = nx * i_norme;
9298 normale_elements(elem, 1) = ny * i_norme;
9299 if (dim==3)
9300 normale_elements(elem, 2) = nz * i_norme;
9301 liste_elements.append_array(elem);
9302 }
9303 }
9304 normale_elements.echange_espace_virtuel();//Manque cet echange (MB)
9305 }
9306 // Calcul d'une distance a l'interface :
9307 terme_src = distance_elements;
9308 tmp = distance_elements;
9309 for (iteration = 0; iteration < n_iter; iteration++)
9310 {
9311 int i_elem, elem;
9312 const int liste_elem_size = liste_elements.size_array();
9313 for (i_elem = 0; i_elem < liste_elem_size; i_elem++)
9314 {
9315 elem = liste_elements[i_elem];
9316 if (terme_src(elem) > distance_sommets_invalides)
9317 {
9318 // Pour les elements traverses par l'interface, la distance n'est pas recalculee.
9319 tmp(elem) = distance_elements(elem);
9320 }
9321 else
9322 {
9323 // Pour les autres, on calcule une distance pour chaque element voisin
9324 double ncontrib = 0.;
9325 double somme_distances = 0.;
9326 int k;
9327 for (k = 0; k < nb_elem_voisins; k++)
9328 {
9329 // On cherche l'element voisin par la face k
9330 const int face = elem_faces(elem, k);
9331 const int e_voisin = face_voisins(face, 0) + face_voisins(face, 1) - elem;
9332 if (e_voisin >= 0) // Si on n'est pas au bord...
9333 {
9334 const double distance_voisin = distance_elements(e_voisin);
9335 if (distance_voisin > distance_sommets_invalides)
9336 {
9337 // Calcul d'une normale moyenne entre l'element et le voisin
9338 double nx = normale_elements(elem, 0) + normale_elements(e_voisin, 0);
9339 double ny = normale_elements(elem, 1) + normale_elements(e_voisin, 1);
9340 double nz = (dim==3)
9341 ? normale_elements(elem, 2) + normale_elements(e_voisin, 2) : 0.;
9342 double norm2 = nx*nx + ny*ny + nz*nz;
9343 if (norm2 > 0.)
9344 {
9345 double i_norm = 1./sqrt(norm2);
9346 nx *= i_norm;
9347 ny *= i_norm;
9348 nz *= i_norm;
9349 }
9350 // Calcul du vecteur (element - element_voisin)
9351 double dx = centre_element(elem, 0) - centre_element(e_voisin, 0);
9352 double dy = centre_element(elem, 1) - centre_element(e_voisin, 1);
9353 double dz = (dim==3)
9354 ? centre_element(elem, 2) - centre_element(e_voisin, 2) : 0.;
9355 double d = nx * dx + ny * dy + nz * dz + distance_voisin;
9356 somme_distances += d;
9357 ncontrib++;
9358 }
9359 }
9360 }
9361 // Moyenne des distances obtenues avec les elements voisins.
9362 if (ncontrib > 0.)
9363 {
9364 double d = somme_distances / ncontrib;
9365 tmp(elem) = d;
9366 }
9367 }
9368 }
9369 distance_elements = tmp;
9370 distance_elements.echange_espace_virtuel();
9371 }
9372 statistics().end_count("Calculer_distance_interface");
9373}
9374
9376 const ArrOfInt& compo_connexes_facettes,
9377 const int nb_compo_tot,
9378 const DoubleTab& vitesse_sommets,
9379 DoubleTab& vitesses,
9380 DoubleTab& positions) const
9381{
9382 assert(nb_compo_tot == vitesses.dimension(0));
9383 assert(nb_compo_tot == positions.dimension(0));
9384
9385 const int dim = vitesses.line_size();
9386 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
9387 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
9388 const IntTab& facettes = maillage.facettes();
9389 const DoubleTab& sommets = maillage.sommets();
9390 assert(facettes.line_size() == dim);
9391
9392 // Surface totale de chaque composante connexe, initialise a zero
9393 ArrOfDouble surfaces_compo(nb_compo_tot);
9394 positions = 0.;
9395
9396 // Calcul du centre de gravite de la composante connexe
9397 // (centre de gravite de la surface, pas du volume)
9398 const int nb_facettes_tot = facettes.dimension_tot(0);
9399 {
9400 for (int i = 0; i < nb_facettes_tot; i++)
9401 {
9402 if (maillage.facette_virtuelle(i))
9403 continue;
9404 const int compo = compo_connexes_facettes[i];
9405 const double surface = surface_facettes[i];
9406 surfaces_compo[compo] += surface;
9407 // Centre de gravite de la facette, pondere par la surface
9408 for (int j = 0; j < dim; j++)
9409 {
9410 // Indice du sommet
9411 const int s = facettes(i, j);
9412 for (int k = 0; k < dim; k++)
9413 // On divisera par dim a la fin:
9414 positions(compo, k) += surface * sommets(s, k);
9415 }
9416 }
9417 mp_sum_for_each_item(surfaces_compo);
9418 mp_sum_for_each_item(positions);
9419
9420 positions *= (1. / dim);
9421
9422 DoubleVect s; // tab_divide prend DoubleVect, pas ArrOfDouble...
9423 s.ref_array(surfaces_compo);
9424 tab_divide_any_shape(positions, s);
9425 }
9426 ArrOfInt som(3);
9427 // Calcul de la vitesse de deplacement moyenne
9428 vitesses = 0.;
9429 //calcul de la vitesse moyenne de deplacement de l'interface
9430 for (int fa7 = 0; fa7 < nb_facettes_tot; fa7++)
9431 {
9432
9433 if (maillage.facette_virtuelle(fa7))
9434 continue;
9435 const double si=surface_facettes[fa7];
9436 som=0;
9437
9438 for (int d=0; d<dim; d++)
9439 som[d]=facettes(fa7,d);
9440
9441 //calcul de ds_dt
9442 double ds_dt=0.;
9443
9444 if(dim==2)
9445 {
9446 const double n0=normale_facettes(fa7,0);
9447 const double n1=normale_facettes(fa7,1);
9448 ds_dt=-n1*vitesse_sommets(som[0],0)+n0*vitesse_sommets(som[0],1)+n1*vitesse_sommets(som[1],0)-n0*vitesse_sommets(som[1],1);
9449 }
9450 else
9451 {
9452 const double n0=normale_facettes(fa7,0)*0.5;
9453 const double n1=normale_facettes(fa7,1)*0.5;
9454 const double n2=normale_facettes(fa7,2)*0.5;
9455 double s2s1[3],d_surface[3];
9456
9457 for (int i = 0; i < 3; i++)
9458 {
9459 // La differentielle de surface pour un deplacement du sommet i
9460 // est le produit vectoriel de la normale par le vecteur
9461 // s2s1 = (sommet[(i+1)%3] - sommet[(i+2)%3]) * 0.5
9462 // (vecteur de norme "base du triangle * 0.5" et de direction
9463 // la hauteur du triangle)
9464 const int s0 = som[i];
9465 const int s1 = som[ (i+1)%3 ];
9466 const int s2 = som[ (i+2)%3 ];
9467
9468 s2s1[0] = sommets(s1,0) - sommets(s2,0);
9469 s2s1[1] = sommets(s1,1) - sommets(s2,1);
9470 s2s1[2] = sommets(s1,2) - sommets(s2,2);
9471
9472 d_surface[0] = s2s1[1] * n2 - s2s1[2] * n1;
9473 d_surface[1] = s2s1[2] * n0 - s2s1[0] * n2;
9474 d_surface[2] = s2s1[0] * n1 - s2s1[1] * n0;
9475
9476 ds_dt+=d_surface[0]*vitesse_sommets(s0,0) + d_surface[1]*vitesse_sommets(s0,1) +d_surface[2]*vitesse_sommets(s0,2);
9477 }
9478 }
9479
9480 const int compo = compo_connexes_facettes[fa7];
9481 for (int d=0; d<dim; d++)
9482 {
9483 double V=0.;
9484 double p=0.;
9485 for (int d1=0; d1<dim; d1++)
9486 {
9487 V+=vitesse_sommets(som[d1],d);
9488 p+=sommets(som[d1],d);
9489 }
9490 V /= dim;
9491 p /= dim;
9492 vitesses(compo, d) += si * V + (p-positions(compo, d)) * ds_dt;
9493 }
9494 }
9495
9496 mp_sum_for_each_item(vitesses);
9497 {
9498 DoubleVect s; // tab_divide prend DoubleVect, pas ArrOfDouble...
9499 s.ref_array(surfaces_compo);
9500 tab_divide_any_shape(vitesses, s);
9501 }
9502
9504 {
9507 const Domaine& domain = domaine_dis().domaine();
9509 }
9510
9511}
9512
9513
9514// Note added by L. Wei on 13/01/2025
9515// This subroutine advects [valeurs] from PURE cells (both liquid and vapor).
9516// into two of their neighboring cells: one along the x-direction and another along the y-direction.
9517// The neighboring cell is identified by the normal direction of the liquid-vapor interface.
9518// Factors such as the normal vector to the liquid-vapor (L-V) interface and the proportion of the surface in x and y-dir of pure cells are considered
9519// to determine the appropriate proportion to redistribute to each neighboring cell. [i.e., the final valeur of tmp_flux]
9520// It's important to note that when this subroutine is invoked, it performs the advection process exactly once for all cells
9521// within the area where the interface normal vector ('normale_interface') is defined and non-zero. [normally serveral cells thickness surronding the interface]
9523 DoubleVect& flux,
9524 DoubleVect& valeurs)
9525{
9526 // Calcul d'un flux a travers chaque face, proportionnel a
9527 // Surface_face * (normale_interface scalaire normale_face) * grandeur_amont_a_transporter
9528 const int dim = Objet_U::dimension;
9529 const Domaine_VF& domaine_vf = ref_cast(Domaine_VF, domaine_dis());
9530 const Domaine& domaine = domaine_vf.domaine();
9531 const IntTab& face_voisins = domaine_vf.face_voisins();
9532 const IntTab& elem_faces = domaine_vf.elem_faces();
9533 const int nb_faces_tot = domaine_vf.nb_faces_tot();
9534 //const int nb_elem = domaine.nb_elem();
9535 const int nb_elem_tot = domaine.nb_elem_tot();
9536 const int nb_faces_elem = domaine_vf.domaine().nb_faces_elem();
9537 const DoubleVect& indic = get_indicatrice().valeurs();
9538 const DoubleTab& normale_interface = get_normale_interface().valeurs(); // direction: from vapour toward liquid
9539 for (int i_face = 0; i_face < nb_faces_tot; i_face++)
9540 {
9541 double f;
9542 const int elem0 = face_voisins(i_face, 0);
9543 const int elem1 = face_voisins(i_face, 1);
9544 if (elem0 < 0 || elem1 < 0) // at teh boundary
9545 f = 0.;
9546 else
9547 {
9548 double prod_scal = 0.;
9549 // Le produit scalaire est fait avec la normale a l'interface evaluee
9550 // a la face (moyenne des normales n0 et n1 des deux elements voisins.
9551 // faces_normales() donne une normale de norme egale a la surface de la face
9552 for (int i = 0; i < dim; i++)
9553 {
9554 double n0 = normale_interface(elem0, i);
9555 double n1 = normale_interface(elem1, i);
9556 prod_scal += (n0 + n1) * 0.5 * domaine_vf.face_normales(i_face, i);
9557 }
9558 if (indic(elem0) == 1. || indic(elem1) == 1.)
9559 prod_scal = - prod_scal;
9560 // Si la face appartient a deux elements diphasiques alors
9561 // on annule le flux pour eviter les echanges entre ces cellules
9562 if (indic(elem0) != 0. && indic(elem0) != 1.)
9563 {
9564 if (indic(elem1) != 0. && indic(elem1) != 1.)
9565 {
9566 prod_scal=0.;
9567 }
9568 }
9569 f = prod_scal;
9570 }
9571 flux(i_face) = f;
9572 }
9573 //
9575 //
9576 // Renormalisation des flux de sorte que la somme des flux sortants de chaque
9577 // element vide completement cet element.
9578 // On travaille sur une copie du tableau flux pour eviter les interactions
9579 // entre les deux boucles qui suivent
9580 DoubleVect tmp_flux = flux;
9581 ArrOfInt flag(nb_faces_elem);
9582 for (int i_elem = 0; i_elem < nb_elem_tot; i_elem++)
9583 {
9584 // Somme des flux sortants de l'element:
9585 double somme = 0.;
9586 for (int j = 0; j < nb_faces_elem; j++)
9587 {
9588 int i_face = elem_faces(i_elem, j);
9589 const int elem0 = face_voisins(i_face, 0);
9590 const int elem1 = face_voisins(i_face, 1);
9591 if (elem0 < 0 || elem1 < 0)
9592 continue;
9593 // Le flux est-il sortant ?
9594 const double signe = (elem0 == i_elem) ? 1. : -1.;
9595 const double f = flux(i_face);
9596 if (f * signe > 0.)
9597 {
9598 somme += f * signe; // oui
9599 flag[j] = 1;//
9600 }
9601 }
9602 // renormalisation des flux sortants et multiplication par la valeur a transporter:
9603 if (somme > 0.)
9604 {
9605 const double facteur = valeurs(i_elem) / somme;
9606 for (int j = 0; j < nb_faces_elem; j++)
9607 {
9608 int i_face = elem_faces(i_elem, j);
9609 if (flag[j])
9610 {
9611 tmp_flux[i_face] = tmp_flux[i_face] * facteur;
9612 flag[j] = 0;
9613 }
9614 }
9615 }
9616 }
9617 // Recopie de tmp_flux dans flux
9618 for (int i_elem = 0; i_elem < nb_elem_tot; i_elem++)
9619 {
9620 for (int j = 0; j < nb_faces_elem; j++)
9621 {
9622 int i_face = elem_faces(i_elem, j);
9623 flux[i_face]=tmp_flux[i_face];
9624 }
9625 }
9626 // Application du flux calcule
9627 // nb_elem_tot a la place de nb_elem
9628 for (int i_elem = 0; i_elem < nb_elem_tot; i_elem++)
9629 {
9630 double x = valeurs(i_elem);
9631 for (int j = 0; j < nb_faces_elem; j++)
9632 {
9633 int i_face = elem_faces(i_elem, j);
9634 double f = flux(i_face);
9635 double signe = (i_elem == face_voisins(i_face, 1)) ? 1. : -1.;
9636 x += f * signe;
9637 }
9638 valeurs(i_elem) = x;
9639
9640 }
9641 valeurs.echange_espace_virtuel();
9642}
9643
9644// Calcule des valeurs aux sommets du maillage ft a partir des valeurs euler qui sont supposees etre aux elements.
9645// Le transfert est conservatif: on suppose que les valeurs_euler sont des integrales sur chaque element.
9646// La somme de ces valeurs sera egale a la somme des valeurs associees aux sommets lagrangiens.
9648 const DoubleVect& valeurs_euler,
9649 ArrOfDouble& valeurs_lagrange)
9650{
9651 const int nb_sommets = maillage.nb_sommets();
9652 valeurs_lagrange.resize_array(nb_sommets);
9653 // Initialisation a zero car on va ajouter des contributions dans le desordre :
9654 valeurs_lagrange = 0.;
9655
9656 const int dim = Objet_U::dimension;
9657 const IntTab& facettes = maillage.facettes();
9658 const Intersections_Elem_Facettes& intersections = maillage.intersections_elem_facettes();
9659 const ArrOfInt& index_elem = intersections.index_elem();
9660 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
9661 const int nb_elements = valeurs_euler.size();
9662 assert(nb_elements == index_elem.size_array());
9663
9664 // Boucle sur les elements euleriens
9665 int element;
9666 for (element = 0; element < nb_elements; element++)
9667 {
9668
9669 // Si cet element n'est pas traverse par l'interface, ne pas calculer
9670 // la variation de volume.
9671 const int index_premiere_intersection = index_elem[element];
9672 if (index_premiere_intersection < 0) // Pas de facette dans cet element
9673 continue;
9674
9675 // Repartition conservative de la valeur_euler sur les noeuds
9676 // du maillage lagrangien :
9677
9678 // Premier passage : calcul de la surface totale d'intersection entre le
9679 // maillage lagrangien et l'element eulerien "element".
9680 double surface_totale = 0.;
9681 // Boucle sur les faces qui traversent l'element:
9682 int index = index_premiere_intersection;
9683 while (index >= 0)
9684 {
9685 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
9686 const int facette = data.numero_facette_;
9687 const double surface_facette = surface_facettes[facette];
9688 surface_totale += data.fraction_surface_intersection_ * surface_facette;
9689 index = data.index_facette_suivante_;
9690 }
9691
9692 const double valeur_euler = valeurs_euler[element];
9693
9694 // Deuxieme passage : repartition de la valeur_euler sur les sommets,
9695 // proportionnelle a la surface et a la coordonnee barycentrique du sommet :
9696 index = index_premiere_intersection;
9697 if (surface_totale > 0.)
9698 {
9699 const double inv_surface_tot = 1. / surface_totale;
9700 while (index >= 0)
9701 {
9702 const Intersections_Elem_Facettes_Data& data = intersections.data_intersection(index);
9703 const int facette = data.numero_facette_;
9704 const double surface_facette = surface_facettes[facette];
9705 // Fraction de la surface d'intersection de cette facette a la surface totale
9706 // d'intersection avec l'element :
9707 const double fraction_surface = data.fraction_surface_intersection_ * surface_facette * inv_surface_tot;
9708 int i;
9709 for (i = 0; i < dim; i++)
9710 {
9711 const int sommet = facettes(facette, i);
9712 const double coeff = data.barycentre_[i];
9713 // La somme des "coeff" pour une intersection vaut 1
9714 // et la sommet des fraction_surface pour toutes les intersections
9715 // vaut 1, donc on distribue "valeur_euler" de facon conservative
9716 // sur les sommets du maillage lagrangien :
9717 const double valeur = coeff * fraction_surface * valeur_euler;
9718 // Certaines contributions sont ajoutees a des sommets virtuels,
9719 // on collecte le tout a la fin :
9720 valeurs_lagrange[sommet] += valeur;
9721 }
9722 index = data.index_facette_suivante_;
9723 }
9724 }
9725 }
9726
9728 // Mise a jour des espaces virtuels :
9729 maillage.desc_sommets().echange_espace_virtuel(valeurs_lagrange);
9730}
9731
9732void Transport_Interfaces_FT_Disc::compute_nb_particles_tot()
9733{
9735 const int nb_facettes=mesh.nb_facettes();
9736 ArrOfInt id_number_fa7(nb_facettes); // Init a zero
9737 int n = search_connex_components_local_FT(mesh, id_number_fa7);
9738 nb_particles_tot_= compute_global_connex_components_FT(mesh, id_number_fa7, n);
9739}
9740
9742{
9743 const Domaine& domain = domaine_dis().domaine();
9744 // computing the total number of particles
9745 // one cannot use Transport_Interfaces_FT_Disc::compute_nb_compo_tot()
9746 // because we need compo_connex_fa7 after
9748 const int nb_facettes=mesh.nb_facettes();
9749 ArrOfInt id_number_fa7(nb_facettes); // Init a zero
9750 int n = search_connex_components_local_FT(mesh, id_number_fa7);
9751 int nb_particles_tot=compute_global_connex_components_FT(mesh, id_number_fa7, n);
9752
9753 // particles dont't have initial velocity, their velocity is initialized with 0
9754 if ((particles_velocity_collision_.dimension(0) != nb_particles_tot) || (particles_velocity_collision_.dimension(1) != dimension))
9755 {
9756 Cerr << "WARNING, renumbering particles !" << finl;
9757 particles_position_collision_.resize(nb_particles_tot, dimension);
9758 particles_velocity_collision_.resize(nb_particles_tot, dimension);
9761
9762 const ArrOfDouble& surface_facettes = mesh.get_update_surface_facettes();
9763 const IntTab& facettes = mesh.facettes();
9764 const DoubleTab& sommets = mesh.sommets();
9765
9766 DoubleVect particles_surfaces(nb_particles_tot);
9767
9768 // computing surface gravity center
9769 const int nb_facettes_tot = facettes.dimension_tot(0);
9770 {
9771 for (int i = 0; i < nb_facettes_tot; i++)
9772 {
9773 if (mesh.facette_virtuelle(i)) continue;
9774
9775 const int id_number_lagrangian_vertice = id_number_fa7[i];
9776 const double surface = surface_facettes[i];
9777 particles_surfaces[id_number_lagrangian_vertice] += surface;
9778
9779 // computing the facet gravity surface weighted by its surface
9780 for (int j = 0; j < dimension; j++)
9781 {
9782 const int s = facettes(i, j);
9783 for (int k = 0; k < dimension; k++)
9784 particles_position_collision_(id_number_lagrangian_vertice, k) +=
9785 surface * sommets(s, k);
9786 }
9787 }
9788 mp_sum_for_each_item(particles_surfaces);
9790
9792 DoubleVect s;
9793 s.ref_array(particles_surfaces);
9794 tab_divide_any_shape(particles_position_collision_, s);
9795 }
9796 }
9798 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
9799 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
9801}
9802
9803/*! @brief WARNING, particles_position_collision_ and particles_velocity_collision_ are not used to transport particles
9804* but only for the computation of contact forces. Thus, be aware that tables Vitesses and Positions
9805* from the method calculer_vitesse_repere_local() are different from those of the present method.
9806* Indeed, it is not required to conserve the same lagrangian number to transport particles.
9807* To merge tables from both methods, one should modify the following methods: search_connex_components_local_FT
9808* and compute_global_connex_components_FT. If a particle is numbered 0 by proc 0, its global Lagrangian number will be 0.
9809* However, if it passes to proc 1 and is assigned the number 0, its global number will be 0 + the number of particles of proc 0.
9810* This method swap rows of particles_position_collision_ and particles_velocity_collision_ to conserve the particles
9811* lagrangian ID number between two successive times steps using the particles eulerian ID number. Indeed, after calling
9812* the function search_connex_components_local_FT and compute_global_connex_components_FT, their lagrangian number has changed.
9813* The method is base on the assumption that the element in which the gravity center of a given particle conserve its
9814* eulerian ID number between two successive time steps, which is always verified for resolved particles.
9815* We then attribute the eulerian ID number of this elem to the lagrangian particle ID number by swapping table rows.
9816* /!\ /!\ /!\ At the moment, this method is performed sequentially only
9817* All processors know the tables particles_position_collision_ and particles_velocity_collision_
9818*/
9820{
9821 const Domaine& domain = domaine_dis().domaine();
9822 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
9823 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
9824 int nb_particles_tot = particles_position_collision_.dimension(0);
9825 DoubleTab correct_particles_position(nb_particles_tot, dimension);
9826 DoubleTab correct_particles_velocity(nb_particles_tot, dimension);
9827 IntVect particles_correct_id_number(nb_particles_tot);
9828
9829 // Step 1: Identification of the elements which contain particles gravity center
9831 const IntTab& particles_eulerian_id_number = ns.get_particles_eulerian_id_number();
9832
9833 // Step 2: Identification of the permutations required to conserve the Lagrangian number
9834 for (int wrong_id_number=0; wrong_id_number<nb_particles_tot; wrong_id_number++)
9835 {
9836 int particle_gravity_center_elem=gravity_center_elem_[wrong_id_number];
9837 int correct_id_number;
9838 if (particle_gravity_center_elem==-1) correct_id_number =-1;
9839 else correct_id_number = particles_eulerian_id_number[particle_gravity_center_elem];
9840 particles_correct_id_number(wrong_id_number)=correct_id_number;
9841 }
9842 mp_max_for_each_item(particles_correct_id_number);
9843 int isduplicateValue = collision_model_.valeur().check_for_duplicates(particles_correct_id_number);
9844 if (isduplicateValue == 1) Process::exit("Transport_Interfaces_FT_Disc::swap_particles_position_velocity "
9845 "ERROR: duplicate value of the particles lagrangian ID number");
9846
9847 // Step3:Swapping table rows
9848 for (int wrong_id_number = 0; wrong_id_number < nb_particles_tot; wrong_id_number++)
9849 {
9850 int good_id_number = particles_correct_id_number[wrong_id_number];
9851 for (int d = 0; d < dimension; d++)
9852 {
9853 correct_particles_position(good_id_number, d) = particles_position_collision_(wrong_id_number, d);
9854 correct_particles_velocity(good_id_number, d) = particles_velocity_collision_(wrong_id_number, d);
9855 }
9856 }
9857 particles_position_collision_ = correct_particles_position;
9858 particles_velocity_collision_ = correct_particles_velocity;
9859}
9860
9862{
9863 const Domaine_VF& domain_vf = ref_cast(Domaine_VF, domaine_dis());
9864 const DoubleVect& mesh_volumes = domain_vf.volumes();
9865 const IntTab& elem_faces = domain_vf.elem_faces();
9866 const DoubleTab& phase_indicator_function = indicatrice_->valeurs();
9867 Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
9868 Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
9869 const Fluide_Diphasique& two_phase_elem=ns.fluide_diphasique();
9870 const int id_solid_phase=1-two_phase_elem.get_id_fluid_phase();
9871 const IntTab& particles_eulerian_id_number = ns.get_particles_eulerian_id_number();
9872 const DoubleTab& tab_velocity=ns.inconnue().valeurs();
9873
9878
9879 for (int elem=0; elem<domain_vf.nb_elem(); elem++)
9880 {
9881 // the mean is realized on pure elem only
9882 if (phase_indicator_function(elem)==id_solid_phase)
9883 {
9884 const int particle= particles_eulerian_id_number(elem);
9885 particles_purely_solid_mesh_volume_(particle)+=mesh_volumes(elem);
9886 for (int dim=0; dim<dimension; dim++)
9887 {
9888 mean_particles_volumic_velocity_(particle,dim)+=0.5*(
9889 tab_velocity(elem_faces(elem,dim))+
9890 tab_velocity(elem_faces(elem,dim+dimension))
9891 )*mesh_volumes(elem);
9892
9894 0.5*(tab_velocity(elem_faces(elem,dim))+
9895 tab_velocity(elem_faces(elem,dim+dimension))
9896 )*mesh_volumes(elem),2);
9897 }
9898 }
9899 }
9900
9904 DoubleVect s_vparticles;
9906 tab_divide_any_shape(mean_particles_volumic_velocity_, s_vparticles);
9907 tab_divide_any_shape(mean_particles_volumic_squared_velocity_, s_vparticles);
9908
9909 for (int particle=0; particle<nb_particles_tot_; particle++)
9910 {
9911 for (int dim=0; dim<dimension; dim++)
9912 {
9913 rms_particles_volumic_velocity_(particle,dim)=
9914 sqrt(fabs(pow(mean_particles_volumic_velocity_(particle,dim),2)
9916 }
9917 }
9918
9919}
9920
9921void Transport_Interfaces_FT_Disc::fill_ftab_scalar(DoubleTab *ftab,
9922 const ArrOfDouble& values) const
9923{
9924 const int nb_fa7 = values.size_array();
9925 ftab->resize(nb_fa7, 1);
9926 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
9927 (*ftab)(fa7,0) = (float) values(fa7);
9928}
9929
9930void Transport_Interfaces_FT_Disc::fill_ftab_scalar(DoubleTab *ftab,
9931 const DoubleVect& values) const
9932{
9933 const int nb_fa7 = values.size_array();
9934 ftab->resize(nb_fa7, 1);
9935 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
9936 (*ftab)(fa7,0) = (float) values(fa7);
9937}
9938
9939void Transport_Interfaces_FT_Disc::fill_ftab_scalar(DoubleTab *ftab,
9940 const DoubleTab& values) const
9941{
9942 const int nb_fa7 = values.dimension(0);
9943 ftab->resize(nb_fa7, 1);
9944 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
9945 (*ftab)(fa7,0) = (float) values(fa7);
9946}
9947
9948void Transport_Interfaces_FT_Disc::fill_ftab_vector(DoubleTab *ftab, const DoubleTab& values) const
9949{
9950
9951 const int nb_fa7 = values.dimension(0);
9952 const int nb_compo = values.dimension(1);
9953 ftab->resize(nb_fa7, nb_compo);
9954 for (int fa7=0 ; fa7<nb_fa7 ; fa7++)
9955 for (int k=0 ; k<nb_compo ; k++)
9956 (*ftab)(fa7,k) = (float) values(fa7,k);
9957}
9958
9959void Transport_Interfaces_FT_Disc::fill_ftab_vertices_curvature(DoubleTab *ftab, const DoubleTab& dummytab) const
9960{
9962 fill_ftab_scalar(ftab,mesh.get_update_courbure_sommets());
9963}
9964
9965void Transport_Interfaces_FT_Disc::fill_ftab_velocity(DoubleTab *ftab,const DoubleTab& dummytab) const
9966{
9967 if (variables_internes_->refequation_vitesse_transport)
9968 {
9969 DoubleTabFT vit;
9970 // Calcul de la vitesse de deplacement des sommets par interpolation
9971 // (deplacement contient en fait la vitesse en m/s)
9972 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
9973 const Champ_base& champ_vitesse = eqn_hydraulique.inconnue();
9974 int flag = 1;
9975 if (sub_type(Navier_Stokes_FT_Disc, eqn_hydraulique))
9976 {
9977 const Navier_Stokes_FT_Disc& ns = ref_cast(Navier_Stokes_FT_Disc, eqn_hydraulique);
9979 flag=0;
9980 }
9982 0 /* ne pas recalculer le champ de vitesse L2 */, // GB 2020/03/20 -> Je suis surpris par cette option 0 en desaccord avec le moment du calcul
9983 // mais je ne prends pas la responsabilite de changer car je ne sais pas trop ce que ca represente (c'est du VEF uniquement?)
9984 flag /* Interpolation Multi-lineaire en VDF */,
9985 false /* la_roue_de_vitesse_a_deja_tournee => C'est vrai
9986 Mais en post, on veut afficher la valeur future de la vitesse qui sera appliquee lors du prochain dt,
9987 on l'obtient donc en regardant la case present */ );
9988 // Pour ajouter le saut de vitesse a l'interface :
9989 ajouter_contribution_saut_vitesse(vit, // TODO: a verifier. Je ne sais pas ce que l'on veut
9990 false /* la_roue_de_vitesse_a_deja_tournee => permet d'afficher la valeur future en expli */ ); // ici, l'interpolation depend de ns.get_new_mass_source()
9991 fill_ftab_vector(ftab,vit);
9992 }
9993 else
9994 {
9995 // Coder le postraitement d'une vitesse imposee
9996 Cerr << "Error : velocity nodes post-processing : to be developped." << finl;
9997 assert(0);
9998 Process::exit();
9999 }
10000
10001}
10002
10003void Transport_Interfaces_FT_Disc::fill_ftab_local_reference_frame_velocity(DoubleTab *ftab, const DoubleTab& dummytab) const
10004{
10005 if (variables_internes_->refequation_vitesse_transport)
10006 {
10007 DoubleTabFT vit;
10008 DoubleTab Positions,Vitesses;
10009 // Calcul de la vitesse de deplacement des sommets par interpolation
10010 // (deplacement contient en fait la vitesse en m/s)
10011 const Equation_base& eqn_hydraulique = variables_internes_->refequation_vitesse_transport.valeur();
10012 const Champ_base& champ_vitesse = eqn_hydraulique.inconnue();
10014 0 /* ne pas recalculer le champ de vitesse L2 */, // GB 2020/03/20 -> Je suis surpris par cette option 0 en desaccord avec le moment du calcul
10015 // mais je ne prends pas la responsabilite de changer car je ne sais pas trop ce que ca represente (c'est du VEF uniquement?)
10016 1 /* Interpolation Multi-lineaire en VDF */,
10017 false /* la_roue_de_vitesse_a_deja_tournee => C'est vrai
10018 Mais en post, on veut afficher la valeur future de la vitesse qui sera appliquee lors du prochain dt,
10019 on l'obtient donc en regardant la case present */ );
10020 // Pour ajouter le saut de vitesse a l'interface :
10021 ajouter_contribution_saut_vitesse(vit, // TODO: a verifier. Je ne sais pas ce que l'on veut
10022 false /* la_roue_de_vitesse_a_deja_tournee => permet d'afficher la valeur future en expli */ );// ici, l'interpolation depend de ns.get_new_mass_source()
10024 fill_ftab_vector(ftab,vit);
10025 }
10026 else
10027 {
10028 // Coder le postraitement d'une vitesse imposee
10029 Cerr << "Error : vitesse_repere_local nodes post-processing : to be developped." << finl;
10030 assert(0);
10031 Process::exit();
10032 }
10033}
10034
10035void Transport_Interfaces_FT_Disc::fill_ftab_normal_unit(DoubleTab *ftab,const DoubleTab& dummytab) const
10036{
10038 fill_ftab_vector(ftab,mesh.get_update_normale_facettes());
10039}
10040
10041void Transport_Interfaces_FT_Disc::fill_ftab_pressure_force(DoubleTab *ftab,const DoubleTab& dummytab) const
10042{
10043 if (post_process_hydro_forces_.get_is_post_process_pressure_force_fa7())
10044 fill_ftab_vector(ftab,post_process_hydro_forces_.get_pressure_force_fa7());
10045}
10046
10047void Transport_Interfaces_FT_Disc::fill_ftab_friction_force(DoubleTab *ftab,const DoubleTab& dummytab) const
10048{
10049 if (post_process_hydro_forces_.get_is_post_process_friction_force_fa7())
10050 fill_ftab_vector(ftab,post_process_hydro_forces_.get_friction_force_fa7());
10051}
10052
10053void Transport_Interfaces_FT_Disc::fill_ftab_Stokes(DoubleTab* ftab, const DoubleTab& values) const
10054{
10055 if(post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
10056 fill_ftab_vector(ftab,values);
10057}
10058
10059void Transport_Interfaces_FT_Disc::fill_ftab_pressure(DoubleTab *ftab,const DoubleTab& dummytab) const
10060{
10061 if(post_process_hydro_forces_.get_is_post_process_pressure_fa7())
10062 fill_ftab_scalar(ftab,post_process_hydro_forces_.get_pressure_fa7());
10063}
10064
10065void Transport_Interfaces_FT_Disc::fill_ftab_Stokes_pressure_interp(DoubleTab* ftab, const DoubleTab& dummytab) const
10066{
10067 if(post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
10068 fill_ftab_scalar(ftab,post_process_hydro_forces_Stokes_.get_pressure_fa7());
10069}
10070void Transport_Interfaces_FT_Disc::fill_ftab_Stokes_pressure_th(DoubleTab* ftab, const DoubleTab& dummytab) const
10071{
10072 if(post_process_hydro_forces_Stokes_.get_is_compute_forces_Stokes_th())
10073 fill_ftab_scalar(ftab,post_process_hydro_forces_Stokes_.get_pressure_fa7_Stokes_th());
10074}
10075
: classe Algorithmes_Transport_FT_Disc
int testsetbit(int_t i) const
Renvoie la valeur du bit e, puis met le bit e a 1.
Definition ArrOfBit.h:85
class Champ_Face_VDF Cette classe sert a representer un champ vectoriel dont on ne calcule
classe Champ_Fonc_Face_VDF
classe Champ_Fonc_P1NC
Classe Champ_Inc_base.
DoubleTab & passe(int i=1) override
Renvoie les valeurs du champs a l'instant t-i.
double changer_temps(const double temps) override
Fixe le temps du champ.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & futur(int i=1)
Definition Champ_Proto.h:47
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual const Domaine_dis_base & domaine_dis_base() const
virtual DoubleTab & valeur_aux_elems_passe(const DoubleTab &positions, const IntVect &les_polys, DoubleTab &tab_valeurs) const
Definition Champ_base.h:92
double temps() const
Renvoie le temps du champ.
virtual DoubleTab & valeur_aux_elems(const DoubleTab &positions, const IntVect &les_polys, DoubleTab &valeurs) const
provoque une erreur ! doit etre surchargee par les classes derivees
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
virtual void suppression_interfaces(const IntVect &num_compo, const ArrOfInt &flags_compo_a_supprimer, int nouvelle_phase)
Methode appelee par Transport_Interfaces_xxx::test_suppression_interfaces_sous_domaine() lorqu'une in...
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
void collecter_espace_virtuel(ArrOfDouble &tab, MD_Vector_tools::Operations_echange op) const
void echange_espace_virtuel(ArrOfDouble &tab) const
classe Discretisation_base Cette classe represente un schema de discretisation en espace,...
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
void construire_elem_virt_pe_num()
Definition Domaine.cpp:704
const Sous_Domaine_t & ss_domaine(int i) const
Definition Domaine.h:290
SmallArrOfTID_t & chercher_elements(const DoubleTab &pos, SmallArrOfTID_t &elem, int reel=0) const
Recherche des elements contenant les points dont les coordonnees sont specifiees.
Definition Domaine.cpp:405
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau parallele de valeurs aux elements.
Definition Domaine.cpp:851
DoubleTab_t & les_sommets()
Definition Domaine.h:113
IntTab_t & les_elems()
Definition Domaine.h:129
int_t nb_elem() const
Definition Domaine.h:131
int nb_faces_elem(int=0) const
Renvoie le nombre de face de type i des elements geometriques constituants le domaine.
Definition Domaine.h:484
virtual void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Cree un tableau ayant une "ligne" par sommet du maillage.
Definition Domaine.cpp:1000
class Domaine_VDF
Definition Domaine_VDF.h:64
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
double distance_face(int, int, int k) const
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
int nb_joints() const
Definition Domaine_VF.h:65
const Joint & joint(int i) const
Definition Domaine_VF.h:105
double volumes(int i) const
Definition Domaine_VF.h:113
void construire_face_virt_pe_num()
Remplissage du tableau face_virt_pe_num_ (voir commentaire dans Domaine_VF.
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
int moments_a_imprimer() const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
virtual IntTab & face_voisins()
int nb_elem_tot() const
const Domaine & domaine() const
Lecture dans un fichier d'objets ecrits au format binaire.
Definition EFichierBin.h:30
Fichier en lecture Cette classe est a la classe C++ ifstream ce que la classe Entree est a la.
Definition EFichier.h:29
static Nom & get_Output()
Renvoie le mode d'ecriture utilise (pour pouvoir le modifier).
static int is_ecriture_special(int &special, int &a_faire)
indique si le format special a ete demande en lecture active par sauvegarde xyz .
static int is_lecture_special()
indique si le format special a ete demande en lecture active par reprise xyz .
Fichier en lecture Cette classe est a la classe C++ ifstream ce que la classe Entree est a la.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
virtual void set_param(Param &titi) const override
const Nom & le_nom() const override
Renvoie le nom de l'equation.
int reprendre(Entree &) override
On reprend l'inconnue a partir d'un flot d'entree.
virtual std::vector< YAML_data > data_a_sauvegarder() const
for PDI IO: retrieve name, type and dimensions of the data to save/restore. This has to be overrode f...
virtual void associer_pb_base(const Probleme_base &)
S'associe au Probleme passe en parametre.
const Discretisation_base & discretisation() const
Renvoie la discretisation associee a l'equation.
Solveur_Masse_base & solv_masse()
Renvoie le solveur de masse associe a l'equation.
virtual const Champ_Inc_base & inconnue() const =0
int calculate_time_derivative() const
virtual int nombre_d_operateurs() const =0
int sauvegarder(Sortie &) const override
On sauvegarde l'inconnue, puis les sources sur un flot de sortie.
virtual const Champ_Inc_base & derivee_en_temps() const
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
int limpr() const
Demande au schema en temps si il faut effectuer une impression.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
Champs_compris champs_compris_
virtual const Operateur & operateur(int) const =0
Domaine_dis_base & domaine_dis()
Renvoie le domaine discretise associe a l'equation.
const int & get_id_fluid_phase() const
: Classe de postraitement des champs euleriens au format lata
int ecrire_entete(const double temps_courant, const int reprise, const int est_le_premier_post) override
Ouvre le fichier maitre en mode ERASE et ecrit l'entete du fichier lata (sur le processeur maitre seu...
@ BINAIRE
int ecrire_domaine(const Domaine &domaine, const int est_le_premier_post) override
voir Format_Post_base::ecrire_domaine On accepte l'ecriture d'un domaine dans un pas de temps,...
int ecrire_temps(const double temps) override
commence l'ecriture d'un nouveau pas de temps En l'occurence pour le format LATA:
int ecrire_champ(const Domaine &domaine, const Noms &unite_, const Noms &noms_compo, int ncomp, double temps_, const Nom &id_du_champ, const Nom &id_du_domaine, const Nom &localisation, const Nom &nature, const DoubleTab &data) override
voir Format_Post_base::ecrire_champ
int initialize(const Nom &file_basename, const int format, const Nom &option_para) override
static Objet_U & objet(const Nom &)
Voir Interprete_bloc::objet_global() BM: la classe Interprete n'est pas le meilleur endroit pour cett...
: class Intersections_Elem_Facettes
const ArrOfInt & index_elem() const
Renvoie un tableau de taille domaine.
const Intersections_Elem_Facettes_Data & data_intersection(int index) const
Renvoie les donnees de l'intersection stockee a l'indice "index" dans le tableau "data" ( 0 <= index ...
const Joint_Items_t & joint_item(JOINT_ITEM type) const
Renvoie les informations de joint pour le type demande.
Definition Joint.cpp:128
const IntTab_t & renum_items_communs() const
Voir renum_items_communs_.
Cette classe implemente les operateurs et les methodes virtuelles de la classe EFichier de la facon s...
int get_sequential_items_flags(ArrOfBit &flags, int line_size=1) const
static void echange_espace_virtuel(IntVect &, Operations_echange opt=ECHANGE_EV, IsExchangeBlocking is_exchange_blocking=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
: class Maillage_FT_Disc Cette classe decrit un maillage:
virtual Entree & lire_param_maillage(Entree &is)
Cette fonction permet de lire les parametres pour le maillage des interfaces.
void mesh_tag_increase() const
int get_mesh_tag() const
return mesh_state_tag_
void set_is_solid_particle(const bool is_solid_particle)
void preparer_tableau_avant_transport(ArrOfDouble &tableau, const Desc_Structure_FT &descripteur) const
Prepare un tableau de donnees aux sommets ou aux facettes pour conserver les valeurs apres transport.
int nb_sommets() const
renvoie le nombre de sommets (reels et virtuels) (egal a sommets().
const DoubleTab & sommets() const
renvoie le tableau des sommets (reels et virtuels) dimension(0) = nombre de sommets,
void associer_equation_transport(const Equation_base &equation) override
on remplit refequation_transport_, schema_comm_domaine_ desc_sommets_.comm_group_ et desc_facettes_....
void update_tableau_apres_transport(ArrOfDouble &tableau, int nb_elements, const Desc_Structure_FT &descripteur) const
Voir preparer_tableau_avant_transport.
int nb_facettes() const
renvoie le nombre de facettes (reelles et virtuelles) (egal a facettes().
int facette_virtuelle(int i) const
Renvoie 0 si la facette m'appartient, 1 sinon.
double temps() const
return temps_physique_ (temps_physique_ ne sert a rien en interne.
const Desc_Structure_FT & desc_sommets() const
renvoie le descripteur des sommets (espace_distant/virtuel)
void completer_maillage()
Complete les structures de donnees du maillage.
virtual void ajouter_maillage(const Maillage_FT_Disc &maillage_tmp, int skip_facettes=0)
double changer_temps(double t)
return temps_physique_ = t
virtual const DoubleTab & get_update_normale_facettes() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
void facette_PE_owner(ArrOfInt &facette_pe) const
pour postraitement, remplit le tableau en parametre avec le numero du PE proprietaire de chaque facet...
void parcourir_maillage()
Remplit la structure intersections_elem_facettes_.
const Schema_Comm & get_schema_comm_FT() const
int sommet_virtuel(int i) const
const ArrOfInt & sommet_PE_owner() const
pour postraitement, renvoie le numero du PE proprietaire des sommets
void calcul_indicatrice(DoubleVect &indicatrice, const DoubleVect &indicatrice_precedente) const
Calcul de la fonction indicatrice (on suppose que "indicatrice" a la structure d'un tableau de valeur...
virtual void transporter(const DoubleTab &deplacement)
Deplace les sommets de l'interface d'un vecteur "deplacement" fourni, Change eventuellement les somme...
const Intersections_Elem_Facettes & intersections_elem_facettes() const
void nettoyer_elements_virtuels()
Retire toutes les facettes virtuelles et tous les sommets qui ne sont pas utilises.
virtual const ArrOfDouble & get_update_surface_facettes() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
virtual const ArrOfDouble & get_update_courbure_sommets() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau aux sommets du maillage Meme principe que Domaine::creer_tableau_sommets()
const IntTab & facettes() const
renvoie le tableau des facettes (reelles et virtuelles) dimension(0) = nombre de facettes,
const ArrOfInt & sommet_elem() const
pour postraitement, renvoie sommet_elem_
int construire_iso(const DoubleVect &valeurs_sommets, double isovaleur, Maillage_FT_Disc &maillage, DoubleVect &indicatrice_approchee, const Maillage_FT_Disc::AjoutPhase phase, int ignorer_collision=0) const
Construction d'un maillage en segments ou en triangles comme l'isovaleur d'une fonction discretisee a...
void associer_domaine_vf(const Domaine_VF &domaine_vf)
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:321
virtual const Champ_base * get_delta_vitesse_interface() const
Si le champ de vitesse est discontinu (calcul avec changement de phase), renvoie un pointeur vers le ...
void compute_particles_eulerian_id_number(const OWN_PTR(Collision_Model_FT_base)&collision_model_ptr)
const DoubleTab & get_interfacial_area() const
virtual void calculer_dI_dt(DoubleVect &dI_dt, const DoubleTab &tab_vitesse)
virtual const Fluide_Diphasique & fluide_diphasique() const
const IntTab & get_particles_eulerian_id_number() const
void swap_particles_eulerian_id_number(const ArrOfInt &gravity_center_elem)
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
const Champ_Inc_base & inconnue() const override
Renvoie la vitesse (champ inconnue de l'equation) (version const).
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
virtual int finit_par(const char *const n) const
Definition Nom.cpp:324
virtual int find(const char *const n) const
Definition Nom.cpp:314
const std::string & getString() const
Definition Nom.h:92
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
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
static int dimension
Definition Objet_U.h:99
friend class Sortie
Definition Objet_U.h:75
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
static double precision_geom
Definition Objet_U.h:86
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
static int bidim_axi
Definition Objet_U.h:102
virtual int reprendre(Entree &)
Reprise d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:338
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Operateur Classe generique de la hierarchie des operateurs.
Definition Operateur.h:39
double calculer_pas_de_temps() const
Calcule le prochain pas de temps.
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
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
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
void associer_connectivite_frontieres(const Connectivite_frontieres &connect)
void associer_domaine_dis(const Domaine_dis_base &domaine_dis)
Remplissage des variables persistantes de la classe (refdomaine_vf_, nb_faces_elem_,...
classe Paroi_FT_disc Condition aux limites d'angle de contact pour l'equation
Representation des donnees de la classe Parser.
Definition Parser.h:39
void addVar(const char *)
Definition Parser.cpp:565
virtual void setNbVar(int nvar)
Definition Parser.cpp:116
void setVar(const char *sv, double val)
Definition Parser.h:73
double eval()
Definition Parser.h:68
void setString(const std::string &s)
Definition Parser.h:102
virtual void parseString()
Definition Parser.cpp:124
static const char *const demande_description
const Triple_Line_Model_FT_Disc & tcl() const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
const Nom & checkpoint_filename() const
bool is_dilatable() const
bool & reprise_effectuee()
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
virtual int nombre_d_equations() const =0
virtual const Equation_base & equation(int) const =0
const Nom & restart_filename() const
static void mp_max_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:196
static double mp_min(double)
Definition Process.cpp:386
static int check_int_overflow(trustIdType)
Definition Process.cpp:428
static void mp_sum_for_each(T &arg1, T &arg2)
C++14 compatible mp_sum_for_each: combine multiple mp_sum calls into one collective operation Usage: ...
Definition Process.cpp:207
static double mp_max(double)
Definition Process.cpp:376
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static void abort()
Routine de sortie de Trio-U sur une erreur abort().
Definition Process.cpp:570
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Classe qui porte les proprietes de particules.
void nettoyer(const ArrOfInt &som_utilises)
: class Remaillage_FT Cette classe implemente les procedures de remaillage des interfaces pour le Fro...
int traite_decollement(Maillage_FT_Disc &maillage, const DoubleTab &deplacement) const
Cette fonction permet de gerer le decollement de l'interface de la paroi Si un sommet de bord n'a pas...
int traite_adherence(Maillage_FT_Disc &maillage) const
Cette fonction permet de gerer l'adherence de l'interface a la paroi Si une facette possede 3 sommets...
void associer_domaine(const Domaine_dis_base &domaine_dis)
Cette fonction stocke le domaine_dis dans refdomaine_dis_.
double calculer_variation_volume(const Maillage_FT_Disc &maillage, const DoubleTab &position_initiale, ArrOfDouble &varVolume) const
Cette fonction calcule le volume de phase 0 engendre par chaque sommet lors du deplacement de l'inter...
void set_is_solid_particle(const bool is_solid_particle)
void lisser_dvolume(const Maillage_FT_Disc &maillage, ArrOfDouble &var_volume, const int nb_iterations) const
Regularise le champ scalaire "var_volume" defini aux sommets du "maillage".
void corriger_volume_(Maillage_FT_Disc &maillage, ArrOfDouble &var_volume, const int nb_iter_corrections_vol)
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
static void lire_xyz(Maillage_FT_Disc &mesh, const Domaine_VF *domaine_vf, Entree *fichier, const Domaine *domaine_src)
Remplissage du maillage mesh a partir d'un fichier de sauvegarde xyz (fichier) ou d'un domaine source...
static void init_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
Create parallel descriptors for the vertex and element arrays of the domain (necessary because Scatte...
Definition Scatter.cpp:2742
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
methode utilisee par les interpretes qui modifient le domaine (sequentiel), detruit les descripteurs ...
Definition Scatter.cpp:2757
class Schema_Temps_base
int nb_impr() const
Renvoie le nombre d'impressions effectuees.
double temps_courant() const
Renvoie le temps courant.
void imprimer_temps_courant(SFichier &) const
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
virtual int nb_valeurs_temporelles() const =0
void update_critere_statio(const DoubleTab &tab_critere, Equation_base &equation)
//Actualisation de stationnaire_atteint_ et residu_ (critere residu_<seuil_statio_)
classe Solveur_Masse_base Represente la matrice de masse d'une equation.
virtual DoubleTab & appliquer(DoubleTab &) const
renvoie appliquer_impl(x/coeffient_temporelle) si on a un coefficient temporel sinon renvoie applique...
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
void precision(int pre) override
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual Sortie & flush()
Definition Sortie.cpp:138
int_t nb_elem_tot() const
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
_TYPE_ * addr()
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
int est_vide() const
TRUSTList & add(_TYPE_)
insertion en queue
Definition TRUSTList.tpp:85
TRUSTList & add_if_not(_TYPE_)
Ajout d'un element a la liste ssi il n'existe pas deja.
int contient(_TYPE_) const
Verifie si un element appartient ou non a la liste.
int size() const
Definition TRUSTList.h:68
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
int line_size() const
Definition TRUSTVect.tpp:67
void ref_array(TRUSTArray< _TYPE_, _SIZE_ > &, _SIZE_ start=0, _SIZE_ sz=-1) override
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
classe TRUST_2_PDI Encapsulation of PDI methods (library used for IO operations). See the website pdi...
Definition TRUST_2_PDI.h:59
void read(const std::string &name, void *data)
static void set_PDI_restart(int r)
void get_type(const Nom &name, Nom &type)
Generic method to read the type of a TRUST object in the HDF5 file.
static void set_PDI_checkpoint(int c)
static int is_PDI_checkpoint()
static int is_PDI_restart()
void TRUST_start_sharing(const std::string &name, const void *data)
: class Topologie_Maillage_FT Cette classe implemente les procedures de remaillage des interfaces pou...
virtual int calculer_composantes_connexes_pour_suppression(const Domaine_VF &domaine_vf, const DoubleTab &indicatrice, IntVect &num_compo) const
Computes eulerian connex components of the phase indicator function "indicatrice" according to the ge...
virtual void remailler_interface(const double temps, Maillage_FT_Disc &maillage, Champ_base &indicatrice, Remaillage_FT &algo_remaillage_local)
Remaillage de l'interface: - amelioration petites et grandes facettes,.
virtual double suppression_interfaces(const IntVect &num_compo, const ArrOfInt &flags_compo_a_supprimer, Maillage_FT_Disc &maillage, DoubleTab &indicatrice)
Removes all interfaces contained in eulerian elements marked by the "flags_" array,...
std::vector< YAML_data > data_a_sauvegarder() const
for PDI IO: retrieve name and type and dimensions of the indicatrice tag
OWN_PTR(Champ_Inc_base) indicatrice_cache
int reprendre(Entree &is) override
Reprise d'un Objet_U sur un flot d'entree Methode a surcharger.
int sauvegarder(Sortie &os) const override
Sauvegarde d'un Objet_U sur un flot de sortie Methode a surcharger.
void set_param(Param &titi) const override
DoubleTab & derivee_en_temps_inco(DoubleTab &derivee) override
Calcul de la derivee en temps de l'inconnue : zero.
const Operateur & operateur(int i) const override
void fill_ftab_pressure_force(DoubleTab *ftab, const DoubleTab &dummytab) const
void fill_ftab_friction_force(DoubleTab *ftab, const DoubleTab &dummytab) const
virtual void get_expression_vitesse_imposee(DoubleTab &vitesse_imp)
const DoubleTab & get_mean_particles_volumic_squared_velocity() const
virtual void PPP_face_interface_voisin(const DoubleTab &indicatrice, const DoubleTab &indicatrice_face, DoubleTab &Vertex, DoubleTab &PPP)
void update_indicatrice_normale_distance()
Updates normals and distances to interface, then updates indicatrice.
virtual const Champ_base & get_indicatrice_faces()
void fill_ftab_normal_unit(DoubleTab *ftab, const DoubleTab &dummytab) const
virtual double suppression_interfaces(const IntVect &num_compo, const ArrOfInt &flags_compo_a_supprimer)
virtual int get_champ_post_FT(const Motcle &champ, Postraitement_base::Localisation loc, DoubleTab *dtab=0) const
Cherche le champ discret aux interfaces dont le nom est "champ", et verifie qu'il peut etre postraite...
void associer_equation_ns(const Navier_Stokes_FT_Disc &ns)
const DoubleTab & get_mean_particles_volumic_velocity() const
int preparer_calcul() override
Tout ce qui ne depend pas des autres problemes eventuels.
void fill_ftab_vertices_curvature(DoubleTab *ftab, const DoubleTab &dummytab) const
int sauvegarder(Sortie &) const override
On sauvegarde l'inconnue, puis les sources sur un flot de sortie.
virtual void remailler_interface()
Remaillage de l'interface : - amelioration petites et grandes facettes,.
virtual const DoubleTab & get_update_distance_interface_sommets() const
Renvoi de la distance signee entre l'interface et les sommets du maillage eulerien.
const Topologie_Maillage_FT & topologie_interface() const
int impr(Sortie &os) const override
Imprime les operateurs de l'equation sur un flot de sortie, de facon inconditionnelle.
void calcul_source(const DoubleTab &inco_val, const DoubleTab &vpoint, const DoubleTab &rho_faces, DoubleTab &source_val, const DoubleTab &vit_imposee, const DoubleTab &indicatrice_faces, const int is_QC, const double dt, const int is_explicite, const double eta)
void associer_milieu_base(const Milieu_base &milieu) override
void update_indicatrice() override
Recalcul du champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
void impr_effort_fluide_interface(DoubleTab &source_val, DoubleTab &pressure_part, DoubleTab &friction_part, DoubleTab &diff_part)
void calculer_scalaire_interpole(const Champ_base &ch_scal, const Maillage_FT_Disc &, DoubleTab &ch_scal_noeuds, int nv_calc) const
const DoubleTab & get_particles_purely_solid_mesh_volume() const
virtual void transporter_sans_changement_topologie(DoubleTab &vitesse, const double coeff, const double temps)
void calcul_indicatrice_faces(const DoubleTab &indicatrice, const IntTab &face_voisins)
void fill_ftab_Stokes(DoubleTab *ftab, const DoubleTab &values) const
const Proprietes_part_vol & proprietes_particules() const
virtual const Connectivite_frontieres & connectivite_frontieres() const
void mettre_a_jour(double temps) override
La valeur de l'inconnue sur le pas de temps a ete calculee.
void nettoyer_proprietes_particules(const ArrOfInt &som_utilises)
virtual void calcul_nb_traverse(const DoubleTab &xe, const double dx, const int dim, const int ori, Maillage_FT_Disc &maillage, int elem, int &traverse)
int verif_Cl() const override
Methode appelee par Equation_base::readOn On verifie que toutes les cl sont de type Paroi_FT_disc.
const DoubleTab & get_rms_particles_volumic_velocity() const
virtual void calculer_distance_interface(const Maillage_FT_Disc &maillage, DoubleTab &distance_elements, DoubleTab &normale_elements, const int n_iter) const
Calcul d'un champ scalaire aux elements contenant une distance signee entre le centre de l'element et...
virtual void calcul_tolerance_projete_monophasique(const int i_face, const int ori, const int voisin0, const int voisin1, const DoubleTab &indicatrice_face, const DoubleTab &indicatrice, double &tol)
void modifie_source(DoubleTab &so_modif, const DoubleTab &so_val, const DoubleTab &rho_faces, const int n, const int m, const int is_QC, const DoubleVect &vol_entrelaces, const Solveur_Masse_base &solv_masse)
virtual const Parcours_interface & parcours_interface() const
Post_Processing_Hydrodynamic_Forces_Stokes post_process_hydro_forces_Stokes_
virtual const Maillage_FT_Disc & maillage_interface_pour_post() const
Renvoie le maillage stocke specialement pour le postraitement (si on veut postraiter un etat intermed...
const Champ_Inc_base & inconnue() const override
const Champ_base & get_indicatrice() override
getter champ variables_internes_->indicatrice_cache a partir de la position des interfaces.
virtual void calculer_distance_interface_faces(const DoubleTab &dist_elem, const DoubleTab &normale_elem, DoubleTab &dist_faces) const
void check_indicatrice_is_up_to_date() override
Checks if the indicator is up to date.
std::vector< YAML_data > data_a_sauvegarder() const override
for PDI IO: retrieve name and type and dimensions of the indicatrice tag
Transport_Interfaces_FT_Disc()
constructeur par defaut
void discretiser() override
Discretisation des champs: - indicatrice_ : champ scalaire discretise aux elements.
void swap_particles_lagrangian_position_velocity()
WARNING, particles_position_collision_ and particles_velocity_collision_ are not used to transport pa...
const Maillage_FT_Disc & maillage_inject() const
virtual void calculer_vitesse_transport_interpolee(const Champ_base &champ_vitesse, const Maillage_FT_Disc &m, DoubleTab &vitesse_noeuds, int nv_calc) const
void fill_ftab_pressure(DoubleTab *ftab, const DoubleTab &dummytab) const
const Probleme_base & get_probleme_base() const
double calculer_pas_de_temps() const override
Calcul du prochain pas de temps.
void integrer_ensemble_lagrange(const double temps) override
virtual const Champ_base & update_indicatrice_faces()
const Proprietes_part_vol & proprietes_inject() const
virtual void PPP_face_interface(Maillage_FT_Disc &maillage, const DoubleTab &indicatrice, const DoubleTab &indicatrice_face, DoubleTab &Vertex)
virtual const Champ_base & get_normale_interface() const
virtual void RenumFa7(DoubleTab &Barycentre, DoubleTab &Tab110, DoubleTab &Tab111, DoubleTab &Tab112, IntTab &Tab12, IntTab &CptFacette, const int nb_facettes, const int nb_facettes_dim)
void fill_ftab_Stokes_pressure_th(DoubleTab *ftab, const DoubleTab &values) const
Post_Processing_Hydrodynamic_Forces post_process_hydro_forces_
virtual void PPP_face_voisin(const DoubleTab &indicatrice, const DoubleTab &indicatrice_face, DoubleTab &PPP)
virtual double calculer_integrale_indicatrice(const DoubleVect &indicatrice, double &v_ph0) const
const OWN_PTR(Collision_Model_FT_base) &get_ptr_collision_model() const
void associer_pb_base(const Probleme_base &probleme) override
S'associe au Probleme passe en parametre.
virtual const Algorithmes_Transport_FT_Disc & algorithmes_transport() const
virtual void plan_facette_existant(Maillage_FT_Disc &maillage, DoubleList A, DoubleList B, DoubleList C, DoubleList D, const int i_facette, int &test_liste)
virtual const Champ_base & get_update_distance_interface_faces() const
const Maillage_FT_Disc & maillage_interface() const
virtual void uzawa(const double d, const DoubleTab &matrice, const DoubleTab &x, const DoubleTab &secmem, DoubleTab &solution) const
virtual const Marching_Cubes & marching_cubes() const
virtual void calcul_eq_plan_facette(Maillage_FT_Disc &maillage, const int i_facette, double &a, double &b, double &c, double &d)
virtual void interpoler_vitesse_face(const DoubleTab &distance_interface, const int phase, const int stencil_width, DoubleTab &champ, DoubleTab &gradient, const double t, const double dt)
void fill_ftab_velocity(DoubleTab *ftab, const DoubleTab &dummytab) const
void ramasse_miettes(const Maillage_FT_Disc &maillage, DoubleVect &flux, DoubleVect &valeurs)
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
virtual void deplacer_maillage_ft_v_fluide(const double temps)
virtual void calcul_tolerance_projete_diphasique(const int i_face, const int ori, const int voisin0, const int voisin1, const DoubleTab &indicatrice, double &tol)
virtual void calcul_OutElemFa7(Maillage_FT_Disc &maillage, const DoubleTab &indicatrice, const int nb_elem, int &nb_fa7_accepted, IntList &OutElem, IntList &OutFa7)
void verifprojete(const int monophasique, const double Lref, double d, const DoubleTab &x, const DoubleTab &V, DoubleTab &coord_projete, int &cpt)
virtual void calcul_maxfa7(Maillage_FT_Disc &maillage, const DoubleTab &indicatrice, const int nb_elem, int &max_fa7, const int exec_planfa7existan)
void fill_ftab_local_reference_frame_velocity(DoubleTab *ftab, const DoubleTab &dummytab) const
static void transfert_conservatif_eulerien_vers_lagrangien_sommets(const Maillage_FT_Disc &maillage, const DoubleVect &valeurs_euler, ArrOfDouble &valeurs_lagrange)
virtual void StockageFa7(Maillage_FT_Disc &maillage, IntTab &CptFacette, DoubleTab &Tab100, DoubleTab &Tab101, DoubleTab &Tab102, DoubleTab &Tab103, DoubleTab &Tab110, DoubleTab &Tab111, DoubleTab &Tab112, IntTab &Tab12, DoubleTab &Barycentre, const DoubleTab &indicatrice, IntList &OutElem, ArrOfBit &fa7, const int exec_planfa7existant)
void mettre_a_jour_hors_deplacement(double temps, const bool update_statio=true, const bool update_indic=true)
Entree & lire_cond_init(Entree &is) override
Lecture des conditions initiales.
int reprendre(Entree &) override
On reprend l'inconnue a partir d'un flot d'entree.
void fill_ftab_Stokes_pressure_interp(DoubleTab *ftab, const DoubleTab &values) const
virtual void projete_point_face_interface(int &nb_proj_modif, const int dim_fa7, const DoubleTab &indicatrice_face, const DoubleTab &indicatrice, const DoubleTab &dist_face, const double t, const double dt, DoubleTab &Tab100, DoubleTab &Tab101, DoubleTab &Tab102, DoubleTab &Tab103, IntTab &Tab12, IntTab &CptFacette, DoubleTab &v_imp, DoubleTab &Vertex, Parser &parser_x, Parser &parser_y, Parser &parser_z)
virtual void BaryFa7(Maillage_FT_Disc &maillage, const int i_facette, DoubleTab &Barycentre)
OBS_PTR(Probleme_base) probleme_base_
virtual void calculer_vmoy_composantes_connexes(const Maillage_FT_Disc &maillage, const ArrOfInt &compo_connexes_facettes, const int nb_compo_tot, const DoubleTab &vitesse_sommets, DoubleTab &vitesses, DoubleTab &positions) const
virtual void calcul_vitesse(DoubleTab &vitesse_imp, const DoubleTab &champ_vitesse, const DoubleTab &vpoint, const double temps, const double dt)
virtual void calculer_vitesse_repere_local(const Maillage_FT_Disc &maillage, DoubleTab &deplacement, DoubleTab &Positions, DoubleTab &Vitesses) const
virtual void calculer_distance_interface_sommets(const DoubleTab &dist_elem, const DoubleTab &normale_elem, DoubleTab &dist_som) const
Calcule dist_som, la distance entre l'interface et les sommets du maillage eulerien a partir de dist_...
void update_normale_distance_interface() const
Calcule la normale et la distance a l'interface, evaluees sur une epaisseur egale a n_iterations_dist...
virtual void projete_point_face_fluide(int &nb_proj_modif, const int dim_fa7, const DoubleTab &indicatrice_face, const DoubleTab &indicatrice, const DoubleTab &dist_face, const double t, const double dt, DoubleTab &Tab100, DoubleTab &Tab101, DoubleTab &Tab102, DoubleTab &Tab103, IntTab &Tab12, IntTab &CptFacette, DoubleTab &v_imp, DoubleTab &Vertex, Parser &parser_x, Parser &parser_y, Parser &parser_z)
void calcul_effort_fluide_interface(const DoubleTab &vpoint, const DoubleTab &rho_faces, DoubleTab &source_val, const int is_explicite, const double eta)
virtual int calculer_composantes_connexes_pour_suppression(IntVect &num_compo)
void set_is_solid_particle(const bool is_solid_particle)
void ajouter_contribution_saut_vitesse(DoubleTab &deplacement, const bool la_roue_de_vitesse_a_deja_tournee) const
virtual const Champ_base & get_distance_interface() const
void modifier_vpoint_pour_imposer_vit(const DoubleTab &inco_val, DoubleTab &vpoint0, DoubleTab &vpoint, const DoubleTab &rho_faces, DoubleTab &terme_source, const double temps, const double dt, const int is_explicite, const double eta) override
virtual const int & get_n_iterations_distance() const
void assembler(Matrice_Morse &mat_morse, const DoubleTab &present, DoubleTab &secmem) override
classe Transport_Interfaces_base Cette classe constitue la classe de base des equations de transport ...
classe YAML_data : collection of all needed information for data to save/restore in order to write th...
Definition YAML_data.h:26
void set_local(bool l)
Definition YAML_data.h:35