TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Remailleur_Collision_FT_Thomas.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 <Remailleur_Collision_FT_Thomas.h>
17#include <Domaine_VF.h>
18#include <Domaine.h>
19#include <Param.h>
20#include <communications.h>
21#include <SFichier.h>
22#include <Synonyme_info.h>
23
24Implemente_instanciable_sans_constructeur(Remailleur_Collision_FT_Thomas,"Remailleur_Collision_FT_Thomas",Remailleur_Collision_FT_Juric);
25Add_synonym(Remailleur_Collision_FT_Thomas, "Thomas");
26
30
31/*! @brief Lecture des parametres dans le fichier .
32 *
33 * data
34 *
35 */
37{
38 Cerr << "Remailleur_Collision_FT_Thomas::readOn()" << finl;
39 Param param(que_suis_je());
40 param.ajouter_flag("tester", & tester_);
41 param.ajouter("distance_interface_element_max", & distance_utilisateur_);
42 param.lire_avec_accolades_depuis(is);
43
44 if (tester_)
45 Cerr << " Test des fonctions de Remailleur_Collision_FT_Thomas." << finl;
46 if (distance_utilisateur_ <= 0.)
47 {
48 Cerr << "Error: distance_interface_element_max must be positive" << finl;
49 barrier();
51 }
52 return is;
53}
54
55/*! @brief Erreur.
56 *
57 * Pas code.
58 *
59 */
61{
62 Cerr << "Erreur Remailleur_Collision_FT_Thomas::printOn() n'est pas code." << finl;
64 return os;
65}
66
67//Initialise les attributs "voisinage_sommet_" et "next_elem_" qui sont des IntTab
68//et qui forment a eux deux une liste chainee
69//Principe : a un numero d'element eulerien "k" et a un numero local de sommet "sloc"
70//correspondent deux numeros uniques ;
71//-le numero global "sglob" associe a "sloc"
72//-l'entier "p" definit par p=k*nb_som_elem+sloc.
73//Si l'on realise la division euclidienne de "p" par "nb_som_elem", nous retrouvons
74//facilement le numero globlal du sommet associe a "sloc" et l'element eulerien "k" qui le contient.
75//Par consequent, dans "voisinage_sommet_[si]" on stocke le "p" qui correspond au premier
76//element "k" contenant "si", dans "next_elem[p]" l'entier "p1" qui contient le second
77//element "k1" contenant "si", dans "next_elem[p1]" l'entier "p2" qui contient le
78//troisieme element "k2" contenant "si" ... jusqu'a la fin de liste repere par -1.
79//Soit "s" un sommet du maillage eulerien.
80//REMARQUE : il n'y a pas redondance d' elements dans les differentes
81//listes "voisinage_sommet_[s]"
82//REMARQUE : pour le parallele, on stocke egalement les elements voisins qui sont virtuels
84{
85 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
86 const Domaine& domaine = domaine_VF.domaine();
87
88 const int nb_elem_tot = domaine.nb_elem_tot();
89 const int nb_som_elem = domaine.nb_som_elem();
90 const int end_liste = -1;
91
92 //Tableau des sommets par element
93 const IntTab& elem_sommets = domaine.les_elems();
94
95 assert(voisinage_sommet_.dimension_tot(0) == domaine.nb_som_tot());
96 assert(next_elem_.dimension_tot(0) == domaine.nb_elem_tot()*domaine.nb_som_elem());
97
98 voisinage_sommet_ = end_liste;
99
100 //Construction du voisinage d'un sommet "s" :
101 //On boucle sur un element "elem" dont on stocke le numero global
102 //On boucle sur les sommets "s_i" de "elem" dont on recupere les numeros globaux
103 //Si "voisinage_sommet_[s_i] = -1, on initialise "voisinage_sommet_[s_i]" a "elem*nb_som_elem+numero_local_sommet"
104 //Si "voisinage_sommet_[s_i] = l != -1 :
105 //on calcule "elem*nb_som_elem+numero_local_sommet"
106 //on transfere la valeur "l" dans "next_elem["elem*nb_som_elem+numero_local_sommet"]
107 //on modifie "voisinage_sommet_[s_i]" que l'on fixe a "elem*nb_som_elem+numero_local_sommet"
108 for (int elem=0; elem<nb_elem_tot; elem++)
109 for (int som=0; som<nb_som_elem; som++)
110 {
111 const int som_global =
112 domaine.get_renum_som_perio(elem_sommets(elem,som));
113
114 const int p = nb_som_elem*elem+som;
115
116 next_elem_[p] = voisinage_sommet_[som_global];
117 voisinage_sommet_[som_global] = p;
118 }//fin des for
119
120 tmp_flag_elements_.resize_array(nb_elem_tot);
121 tmp_flag_elements_ = 0;
122 return 1;
123}
124
125
126//Mets a jour l'attribut "distance_interface_element_eulerien" qui est un tableau d'entiers
127//Un element eulerien a la distance 0 de l'interface est un element traverse par l'interface
128//et tel que la surface de cette portion d'interface soit non nulle
129//Un element eulerien a la distance 1 de l'interface est un element voisin d'un element a distance 0
130//qui n'est pas lui-meme a distance 0
131//Et ainsi de suite ...
132//Voisinage d'un sommet "s" := union des elements possedant ce sommet
133//Voisinage d'un element "elem" := union des voisinages des sommets "s_i" de "elem"
134//Mets a jour l'attribut "nombre_de_voisins_plus_proches_" qui est tableau d'entiers
135//Est associe a un element eulerien, le nombre des ses elements voisins qui sont
136//plus proches de l'interface qu'il ne l'est lui-meme
137//Mets a jour l'attribut "surface_interface_elements_voisins_" qui est un tableau de double
138//A un element eulerien a distance 0 de l'interface est associe la surface d'interface le traversant
139//A un element eulerien a distance 1 de l'interface est associe la somme des surfaces d'interface
140//traversant ses voisins a distance 0 de l'interface
142{
143 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
144 const Domaine& domaine = domaine_VF.domaine();
145
146 const Intersections_Elem_Facettes& intersection_elem_facettes =
148
149 const ArrOfInt& index_facette = intersection_elem_facettes.index_facette();
150
151 const int nb_elem_tot = domaine.nb_elem_tot();
152 const int nb_elem = domaine.nb_elem();
153 const int nb_facettes_interface = maillage.nb_facettes();
154 const int seen = 1;
155
156 int nb_elem_parcourus = 0;
157 int numero_voisinage = 0;
158
159 //Indispensable pour le parallele : il faut s'assurer
160 //que les procs effectuent bien le meme nombre de boucle.
161 //Ce nombre est cree pour assurer cette contrainte.
162 int ready_to_quit = 0;
163
164 //Indispensable pour le parallele mais LOCAL a chaque proc
165 //Ne stocke des valeurs utiles que pour les elements VIRTUELS
166 IntTab vu_localement(nb_elem_tot-nb_elem);
167
168 //Par convention :
169 //"elem_proches" pointe toujours sur la liste des elements les plus
170 //proches de l'interface
171 //"elem_eloignes" pointe toujours sur la liste des elements les plus
172 //eloignes de l'interface
173 ArrOfInt elements_proches(nb_facettes_interface),elements_eloignes(3*nb_facettes_interface);
174 ArrOfInt *elem_proches, *elem_eloignes; //eloignes = distance_(x+1)
175
176 elements_proches.resize_array(0);
177 elements_eloignes.resize_array(0);
178
179 elem_proches = &(elements_proches);
180 elem_eloignes = &(elements_eloignes);
181
182
183 //
184 //Initialisation des attributs "distance_interface_element_eulerien_"
185 //"nombre_de_voisins_plus_proches_" et "surface_interface_elements_voisins_"
186 //
187 distance_interface_element_eulerien_=-1;
188 nombre_de_voisins_plus_proches_=0;
189 surface_interface_elements_voisins_=0.;
190 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
191 //
192 //Initialisation des elements a distance 0 de l'interface
193 //Initialisation du nombre de voisins plus proches de ces memes elements
194 //Initialisation de la surface totale d'interface traversant ces memes elements
195 //
196 for (int facette=0; facette<nb_facettes_interface; facette++)
197 {
198 const double surface_facette = surface_facettes[facette];
199 //
200 //Parcours des elements REELS traverses par "facette"
201 //et initialisation de la liste des elements REELS a
202 //distance 0 de l'interface, du nombre de leurs
203 //voisins les plus proches, de la surface totale
204 //d'interface les traversant
205 //
206 int index = index_facette[facette];
207
208 while (index >= 0)
209 {
211 intersection_elem_facettes.data_intersection(index);
212
213 const int elem = data.numero_element_;
214 assert(elem<nb_elem);
215
216 //Condition determinant les elements a distance 0 de l'interface
217 if (distance_interface_element_eulerien_[elem]==-1 && data.fraction_surface_intersection_!=0.)
218 {
219 distance_interface_element_eulerien_[elem] = 0;
220 elem_proches->append_array(elem);
221 }
222
223 //Calcul de la surface d'interface coupant les elements a distance
224 //0 de cette meme interface
225 surface_interface_elements_voisins_[elem] += data.fraction_surface_intersection_ * surface_facette;
226
227
228 index = data.index_element_suivant_;
229 }//fin du while
230
231 }//fin du for sur facette
232
233
234 //Pour le parallele : il faut s'assurer que les processus en cours
235 //ont bien finis leurs boucles respectives
236 distance_interface_element_eulerien_.echange_espace_virtuel();
237 surface_interface_elements_voisins_.echange_espace_virtuel();
238
239 //Nous comptons les elements deja parcourus :
240 //nous ne pouvons pas utiliser seulement la fonction size_array()
241 //des ArrOfInt appliquee a "elem_proches" parce que nous parcourons
242 //des elements REELS par definition de la structure de donnee "data".
243 //Or nous voulons parcourir tous les elements y compris les elements
244 //VIRTUELS. D'ou l'astuce suivante qui doit etre realisee APRES
245 //la fonction echange_espace_virtuel().
246 //De meme, il faut rajouter dans la liste "elem_proches" les elements
247 //VIRTUELS qui sont a distance 0 de l'interface
248 nb_elem_parcourus+=elem_proches->size_array();
249
250 for (int elem=nb_elem; elem<nb_elem_tot; elem++)
251 if (surface_interface_elements_voisins_[elem]>0.)
252 {
253 elem_proches->append_array(elem);
254 nb_elem_parcourus++;
255 }
256
257 //
258 //Initialisation des autres elements a distance >= 1 de l'interface
259 //Principe : supposant connu les element a distance n de l'interface,
260 //nous recherchons les voisins de ces elements dont la distance n'a
261 //pas encore ete calculee (distance = -1)
262 //Nous initialisons alors l'attribut "distance_interface_element_eulerien_"
263 //avec la valeur appropriee
264 //Initialisation de "nombre_de_voisins_plus_proches"
265 //Initialisation de "surface_interface_elements_voisins_"
266 //REMARQUE : il faut s'assurer que chaque proc effectue le meme nombre de
267 //boucles d'ou le test initial de la boucle while
268 //
269 ready_to_quit = (int) Process::mp_min(ready_to_quit);
270 ArrOfInt elem_voisins;
271
272 while (!ready_to_quit)
273 {
274 const int taille_liste = elem_proches->size_array();
275 numero_voisinage++;
276
277 //Pour le parallele : il faut reinitialiser la variable
278 //a chaque nouveau front que l'on souhaite parcourir
279 vu_localement = !seen;
280
281 //Pour le parallele : il faut reinitialiser la variable
282 //a chaque nouveau front que l'on souhaite parcourir
283 for (int elem_loc=0; elem_loc<taille_liste; elem_loc++)
284 {
285 //Obtention des elements voisins de "elem"
286 const int elem_glob = (*elem_proches)[elem_loc];
287 elements_voisins(elem_glob,elem_voisins,domaine_VF);
288 const int nb_elem_voisins = elem_voisins.size_array();
289 const int distance_elem = distance_interface_element_eulerien_[elem_glob];
290
291 //Boucle sur les elements voisins qui peuvent etre VIRTUELS
292 for (int elem_voisin_loc=0; elem_voisin_loc<nb_elem_voisins; elem_voisin_loc++)
293 {
294 const int elem_voisin_glob = elem_voisins[elem_voisin_loc];
295
296 //Initialisation locale de l'attribut "distance_interface_element_eulerien_"
297 if (distance_interface_element_eulerien_[elem_voisin_glob]==-1)
298 {
299 distance_interface_element_eulerien_[elem_voisin_glob] = numero_voisinage;
300 elem_eloignes->append_array(elem_voisin_glob);
301 if (elem_voisin_glob>=nb_elem) vu_localement[elem_voisin_glob-nb_elem]=seen;
302 }
303
304 //Initialisation des attributs "nombre_de_voisins_plus_proches"
305 //et "surface_interface_elements_voisins_"
306 //ATTENTION : cette petite boucle doit imperativement venir apres
307 //l'initialisation locale de "distance_interface_element_eulerien_"
308 const int distance_elem_voisin = distance_interface_element_eulerien_[elem_voisin_glob];
309
310 if (distance_elem_voisin>distance_elem)
311 {
312 //Il suffit d'ajouter 1 au nombre des voisins les plus proches
313 //de "elem_voisin_glob"
314 nombre_de_voisins_plus_proches_[elem_voisin_glob]++;
315
316 //Nous ne voulons tenir compte des surfaces que si "distance_elem_voisin==1"
317 if (distance_elem==0)
318 {
319 //pour s'assurer que l'on a pas fait d'erreur
320 assert(distance_elem_voisin==1);
321 surface_interface_elements_voisins_[elem_voisin_glob] += surface_interface_elements_voisins_[elem_glob];
322 }//fin du if sur "distance_elem==0"
323
324 }//fin du if sur "distance_elem_voisin>distance_elem"
325
326 }//fin du for sur "elem_voisin_loc"
327
328 }//fin du for sur "elem_loc"
329
330 //Pour le parallele : il faut s'assurer que les processus en cours
331 //ont bien finis leurs boucles respectives
332 distance_interface_element_eulerien_.echange_espace_virtuel();
333
334
335 //Nous incrementons le compteur
336 //Il faut faire les memes manip que pour les elements
337 //a distance 0 de l'interface en prenant garde, en plus, de ne
338 //pas rajouter des elements dans "elements_eloignes"
339 //qui y ont deja ete place lors du traitement LOCAL, i.e.
340 //avant l'usage de la fonction echange_espace_virtuel()
341 nb_elem_parcourus+=elem_eloignes->size_array();
342
343 for (int elem=nb_elem; elem<nb_elem_tot; elem++)
344 {
345 const int test_distance = (distance_interface_element_eulerien_[elem]==numero_voisinage);
346 const int test_vu = (vu_localement[elem-nb_elem]!=seen);
347
348 if ( test_distance && test_vu)
349 {
350 elem_eloignes->append_array(elem);
351 nb_elem_parcourus++;
352 }
353
354 }//fin du for sur "elem"
355
356
357 //
358 //Swap des pointeurs pour ne pas couter trop cher en memoire
359 //
360 ArrOfInt *temporaire;
361 elem_proches->resize_array(0);
362 temporaire = &(*elem_proches);
363 elem_proches = &(*elem_eloignes);
364 elem_eloignes = &(*temporaire);
365
366 //
367 //Pour mettre a jour le test sur la boucle while
368 //Un processeur est pret a quitter la boucle while() :
369 //s' il a parcouru tous les elements du maillage local
370 //OU s'il a atteint la distance imposee par l'utilisateur
371 //
372 ready_to_quit = (nb_elem_parcourus == nb_elem_tot) || (numero_voisinage == distance_utilisateur_);
373 ready_to_quit = (int) Process::mp_min(ready_to_quit);
374
375 }//fin du while
376
377 assert(nb_elem_parcourus==nb_elem_tot || numero_voisinage==distance_utilisateur_);
378
379 //Pour le parallele : il faut s'assurer que les processus en cours
380 //ont bien finis leurs boucles respectives
381 nombre_de_voisins_plus_proches_.echange_espace_virtuel();
382 surface_interface_elements_voisins_.echange_espace_virtuel();
383
384 //Inititalisation de l'attribut "plus_grande_distance_interface_element_eulerien_"
385 //REMARQUE IMPORTANTE : cet attribut sera identique sur tous les procs
386 plus_grande_distance_interface_element_eulerien_ = numero_voisinage ;
387 assert_parallel(plus_grande_distance_interface_element_eulerien_);
388
389 return 1;
390}
391
392
393//Soit un element "elem" (numero global) passe en argument.
394//PRINCIPE
395//Si le remaillage de l'interface ne conduit pas a une perte de volume dans "elem" : sortie
396//Si le remaillage conduit a une perte de volume dans "elem " alors :
397// Si "elem" est a distance n > 1 de l'interface, on distribue equitablement le volume
398// perdu sur l'ensemble des elements voisins de "elem" a distance n-1
399// Si "elem" est a distance n = 1, on distribue le volume perdu sur l'ensemble
400// des voisins de "elem" a distance 0 de l'interface, proportionnellement a la surface
401// d'interface contenue dans ces memes voisins.
402// Si "elem" est a distance n = 0, on ne transporte pas le volume perdu : sortie
403//Voisinage d'un sommet "s" := ensemble des elements contenant "s"
404//Voisinage d'un element "K" := union des voisinages des sommets "si" de "K"
405//Valeurs de sortie : 1 => pas de volume perdu
406// 2 => pas de transport du volume perdu pour une maille a distance 0 de l'interface
407// 3 => transport du volume perdu pour une maille a distance de l'interface >1
408// 4 => transport du volume perdu pour une maille a distance de l'interface =1
409// -1 => situation problematique (une erreur s'est produite)
411{
412 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
413 const Domaine& domaine = domaine_VF.domaine();
414
415 const int nb_elem = domaine.nb_elem();
416 const int distance_interface_elem = distance_interface_element_eulerien_[elem];
417
418 //int distance_interface_elem_voisin = -2;
419
420 ArrOfInt voisins_a_distance_plus_petite;
421
422 if (volume_perdu_[elem]==0) return 1; //pas de volume perdu => sortie
423
424 //
425 //Si nous arrivons ici, c'est que du volume a ete perdu.
426 //Nous mettons en place l'algorithme de transport
427 //
428
429 //Construction de la liste des elements voisins de "elem"
430 //a distance de l'interface strictement plus petite que la distance
431 //separant "elem" de l'interface.
432 elements_voisins(elem, voisins_a_distance_plus_petite, domaine_VF);
433 elements_voisins_a_distance_plus_petite2(elem, voisins_a_distance_plus_petite);
434
435 const int nb_voisins_a_distance_plus_petite = voisins_a_distance_plus_petite.size_array();
436
437
438 switch (distance_interface_elem)
439 {
440
441 case -1 :
442
443 Cerr << "Erreur Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_element()" << finl;
444 Cerr << "La distance separant l'interface de l'element eulerien " << elem
445 << " est strictement superieur a " << distance_utilisateur_ << finl;
446 Cerr << "L'utilisateur a demande de ne considerer que les elements situes a une distance d'au plus "
447 << distance_utilisateur_ << " de l'interface" << finl;
448 Cerr << "Sortie du programme." << finl;
450
451 // bfa : necessary to avoid a compilation error "[-Werror=implicit-fallthrough=]"
452 return -1;
453
454 case 0 :
455 return 2;//pas de transport => sortie
456
457 case 1 :
458
459 assert(nb_voisins_a_distance_plus_petite!=0 || elem>=nb_elem);
460 assert(nb_voisins_a_distance_plus_petite<=nombre_de_voisins_plus_proches_[elem]);
461 if (elem<nb_elem) assert(nb_voisins_a_distance_plus_petite==nombre_de_voisins_plus_proches_[elem]);
462
463 //Repartition du volume selon les principes enonces.
464 //Utilisation de l'attribut "surface_interface_elements_voisins_" dont nous rappelons
465 //la definition ici :
466 //Aux elements "elem" a distance 0 correspond la surface d'interface qui les coupe
467 //Aux elements "elem" a distance 1 correspond la somme des surfaces d'interface qui coupe
468 //les voisins des "elem" a distance 0 de l'interface
469 for (int elem_loc=0; elem_loc<nb_voisins_a_distance_plus_petite; elem_loc++)
470 {
471 const int elem_voisin = voisins_a_distance_plus_petite[elem_loc];
472
473
474 assert(distance_interface_elem-distance_interface_element_eulerien_[elem_voisin]==1);
475 volume_perdu_[elem_voisin]+=volume_perdu_[elem]*surface_interface_elements_voisins_[elem_voisin]
476 /surface_interface_elements_voisins_[elem];
477
478 }//fin du for sur "elem_loc"
479
480 //remise a zero pour plus de surete
481 volume_perdu_[elem]=0.;
482
483 return 4;
484
485 default :
486
487 assert(nb_voisins_a_distance_plus_petite!=0 || elem>=nb_elem);
488 assert(nb_voisins_a_distance_plus_petite<=nombre_de_voisins_plus_proches_[elem]);
489 if (elem<nb_elem) assert(nb_voisins_a_distance_plus_petite==nombre_de_voisins_plus_proches_[elem]);
490
491 //Repartition du volume selon les principes enonces.
492 for (int elem_loc=0; elem_loc<nb_voisins_a_distance_plus_petite; elem_loc++)
493 {
494 const int elem_voisin = voisins_a_distance_plus_petite[elem_loc];
495
496 assert(distance_interface_elem- distance_interface_element_eulerien_[elem_voisin]==1);
497 volume_perdu_[elem_voisin]+=volume_perdu_[elem]/nombre_de_voisins_plus_proches_[elem];
498
499 }//fin du for sur "elem_loc"
500
501 //remise a zero pour plus de surete
502 volume_perdu_[elem]=0.;
503
504 return 3;
505
506 }//fin du "switch"
507}
508
509
510//Fonction qui transporte le volume perdu lors du remaillage sur les elements
511//euleriens a distance 0 de l'interface
512//PRINCIPE
513//Nous creons une liste chainee qui a partir d'une distance d'interface donnee "n"
514//nous donnes l'ensemble des elements euleriens "elem" a distance "n"
515//Ensuite, nous utilisons la fonction "transport_volume_perdu_sur_element(const int&, const Maillage_FT_Disc&)
516//recursivement, en partant des elements a la plus grande distance de l'interface pour aller
517//vers les elements a la plus petite distance de l'interface i.e. ceux a distance 0
518//RETOUR : la valeur du volume perdu qui a ete transporte
519//REMARQUE : l'attribut "distance_interface_element_eulerien_" doit etre initialise
521{
522 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
523 const Domaine& domaine = domaine_VF.domaine();
524
525 const int nb_elem = domaine.nb_elem();
526 const int nb_elem_tot = domaine.nb_elem_tot();
527 const int end_liste = -1;
528
529 //Construction de la liste chainee distance->{ensemble des elements a cette distance}
530 //Principe : Creation d'une premiere liste de taille "plus_grande_distance_interface_element_eulerien_"
531 // et initialisee a -1
532 // A la distance "n" sera stocke un element "elem" a distance "n" de l'interface
533 // Creation d'une deuxieme liste de taille "nb_elem_tot" initialisee a -1
534 // A la place "elem" est stocke le numero "elem2" d'un deuxieme element a distance "n"
535 // A la place "elem2" est stocke le numero "elem3" d'un deuxieme element a distance "n" etc
536 // La fin de la liste chainee est reperee par un -1
537
538 IntTab distance_des_elements(plus_grande_distance_interface_element_eulerien_+1);
539 IntTab suite_des_elements(nb_elem_tot);
540 distance_des_elements = end_liste;
541 suite_des_elements = end_liste;
542
543 assert(nb_elem_tot==distance_interface_element_eulerien_.dimension_tot(0));
544
545 //Boucle sur "distance_interface_element_eulerien_" afin de modifier nos listes
546 for (int elem=0; elem<nb_elem_tot; elem++)
547 {
548 const int distance = distance_interface_element_eulerien_[elem];
549
550 if (distance==-1) continue; //on passe tout de suite a l'element suivant
551 assert(distance<=plus_grande_distance_interface_element_eulerien_);
552
553 suite_des_elements(elem)=distance_des_elements(distance);
554 distance_des_elements(distance)=elem;
555
556 }//fin du for sur "elem"
557
558
559 //
560 //Transport du volume perdu proprement dit
561 //L'attribut "plus_grande_distance_interface_element_eulerien_" etant identique
562 //sur tous les procs, il n'y a pas de precautions particulieres a prendre
563 //
564 for (int distance=plus_grande_distance_interface_element_eulerien_; distance!=-1; distance--)
565 {
566 //Parcours de tous les elements "elem" situes a la distance "distance" de l'interface
567 //et transport du volume perdu
568 for (int elem=distance_des_elements(distance); elem!=-1; elem=suite_des_elements(elem))
570
571 //Pour le parallele : il faut s'assurer que les processus en cours
572 //ont bien finis leurs boucles respectives
573 volume_perdu_.echange_espace_virtuel();
574
575 }//fin du for sur "distance"
576
577 //
578 //Calcul du volume perdu transporte sur les elements
579 //a distance 0 de l'interface
580 //
581 double volume_perdu_transporte = 0.;
582
583 for (int elem=0; elem<nb_elem; elem++)
584 if (!distance_interface_element_eulerien_[elem])
585 volume_perdu_transporte += volume_perdu_[elem];
586
587 return volume_perdu_transporte;
588}
589
590
591
592//Fonction qui donne la liste des elements voisins a un element "elem" (numero global) donne
593//Voisinage d'un sommet "s" := ensemble des elements du maillage contenant "s"
594//Voisinage d'un element "elem" := union des voisinages des sommets "si" de "elem"
595//REMARQUE : un element de la liste "liste_voisins" n'est present qu'une seule fois
596//REMARQUE : les attributs "voisinage_sommet_" et "next_elem_" doivent etre initialises
597//REMARQUE : le parametre "liste_voisins" doit avoir une taille initiale differente de "0"
598//(astuce de gestion memoire avec l'objet ArrOfInt)
599//REMARQUE : pour le parallele, "liste_voisins" contient egalement des elements voisins virtuels
600//VOIR : Remailleur_Collision_FT_Thomas::voisinage_sommets()
602 ArrOfInt& liste_voisins,
603 const Domaine_dis_base& un_domaine_dis) const
604{
605 // const Maillage_FT_Disc& maillage = ;
606 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,un_domaine_dis);
607 const Domaine& domaine = domaine_VF.domaine();
608
609 const int nb_som_elem = domaine.nb_som_elem();
610 const int end_liste = -1;
611
612 //Tableau des sommets par element
613 const IntTab& elem_sommets = domaine.les_elems();
614
615
616 liste_voisins.resize_array(0);
617
618 //Calcul du voisinage
619 for (int som=0; som<nb_som_elem; som++)
620 {
621 const int som_global = domaine.get_renum_som_perio(elem_sommets(elem,som));
622
623 //On parcourt la liste des elements "elem_voisin" qui contiennent "som_global"
624 for (int p=voisinage_sommet_[som_global]; p!=end_liste; p=next_elem_[p])
625 {
626 const int elem_voisin = p/nb_som_elem;
627 assert(som_global==domaine.get_renum_som_perio(elem_sommets(elem_voisin,p%nb_som_elem)));
628 if (!tmp_flag_elements_.testsetbit(elem_voisin))
629 liste_voisins.append_array(elem_voisin);
630 }
631 }
632
633 const int n = liste_voisins.size_array();
634 for (int i = 0; i < n; i++)
635 tmp_flag_elements_.clearbit(liste_voisins[i]);
636
637 return 1;
638}
639
640
641//Fonction qui donne la liste des elements voisins a un element "elem" (numero global) donne et
642//situes a une distance de l'interface strictement plus petite que la distance separant "elem"
643//de l'interface. (normalement la difference des deux distances doit etre de 1)
644// Changement (BM): on suppose que liste_voisins contient le resultat de la fonction elements_voisins()
645//Voisinage d'un sommet "s" := ensemble des elements du maillage contenant "s"
646//Voisinage d'un element "elem" := union des voisinages des sommets "si" de "elem"
647//Entree : l'element "elem" dont on veut la liste des voisins
648//Entree ET Sortie : la liste des voisins a distance de l'interface plus petite que la distance
649//separant "elem" de l'interface
650//REMARQUE : un element de la liste "liste_voisins" n'est present qu'une seule fois
651//REMARQUE : l'attribut "distance_interface_element_eulerien_" doit etre initialise
652//REMARQUE : pour le parallele, "liste_voisins" contient egalement des elements voisins virtuels
653//VOIR : Remailleur_Collision_FT_Thomas::voisinage_sommets() et Remailleur_Collision_FT_Thomas::elements_voisins()
655 ArrOfInt& liste_voisins) const
656{
657 const int distance_interface_elem = distance_interface_element_eulerien_[elem];
658 const int n = liste_voisins.size_array();
659 int j = 0;
660
661 for (int i = 0; i < n; i++)
662 {
663 const int elem_voisin = liste_voisins[i];
664 const int distance_interface_elem_voisin = distance_interface_element_eulerien_[elem_voisin];
665
666 const bool is_plus_petit = distance_interface_elem_voisin<distance_interface_elem;
667 const bool is_positif = distance_interface_elem_voisin>-1;
668
669 if (is_positif && is_plus_petit)
670 {
671 assert(distance_interface_elem-distance_interface_elem_voisin==1);
672 liste_voisins[j] = elem_voisin;
673 j++;
674 }
675 }
676 liste_voisins.resize_array(j);
677
678 return 1;
679}
680
681
682
683
684//Fonction qui donne le nombre d'elements voisins a un element "elem" (numero global) donne
685//Voisinage d'un sommet "s" := ensemble des elements du maillage contenant "s"
686//Voisinage d'un element "elem" := union des voisinages des sommets "si" de "elem"
687//REMARQUE : pour le parallele, cette fonction comptabilise egalement les elements voisins virtuels
688//VOIR : Remailleur_Collision_FT_Thomas::elements_voisins()
689int Remailleur_Collision_FT_Thomas::nb_elements_voisins(const int elem, const Domaine_dis_base& un_domaine_dis) const
690{
691 ArrOfInt liste_voisins;
692 elements_voisins(elem,liste_voisins,un_domaine_dis);
693 return liste_voisins.size_array();
694}
695
696//Fonction qui donne le nombre d'elements voisins a un element "elem" (numero global) donne
697//situes a une distance de l'interface plus petite que la distance separant "elem" de
698//l'interface.
699//Voisinage d'un sommet "s" := ensemble des elements du maillage contenant "s"
700//Voisinage d'un element "elem" := union des voisinages des sommets "si" de "elem"
701//REMARQUE : pour le parallele, cette fonction comptabilise egalement les elements voisins virtuels
702//VOIR : Remailleur_Collision_FT_Thomas::elements_voisins_a_distance_plus_petite()
704{
705 ArrOfInt liste_voisins;
706 elements_voisins(elem,liste_voisins,un_domaine_dis);
708 return liste_voisins.size_array();
709}
710
712{
713 assert(nombre_de_voisins_plus_proches_.dimension_tot(0)>elem);
714 return nombre_de_voisins_plus_proches_[elem];
715}
716
717
718//Fonction qui assure le remaillage de l'interface.
719//Cette fonction calcule, en outre, le volume perdu dans l'operation de remaillage,
720//et le redistribue de facon a ce que le volume de occupe par l'indicatrice de phase
721//soit identique avant et apres l'operation de remaillage topologique.
722//Remarque : on suppose que les valeurs de l'interface sont connues dans
723//chaque element du maillage eulerien.
725 Champ_base& indicatrice)
726{
727 Journal() << "Remailleur_Collision_FT_Thomas::traite_RuptureCoalescenceInterfaces_Conservatif" << finl;
728 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
729 const Domaine& domaine = domaine_VF.domaine();
730
731 const DoubleVect& volumes_elements_euleriens = domaine_VF.volumes();
732
733 const int nb_elements_euleriens = domaine.nb_elem();
734 const int nb_elements_euleriens_tot = domaine.nb_elem_tot();
735
736 int ok_mise_a_jour = 0, ok_remailleur = 0;
737
738 const double temps = maillage.temps();
739 double volume_initial = 0.;
740 double volume_final = 0.;
741 double le_volume_perdu = 0.;
742 double volume_perdu_elements = 0.;
743 double volume_perdu_sommets = 0.;
744
745 ArrOfDoubleFT variation_volume;
746
747 Champ_base& indicatrice_finale = indicatrice; //pour l'initialisation slt
748
749 assert(indicatrice.valeurs().dimension_tot(0)==nb_elements_euleriens_tot);
750 assert(volumes_elements_euleriens.size_totale()==nb_elements_euleriens_tot);
751
752 //On dimensionne les donnees qui nous interesse
753 if (!est_dimensionne_) initialiser_data(maillage);
754 assert(est_dimensionne_);
755
756 //On initialise l'attribut "volume_perdu_" et
757 //mise a jour entre procs
758 //On calcule le volume initial avant remaillage
759 volume_perdu_ = indicatrice.valeurs();
760 volume_perdu_.echange_espace_virtuel();
761
762 for (int elem=0; elem<nb_elements_euleriens; elem++)
763 volume_initial += indicatrice.valeurs()[elem]*volumes_elements_euleriens[elem];
764
765 volume_initial = Process::mp_sum(volume_initial);
766
767 //On remaille topologiquement puis conservativement
768 //pour obtenir une surface lisse, i.e. sans angle
769 //trop prononce
770 ok_remailleur =
772
773 remaillage_FT(maillage).remaillage_local_interface(temps, maillage);
774
775 //On modifie l'attribut "volume_perdu_" et on calcule
776 //le volume total perdu dans l'operation de remaillage
777 //REMARQUE : le maillage a change apres le remaillage
778 // et donc l'indicatrice egalement
780
781 volume_perdu_ -= maillage.equation_transport().get_indicatrice().valeurs();
782 volume_perdu_.echange_espace_virtuel();
783
784 for (int elem=0; elem<nb_elements_euleriens_tot; elem++)
785 volume_perdu_[elem] *= volumes_elements_euleriens[elem];
786
787 volume_perdu_.echange_espace_virtuel();
788
789 for (int elem=0; elem<nb_elements_euleriens; elem++)
790 le_volume_perdu+=volume_perdu_[elem];
791
792 le_volume_perdu = Process::mp_sum(le_volume_perdu);
793
794
795 //Nous executons la suite de l'algo a savoir :
796 //calcul des voisinages
797 //calcul des distances a l'interface
798 //transport des volumes perdus
799 //calcul des volumes perdus par sommet de l'interface
800 //L'etat du maillage est suppose etre au moins : PARCOURU
801 variation_volume.resize_array(maillage.nb_sommets());
802 variation_volume = 0.;
803
804 maillage.parcourir_maillage();
805 ok_mise_a_jour = mettre_a_jour_data(maillage);
806
807 //Verification du bon deroulement des evenements
808 int ok = ok_remailleur*ok_mise_a_jour;
809 assert(ok);
810
811 //Pour le debug
812 if (tester_) tester(maillage);
813
814 //On transporte le volume perdu jusqu'aux elements a distance 0 de l'interface
815 //On en profite pour calculer le volume total transporte
816 volume_perdu_elements = transport_volume_perdu_sur_element(maillage);
817 volume_perdu_elements = Process::mp_sum(volume_perdu_elements);
818
819 //On transporte le volume perdu aux sommets du maillage de l'interface
820 //On en profite pour calculer le volume total redistribue sur les sommets
821 volume_perdu_sommets = transport_volume_perdu_sur_sommet(variation_volume, maillage);
822 volume_perdu_sommets = Process::mp_sum(volume_perdu_sommets);
823
824 //On deplace les sommets de l'interface pour corriger le volume
825 //puis on calcule le volume finalement obtenu
826 //PARAMETRE : le tableau "variation_volume" calcule ci-dessus
827 //PRINCIPE : lissage puis deplacement des sommets
828 remaillage_FT(maillage).lisser_dvolume(maillage,variation_volume,5);
829 variation_volume*=-1.;
830 remaillage_FT(maillage).corriger_volume(maillage,variation_volume);
831
832 // sometimes the mesh is changed before this, sometimes not
833 // for that we have to change the mesh tag, but not the one of maillage
835 const Maillage_FT_Disc& mesh = eq.maillage_interface();
836 mesh.mesh_tag_increase();
838 indicatrice_finale = maillage.equation_transport().get_indicatrice();
839 for (int elem=0; elem<nb_elements_euleriens; elem++)
840 volume_final += indicatrice_finale.valeurs()[elem]*volumes_elements_euleriens[elem];
841
842 volume_final = Process::mp_sum(volume_final);
843
844 //On affiche la perte de volume calculee
845 Journal() << "Perte de volume due au remaillage : " << le_volume_perdu << " "
846 << volume_perdu_elements << " " << volume_perdu_sommets
847 << "\nVolume initial : " << volume_initial
848 << " volume final : " << volume_final << finl;
849
850 return ok;
851}
852
853//Fonction qui a chaque sommet du maillage de l'interface associe une partie du
854//volume perdu dans l'element "elem" lors du remaillage
855//Principe : si du volume a ete perdu sur la maille eulerienne "elem" traversee par l'interface
856// alors une fraction de ce volume est distribue sur chaque sommet "s" de l'interface coupant "elem".
857// Pour cela, pour chaque facette "fa7" coupant "elem", nous calculons un volume perdu surfacique
858// "volume_perdu_surfacique" qui est le volume perdu dans "elem" divise par la surface de l'intersection de
859// "fa7" dans "elem", nous divisons "volume_perdu_surfacique" par la surface totale d'intersection entre
860// l'interface et "elem", nous recuperons les sommets "si" de "fa7", recuperons le barycentre de l'intersection
861// "G" de la "fa7" dans "elem", et distribuons aux sommets "si" de fa7 (meme si l'un des "si" n'appartient pas a "elem")
862// "volume_perdu_surfacique" proportionnellement aux coordonnees barycentriques de "G", definies
863// par rapport aux "si" de "fa7".
864//REMARQUE : le volume perdu total est suppose avoir ete transfere (d'une maniere ou d'une autre) sur les mailles
865// euleriennes traversees par l'interface
866//REMARQUE : l'attribut "volume_perdu_" est suppose avoir ete initialise
867//REMARQUE : l'attribut "distance_interface_element_eulerien_" est suppose avoir ete initialise
868int Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_sommet(const int elem, ArrOfDouble& volume_perdu_sommet, const Maillage_FT_Disc& maillage) const
869{
870 const Intersections_Elem_Facettes& intersections =
872
873 const ArrOfInt& index_elem = intersections.index_elem();
874 const IntTab& facettes = maillage.facettes();
875
876 const int distance_interface_elem = distance_interface_element_eulerien_[elem];
877
878 assert(volume_perdu_.dimension_tot(0)==domaine_dis(maillage).domaine().nb_elem_tot());
879
880 const double volume_perdu_elem = volume_perdu_[elem];
881 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
882
883 //Boucle sur les faces qui traversent l'element:
884 //ATTENTION : en parallele, le tableau "index_elem" est dimensionne
885 //a nb_elem() et pas a nb_elem_tot()
886 assert(elem<domaine_dis(maillage).domaine().nb_elem());
887 int index = index_elem[elem];
888
889 const double somme_coefs = surface_interface_elements_voisins_[elem];
890 const double inv_somme_coefs = (somme_coefs > 0.) ? (1. / somme_coefs) : 0.;
891
892 while (index >= 0 && distance_interface_elem==0)
893 {
895 intersections.data_intersection(index);
896
897 //Calcul du volume perdu associe a la facette "facette"
898 // i.e. volume perdu*(surface de "facette" dans "elem")/(surface totale de l'interface dans "elem")
899 const int facette = data.numero_facette_;
900 assert(facette<=maillage.nb_facettes());
901 const double coeff_surface = data.fraction_surface_intersection_ * surface_facettes[facette] * inv_somme_coefs;
902
903 const double volume_perdu_surfacique = volume_perdu_elem*coeff_surface;
904
905 for (int som_loc=0; som_loc<Objet_U::dimension; som_loc++)
906 {
907 //Recuperation d'un sommet de "facette" et des coodonnees barycentrique
908 //du barycentre du centre de gravite de l'intersection entre l'interface
909 //et "elem"
910 const int sommet = facettes(facette,som_loc);
911 assert(sommet<maillage.nb_sommets());
912
913 //Calcul du volume perdu associe au sommet
914 volume_perdu_sommet[sommet]+=volume_perdu_surfacique*data.barycentre_[som_loc];
915
916 }//fin du for sur "som_loc"
917
918 index = data.index_facette_suivante_;
919
920 }//fin du while
921
922 return 1;
923}
924
925
926
927//Fonction qui a chaque sommet du maillage de l'interface associe une partie du
928//volume perdu lors du remaillage
929//Principe : Appel la fonction Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_sommet(const int&, ArrOfDouble &, const Maillage_FT_Disc&)
930// pour chaque element "elem" du maillage eulerien.
931//RETOUR : renvoie le volume perdu total qui a ete transporte jusqu'aux sommets du maillage de l'interface
932double Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_sommet(ArrOfDouble& volume_perdu_sommet, const Maillage_FT_Disc& maillage) const
933{
934 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
935 const Domaine& domaine = domaine_VF.domaine();
936
937 const int nb_elem = domaine.nb_elem();
938 const int nb_sommets_interface = maillage.nb_sommets();
939
940 //Initialisation de "volume_perdu_sommet"
941 if (volume_perdu_sommet.size_array()!=nb_sommets_interface)
942 volume_perdu_sommet.resize_array(nb_sommets_interface);
943
944 volume_perdu_sommet = 0.;
945
946
947 //Appel de la fonction Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_sommet(const int&, ArrOfDouble &, const Maillage_FT_Disc&)
948 for (int elem=0; elem<nb_elem; elem++)
949 {
950 [[maybe_unused]] int ok=transport_volume_perdu_sur_sommet(elem,volume_perdu_sommet,maillage);
951 assert(ok==1);
952 }
953
954 //Pour le parallele
955 maillage.desc_sommets().collecter_espace_virtuel(volume_perdu_sommet, MD_Vector_tools::EV_SOMME);
956
957 //
958 //Calcul du volume perdu transporte sur les
959 //sommets de l'interface
960 //
961 double volume_perdu_transporte = 0.;
962
963 for (int som=0; som<nb_sommets_interface; som++)
964 if (!maillage.sommet_virtuel(som)) volume_perdu_transporte+=volume_perdu_sommet[som];
965
966 return volume_perdu_transporte;
967}
968
969
970//Fonction qui renvoie la surface occupee par l'interface
971//dans un element "elem" REEL donne
972//REMARQUE : renvoie 0 si l'element n'est pas traverse par l'interface
973double Remailleur_Collision_FT_Thomas::surface_intersection(const int elem, const Maillage_FT_Disc& maillage) const
974{
975 const Intersections_Elem_Facettes& intersections =
977
978 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
979 const ArrOfInt& index_elem = intersections.index_elem();
980
981 double surface_dans_elem = 0.;
982
983 // Boucle sur les faces qui traversent l'element:
984 //ATTENTION : en parallele, le tableau "index_elem" est dimensionne
985 //a nb_elem() et pas a nb_elem_tot()
986 assert(elem<domaine_dis(maillage).domaine().nb_elem());
987 int index = index_elem[elem];
988
989 while (index >= 0)
990 {
992 intersections.data_intersection(index);
993
994 surface_dans_elem += data.fraction_surface_intersection_ * surface_facettes[data.numero_facette_];
995 index = data.index_facette_suivante_;
996
997 }//fin du while
998
999 return surface_dans_elem;
1000}
1001
1002
1003//Fonctions destinees a tester les autres fonctions membre de la classe
1004void Remailleur_Collision_FT_Thomas::tester(const Maillage_FT_Disc& maillage) const
1005{
1006 tester_interface(maillage);
1007 tester_distance(maillage);
1008 tester_voisinage(maillage);
1009 tester_liste(maillage);
1010 tester_transport(maillage);
1011
1012 DoubleTab copie_volume_perdu(volume_perdu_);
1013 copie_volume_perdu.echange_espace_virtuel();
1014
1015 tester_transport_complet(maillage, copie_volume_perdu);
1016 tester_volume_par_sommet(maillage, copie_volume_perdu);
1017
1019 {
1020 Cerr << "Fin des tests." << finl;
1021 Cerr << "Sortie du programme." << finl;
1022 }
1023
1024 barrier();
1025 Process::exit();
1026}
1027
1028void Remailleur_Collision_FT_Thomas::tester_interface(const Maillage_FT_Disc& maillage) const
1029{
1030 Nom nom("Elements_euleriens_proc_");
1031 nom+=Process::me();
1032 nom+=".txt";
1033 SFichier fichier_elements_euleriens(nom.getChar());
1034
1035 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1036 const Domaine& domaine = domaine_VF.domaine();
1037
1038 const IntTab& facettes = maillage.facettes();
1039 const ArrOfInt& sommet_elem = maillage.sommet_elem();
1040
1041 const DoubleVect& volumes_elements_euleriens = domaine_VF.volumes();
1042 const DoubleTab& indicatrice =
1043 maillage.equation_transport().inconnue().valeurs();
1044
1045 const int nb_elements_euleriens = domaine.nb_elem();
1046
1047 //On va afficher les elements traverses par l'interface
1048 //Les facettes coupant ces elements
1049 //Les sommets de ces facettes
1050 //Les sommets de ces facettes appartenant aux elements coupes par l'interface
1051 const Intersections_Elem_Facettes& intersections =
1052 maillage.intersections_elem_facettes();
1053
1054 const ArrOfInt& index_element = intersections.index_elem();
1055 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
1056
1057 for (int elem=0; elem<nb_elements_euleriens; elem++)
1058 {
1059 fichier_elements_euleriens << "Element eulerien reel numero : " << elem << finl;
1060 fichier_elements_euleriens << "Taux d'occupation de l'interface : " << indicatrice[elem] << finl;
1061 fichier_elements_euleriens << "Volume de l'element " << elem << " : " << volumes_elements_euleriens[elem] << finl;
1062 fichier_elements_euleriens << "Volume occupee par l'interface : " << indicatrice[elem]*volumes_elements_euleriens[elem] << finl;
1063 fichier_elements_euleriens << "L'element " << elem << " est coupe par les facettes : " << finl;
1064
1065 double surface_intersection_totale = 0.;
1066
1067 // Boucle sur les faces qui traversent l'element:
1068 int index = index_element[elem];
1069
1070 while (index >= 0)
1071 {
1072 const Intersections_Elem_Facettes_Data& data =
1073 intersections.data_intersection(index);
1074
1075 const int facette = data.numero_facette_;
1076
1077 double surface_dans_elem = data.fraction_surface_intersection_ * surface_facettes[facette];
1078 surface_intersection_totale += surface_dans_elem;
1079
1080 if (surface_dans_elem!=0.)
1081 {
1082 fichier_elements_euleriens << facette << " de surface d'intersection "
1083 << surface_dans_elem << finl;
1084
1085 fichier_elements_euleriens << "De sommets : ( ";
1086
1087 for (int som_loc=0; som_loc<Objet_U::dimension; som_loc++)
1088 {
1089 //Recuperation d'un sommet de "facette" et des coodonnees barycentrique
1090 //du barycentre du centre de gravite de l'intersection entre l'interface
1091 //et "elem"
1092 const int sommet = facettes(facette,som_loc);
1093 assert(sommet<maillage.nb_sommets());
1094
1095 if (sommet_elem[sommet]==elem)
1096 fichier_elements_euleriens << "{" << (int) sommet << "," << (int) 1 << "} ";
1097 else
1098 fichier_elements_euleriens << "{" << (int) sommet << "," << (int) 0 << "} ";
1099
1100 }//fin du for sur "som_loc"
1101
1102 fichier_elements_euleriens << ")" << finl;
1103
1104 }//fin du if
1105
1106 index = data.index_facette_suivante_;
1107
1108 }//fin du while
1109
1110 fichier_elements_euleriens << "Surface d'intersection totale : " << surface_intersection_totale << finl;
1111 fichier_elements_euleriens << "Erreur fonction Remailleur_Collision_FT_Thomas::surface_intersection()"
1112 << surface_intersection_totale-surface_intersection(elem,maillage) << finl;
1113
1114 fichier_elements_euleriens << "**************************************************************" << finl;
1115 fichier_elements_euleriens << "**************************************************************" << finl;
1116
1117 }//fin du for sur "elem"
1118
1119}
1120
1121
1122void Remailleur_Collision_FT_Thomas::tester_voisinage(const Maillage_FT_Disc& maillage) const
1123{
1124 Nom nom_sommets("Voisinage_sommets_proc_");
1125 nom_sommets+=Process::me();
1126 nom_sommets+=".txt";
1127
1128 Nom nom_elements("Voisinage_elements_proc_");
1129 nom_elements+=Process::me();
1130 nom_elements+=".txt";
1131
1132 SFichier fichier_voisinage_sommet(nom_sommets.getChar());
1133 SFichier fichier_voisinage_element(nom_elements.getChar());
1134
1135 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1136 const Domaine& domaine = domaine_VF.domaine();
1137
1138 //Affichage des voisinages des sommets
1139 const int nb_som_tot = domaine.nb_som_tot();
1140 const int nb_elem_tot = domaine.nb_elem_tot();
1141 const int nb_som_elem = domaine.nb_som_elem();
1142 const int end_liste = -1;
1143
1144 fichier_voisinage_sommet << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1145 fichier_voisinage_sommet << "Nombre d'elements reels : " << domaine.nb_elem() << finl;
1146 fichier_voisinage_sommet << "Nombre d'elements virtuels : " << nb_elem_tot << finl;
1147 fichier_voisinage_sommet << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1148 fichier_voisinage_sommet << finl;
1149 fichier_voisinage_sommet << finl;
1150
1151 for (int som=domaine.get_renum_som_perio(0); som<nb_som_tot; som++) // som=domaine.get_renum_som_perio(som+1))
1152 {
1153 fichier_voisinage_sommet << "Affichage des elements voisins du sommet " << som << " : {{{ ";
1154
1155 for (int p=voisinage_sommet_[som]; p!=end_liste; p=next_elem_[p])
1156 {
1157 const int elem = p/nb_som_elem;
1158
1159 assert(elem<nb_elem_tot);
1160 assert(som==domaine.get_renum_som_perio(domaine.les_elems()(elem,p%nb_som_elem)));
1161 fichier_voisinage_sommet << elem << " ";
1162 }
1163
1164 fichier_voisinage_sommet << "}}}" << finl;
1165 fichier_voisinage_sommet << "*************************************************************" << finl;
1166 fichier_voisinage_sommet << "*************************************************************" << finl;
1167 fichier_voisinage_sommet << finl;
1168
1169 }//fin du for sur "som"
1170
1171
1172
1173 int taille_liste_voisins_plus_proches = -1;
1174 ArrOfInt elem_voisins;
1175
1176 for (int elem=0; elem<nb_elem_tot; elem++)
1177 {
1178 elements_voisins(elem, elem_voisins, domaine_VF);
1179 const int taille_liste_voisins = elem_voisins.size_array();
1180
1181 //
1182 //Affichage des voisins d'un element "elem"
1183 //
1184 fichier_voisinage_element << "Affichage des elements voisins de l'element " << elem << " : {{{ ";
1185
1186 for (int elem_loc=0; elem_loc<taille_liste_voisins; elem_loc++)
1187 fichier_voisinage_element << elem_voisins[elem_loc] << " ";
1188
1189 fichier_voisinage_element << "}}}" << finl;
1190
1191 elements_voisins_a_distance_plus_petite2(elem, elem_voisins);
1192
1193 taille_liste_voisins_plus_proches = elem_voisins.size_array();
1194 assert(taille_liste_voisins_plus_proches<=nombre_de_voisins_plus_proches_[elem]);
1195 if (elem<domaine.nb_elem()) assert(taille_liste_voisins_plus_proches==nombre_de_voisins_plus_proches_[elem]);
1196
1197 //
1198 //Affichage des voisins + proche de l'interface que "elem
1199 //
1200 fichier_voisinage_element << "Affichage des elements voisins de l'element " << elem
1201 << " a distance plus petite que : "
1202 << distance_interface_element_eulerien_[elem] << " : {{{ ";
1203
1204 for (int elem_loc=0; elem_loc<taille_liste_voisins_plus_proches; elem_loc++)
1205 {
1206 const int elem_voisin_plus_proche = elem_voisins[elem_loc];
1207 fichier_voisinage_element << "(" << elem_voisin_plus_proche << ","
1208 << distance_interface_element_eulerien_[elem_voisin_plus_proche]
1209 << ") ";
1210 }//fin du for sur "elem_loc"
1211
1212 fichier_voisinage_element << "}}}" << finl;
1213
1214 fichier_voisinage_element << "Nombre de voisins plus proches : " << nombre_de_voisins_plus_proches_[elem] << finl;
1215
1216 fichier_voisinage_element << "*************************************************************" << finl;
1217 fichier_voisinage_element << "*************************************************************" << finl;
1218 fichier_voisinage_element << finl;
1219
1220 }//fin du for sur "elem"
1221}
1222
1223
1224
1225void Remailleur_Collision_FT_Thomas::tester_distance(const Maillage_FT_Disc& maillage) const
1226{
1227 Nom nom("Distance_interface_proc_");
1228 nom+=Process::me();
1229 nom+=".txt";
1230
1231 SFichier fichier_distance(nom.getChar());
1232
1233 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1234 const Domaine& domaine = domaine_VF.domaine();
1235
1236 const int nb_elem_tot = domaine.nb_elem_tot();
1237
1238 fichier_distance << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1239 fichier_distance << "Nombre d'elements reels : " << domaine.nb_elem() << finl;
1240 fichier_distance << "Nombre d'elements virtuels : " << nb_elem_tot << finl;
1241 fichier_distance << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1242 fichier_distance << finl;
1243 fichier_distance << finl;
1244
1245
1246 fichier_distance << "Affichage de la plus grande distance a l'interface." << plus_grande_distance_interface_element_eulerien_;
1247 fichier_distance << finl;
1248 fichier_distance << "*************************************************************" << finl;
1249 fichier_distance << "*************************************************************" << finl;
1250 fichier_distance << finl;
1251
1252 for (int elem=0; elem<nb_elem_tot; elem++)
1253 {
1254 const int distance = distance_interface_element_eulerien_[elem];
1255 assert(distance<=plus_grande_distance_interface_element_eulerien_);
1256 fichier_distance << "Affichage de l'element " << elem << " ";
1257 fichier_distance << "et de sa distance a l'interface : " << distance << finl;
1258 }
1259}
1260
1261
1262void Remailleur_Collision_FT_Thomas::tester_liste(const Maillage_FT_Disc& maillage) const
1263{
1264 Nom nom("Liste_chainee_proc_");
1265 nom+=Process::me();
1266 nom+=".txt";
1267
1268 SFichier fichier_liste(nom.getChar());
1269
1270 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1271 const Domaine& domaine = domaine_VF.domaine();
1272
1273 const int nb_elem_tot = domaine.nb_elem_tot();
1274
1275 //
1276 //Test du chainage dans la fonction Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_element(const Maillage_FT_Disc&)
1277 //
1278 IntTab distance_des_elements(plus_grande_distance_interface_element_eulerien_+1);
1279 IntTab suite_des_elements(nb_elem_tot);
1280 distance_des_elements = -1;
1281 suite_des_elements = -1;
1282
1283 assert(nb_elem_tot==distance_interface_element_eulerien_.dimension_tot(0));
1284
1285
1286 fichier_liste << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1287 fichier_liste << "Nombre d'elements reels : " << domaine.nb_elem() << finl;
1288 fichier_liste << "Nombre d'elements virtuels : " << nb_elem_tot << finl;
1289 fichier_liste << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1290 fichier_liste << finl;
1291 fichier_liste << finl;
1292
1293
1294 //Boucle sur "distance_interface_element_eulerien_" afin de modifier nos listes
1295 for (int elem=0; elem<nb_elem_tot; elem++)
1296 {
1297 const int distance = distance_interface_element_eulerien_[elem];
1298 if (distance==-1) continue; //on passe directement a l'element suivant
1299 assert(distance<=plus_grande_distance_interface_element_eulerien_);
1300
1301 suite_des_elements(elem)=distance_des_elements(distance);
1302 distance_des_elements(distance)=elem;
1303
1304 }//fin du for sur "elem"
1305
1306
1307 fichier_liste << "Affichage de la premiere liste chainee" << finl;
1308 fichier_liste << finl;
1309 for (int distance=0; distance<plus_grande_distance_interface_element_eulerien_+1; distance++)
1310 fichier_liste << "Distance : " << distance << " element : " << distance_des_elements(distance) << finl;
1311
1312 fichier_liste << finl;
1313 fichier_liste << "*************************************************************" << finl;
1314 fichier_liste << "*************************************************************" << finl;
1315 fichier_liste << finl;
1316
1317
1318 fichier_liste << "Affichage de la deuxieme liste chainee" << finl;
1319 fichier_liste << finl;
1320
1321 for (int elem=0; elem<nb_elem_tot; elem++)
1322 fichier_liste << "Precedent : " << elem << " suivant : " << suite_des_elements(elem) << finl;
1323
1324 fichier_liste << finl;
1325 fichier_liste << "*************************************************************" << finl;
1326 fichier_liste << "*************************************************************" << finl;
1327 fichier_liste << finl;
1328
1329 fichier_liste << "Test du parcours de la liste chainee" << finl;
1330 fichier_liste << finl;
1331
1332
1333 for (int distance=plus_grande_distance_interface_element_eulerien_; distance!=-1; distance--)
1334 {
1335 //Parcours de tous les elements "elem" situes a la distance "distance" de l'interface
1336 //et transport du volume perdu
1337 fichier_liste << "Affichage des elements a distance " << distance << " de l'interface." << finl;
1338 fichier_liste << "{ ";
1339
1340 for (int elem=distance_des_elements(distance); elem!=-1; elem=suite_des_elements(elem))
1341 fichier_liste << elem << " ";
1342
1343 fichier_liste << "}" << finl;
1344 fichier_liste << "-------------------------------------------------------------" << finl;
1345 fichier_liste << finl;
1346
1347 }//fin du for sur distance
1348}
1349
1350
1351void Remailleur_Collision_FT_Thomas::tester_transport(const Maillage_FT_Disc& maillage) const
1352{
1353 Nom nom("Transport_proc_");
1354 nom+=Process::me();
1355 nom+=".txt";
1356
1357 SFichier fichier_transport(nom.getChar());
1358
1359 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1360 const Domaine& domaine = domaine_VF.domaine();
1361
1362 const int nb_elem = domaine.nb_elem();
1363 const int nb_elem_tot = domaine.nb_elem_tot();
1364
1365 if (volume_perdu_.dimension_tot(0) != nb_elem_tot)
1366 {
1367 Cerr << "Erreur Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_element()" << finl;
1368 Cerr << "Le tableau volume_distribue_ n'est pas correctement initialise." << finl;
1369 Cerr << "Sortie du programme." << finl;
1370 Process::exit();
1371 }
1372
1373 if (distance_interface_element_eulerien_.dimension_tot(0) != nb_elem_tot)
1374 {
1375 Cerr << "Erreur Remailleur_Collision_FT_Thomas::transport_volume_perdu_sur_element()" << finl;
1376 Cerr << "Le tableau distance_interface_element_eulerien_ n'est pas correctement initialise." << finl;
1377 Cerr << "Sortie du programme." << finl;
1378 Process::exit();
1379 }
1380
1381
1382
1383 ArrOfInt voisins_a_distance_plus_petite(100);
1384 voisins_a_distance_plus_petite.resize_array(0);
1385
1386
1387 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1388 fichier_transport << "Nombre d'elements reels : " << nb_elem << finl;
1389 fichier_transport << "Nombre d'elements virtuels : " << nb_elem_tot << finl;
1390 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1391 fichier_transport << finl;
1392 fichier_transport << finl;
1393
1394 for (int elem=0; elem<nb_elem_tot; elem++)
1395 {
1396 const int distance_interface_elem = distance_interface_element_eulerien_[elem];
1397
1398 if (volume_perdu_[elem]==0)
1399 {
1400 fichier_transport << "Pas de volume perdu pour l'element " << elem << finl;
1401 fichier_transport << "*******************************************************" << finl;
1402 fichier_transport << "*******************************************************" << finl;
1403 fichier_transport << finl;
1404 continue;
1405 }
1406
1407 elements_voisins(elem, voisins_a_distance_plus_petite,domaine_VF);
1408 elements_voisins_a_distance_plus_petite2(elem, voisins_a_distance_plus_petite);
1409 const int nb_voisins_a_distance_plus_petite = voisins_a_distance_plus_petite.size_array();
1410
1411 ArrOfDouble surface_par_element(nb_voisins_a_distance_plus_petite);
1412
1413 //Recuperation de la surface totale des facettes traversant
1414 //l'ensemble des elements a distance 0 de l'interface, ainsi que la surface
1415 //des facettes traversant chaque element a distance 0 de l'inteface
1416 double surface_totale = 0.;
1417 // int distance_interface_elem_voisin = -2;
1418
1419
1420 switch(distance_interface_elem)
1421 {
1422
1423 case -1 :
1424
1425 fichier_transport << "L'element " << elem
1426 << " est a une distance de l'interface superieure a " << distance_interface_elem << finl;
1427 fichier_transport << "*******************************************************" << finl;
1428 fichier_transport << "*******************************************************" << finl;
1429 fichier_transport << finl;
1430
1431 break;
1432
1433
1434
1435 case 0 :
1436
1437 fichier_transport << "Pas de transport pour l'element " << elem
1438 << " a distance " << distance_interface_elem << " de l'interface" << finl;
1439 fichier_transport << "*******************************************************" << finl;
1440 fichier_transport << "*******************************************************" << finl;
1441 fichier_transport << finl;
1442
1443 break;
1444
1445
1446
1447 case 1 : //cas ou distance_interface_element==1
1448
1449 assert(nb_voisins_a_distance_plus_petite!=0 || elem>=nb_elem);
1450 assert(nb_voisins_a_distance_plus_petite<=nombre_de_voisins_plus_proches_[elem]);
1451 if (elem<nb_elem) assert(nb_voisins_a_distance_plus_petite==nombre_de_voisins_plus_proches_[elem]);
1452
1453 for (int elem_loc=0; elem_loc<nb_voisins_a_distance_plus_petite; elem_loc++)
1454 {
1455 const int elem_voisin = voisins_a_distance_plus_petite[elem_loc];
1456 const double surface_dans_elem_voisin = surface_interface_elements_voisins_[elem_voisin];
1457
1458 surface_totale += surface_dans_elem_voisin;
1459 surface_par_element[elem_loc] += surface_dans_elem_voisin;
1460
1461 }//fin du for sur "elem_loc"
1462
1463
1464 fichier_transport << "L'element " << elem << " est a distance "
1465 << distance_interface_elem << " case 1" << finl;
1466 fichier_transport << "Cet element a perdu le volume " << volume_perdu_[elem] << finl;
1467 fichier_transport << "Cet element a " << nombre_de_voisins_plus_proches_[elem] << " voisins plus proches" << finl;
1468 fichier_transport << "La surface d'interface dans l'ensemble de ces voisins les plus proches est : "
1469 << surface_totale << " ou " << surface_interface_elements_voisins_[elem] << finl;
1470 fichier_transport << "-------------------------------------------------------" << finl;
1471
1472 //Repartition du volume selon les principes enonces.
1473 for (int elem_loc=0; elem_loc<nb_voisins_a_distance_plus_petite; elem_loc++)
1474 {
1475 const int elem_voisin = voisins_a_distance_plus_petite[elem_loc];
1476
1477
1478 assert(distance_interface_elem-distance_interface_element_eulerien_[elem_voisin]==1);
1479
1480 fichier_transport << "La surface d'interface dans le voisin " << elem_voisin
1481 << " de " << elem << " est : "
1482 << surface_par_element[elem_loc] << " ou "
1483 << surface_interface_elements_voisins_[elem_voisin] << finl;
1484
1485 fichier_transport << "L'element voisin " << elem_voisin << " recoit le volume "
1486 << volume_perdu_[elem]*surface_interface_elements_voisins_[elem_voisin]/surface_interface_elements_voisins_[elem]
1487 << finl;
1488 fichier_transport << finl;
1489
1490 }//fin du for sur "elem_loc"
1491
1492 fichier_transport << "-------------------------------------------------------" << finl;
1493 fichier_transport << "*******************************************************" << finl;
1494 fichier_transport << "*******************************************************" << finl;
1495 fichier_transport << finl;
1496
1497 break;
1498
1499
1500 default :
1501
1502 assert(nb_voisins_a_distance_plus_petite!=0 || elem>=nb_elem);
1503 assert(nb_voisins_a_distance_plus_petite==nombre_de_voisins_plus_proches_[elem]);
1504 if (elem<nb_elem) assert(nb_voisins_a_distance_plus_petite==nombre_de_voisins_plus_proches_[elem]);
1505
1506 fichier_transport << "L'element " << elem << " est a distance "
1507 << distance_interface_elem << " default" << finl;
1508
1509 fichier_transport << "Cet element a perdu le volume " << volume_perdu_[elem] << finl;
1510 fichier_transport << "Cet element a " << nombre_de_voisins_plus_proches_[elem] << " voisins plus proches" << finl;
1511 fichier_transport << "Et distribue a ces voisins les plus proches le volume : "
1512 << volume_perdu_[elem]/nombre_de_voisins_plus_proches_[elem] << finl;
1513 fichier_transport << "*******************************************************" << finl;
1514 fichier_transport << "*******************************************************" << finl;
1515 fichier_transport << finl;
1516
1517 break;
1518
1519 }//fin du switch
1520
1521 }//fin du for sur "elem"
1522}
1523
1524
1525
1526void Remailleur_Collision_FT_Thomas::tester_transport_complet(const Maillage_FT_Disc& maillage, DoubleTab& copie_volume_perdu_) const
1527{
1528 Nom nom("Transport_complet_proc_");
1529 nom+=Process::me();
1530 nom+=".txt";
1531
1532 SFichier fichier_transport(nom.getChar());
1533
1534 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1535 const Domaine& domaine = domaine_VF.domaine();
1536
1537 const int nb_elem = domaine.nb_elem();
1538 const int nb_elem_tot = domaine.nb_elem_tot();
1539 const int end_liste = -1;
1540
1541 //Construction de la liste chainee distance->{ensemble des elements a cette distance}
1542 //Principe : Creation d'une premiere liste de taille "plus_grande_distance_interface_element_eulerien_"
1543 // et initialisee a -1
1544 // A la distance "n" sera stocke un element "elem" a distance "n" de l'interface
1545 // Creation d'une deuxieme liste de taille "nb_elem_tot" initialisee a -1
1546 // A la place "elem" est stocke le numero "elem2" d'un deuxieme element a distance "n"
1547 // A la place "elem2" est stocke le numero "elem3" d'un deuxieme element a distance "n" etc
1548 // La fin de la liste chainee est reperee par un -1
1549
1550 IntTab distance_des_elements(plus_grande_distance_interface_element_eulerien_+1);
1551 IntTab suite_des_elements(nb_elem_tot);
1552 distance_des_elements = end_liste;
1553 suite_des_elements = end_liste;
1554
1555 assert(nb_elem_tot==distance_interface_element_eulerien_.dimension_tot(0));
1556
1557
1558 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1559 fichier_transport << "Nombre d'elements reels : " << nb_elem << finl;
1560 fichier_transport << "Nombre d'elements virtuels : " << nb_elem_tot << finl;
1561 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1562 fichier_transport << finl;
1563 fichier_transport << finl;
1564
1565
1566 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1567 double volume_total_avant = 0.;
1568 for (int elem=0; elem<nb_elem; elem++)
1569 volume_total_avant += copie_volume_perdu_[elem];
1570
1571 fichier_transport << "Affichage du volume perdu avant tester_transport_complet() : "
1572 << Process::mp_sum(volume_total_avant) << finl;
1573 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1574 fichier_transport << finl;
1575 fichier_transport << finl;
1576
1577 //Boucle sur "distance_interface_element_eulerien_" afin de modifier nos listes
1578 for (int elem=0; elem<nb_elem_tot; elem++)
1579 {
1580 const int distance = distance_interface_element_eulerien_[elem];
1581 if (distance==-1) continue; //on passe directement a l'element suivant
1582 assert(distance<=plus_grande_distance_interface_element_eulerien_);
1583
1584 suite_des_elements(elem)=distance_des_elements(distance);
1585 distance_des_elements(distance)=elem;
1586
1587 }//fin du for sur "elem"
1588
1589
1590 //
1591 //Transport du volume perdu proprement dit
1592 //
1593
1594 ArrOfInt voisins_a_distance_plus_petite(100);
1595
1596 // int distance_interface_elem_voisin = -2;
1597
1598 for (int distance=plus_grande_distance_interface_element_eulerien_; distance!=-1; distance--)
1599 {
1600
1601 //Parcours de tous les elements "elem" situes a la distance "distance" de l'interface
1602 //et transport du volume perdu
1603 for (int elem=distance_des_elements(distance); elem!=-1; elem=suite_des_elements(elem))
1604 {
1605 voisins_a_distance_plus_petite.resize_array(0);
1606
1607 elements_voisins(elem, voisins_a_distance_plus_petite,domaine_VF);
1608 elements_voisins_a_distance_plus_petite2(elem, voisins_a_distance_plus_petite);
1609 const int nb_voisins_a_distance_plus_petite = voisins_a_distance_plus_petite.size_array();
1610
1611 const int distance_interface_elem = distance_interface_element_eulerien_[elem];
1612
1613 ArrOfDouble surface_par_element(nb_voisins_a_distance_plus_petite);
1614 double surface_totale = 0.;
1615
1616 if (copie_volume_perdu_[elem]==0)
1617 {
1618 fichier_transport << "L'element " << elem << " n' a pas perdu de volume" << finl;
1619 fichier_transport << "*******************************************************" << finl;
1620 fichier_transport << "*******************************************************" << finl;
1621
1622 continue;
1623 }; //pas de volume perdu => sortie
1624
1625
1626 switch(distance_interface_elem)
1627 {
1628
1629 case -1 :
1630
1631 fichier_transport << "L'element " << elem << " est a une distance de l'interface superieure "
1632 << "a la distance prescrite par l'utilisateur." << finl;
1633 fichier_transport << "*******************************************************" << finl;
1634 fichier_transport << "*******************************************************" << finl;
1635
1636 break;
1637
1638
1639 case 0 :
1640
1641 fichier_transport << "L'element " << elem << " n' est pas traverse par l'interface" << finl;
1642 fichier_transport << "*******************************************************" << finl;
1643 fichier_transport << "*******************************************************" << finl;
1644
1645 break;
1646
1647
1648 case 1 :
1649
1650 assert(nb_voisins_a_distance_plus_petite!=0 || elem>=nb_elem);
1651 assert(nb_voisins_a_distance_plus_petite<=nombre_de_voisins_plus_proches_[elem]);
1652 if (elem<nb_elem) assert(nb_voisins_a_distance_plus_petite==nombre_de_voisins_plus_proches_[elem]);
1653
1654 fichier_transport << "Case 1" << finl;
1655 fichier_transport << "L'element " << elem << " est a distance " << distance_interface_elem
1656 << " de l'interface et a perdu le volume : " << copie_volume_perdu_[elem] << finl;
1657 fichier_transport << "Il a " << nombre_de_voisins_plus_proches_[elem]
1658 << " voisins plus proches de l'interface." << finl;
1659 fichier_transport << "Ces voisins sont : " << finl;
1660
1661
1662 //Recuperation de la surface totale des facettes traversant
1663 //l'ensemble des elements a distance 0 de l'interface, ainsi que la surface
1664 //des facettes traversant chaque element a distance 0 de l'interface
1665 for (int elem_loc=0; elem_loc<nb_voisins_a_distance_plus_petite; elem_loc++)
1666 {
1667 const int elem_voisin = voisins_a_distance_plus_petite[elem_loc];
1668 const double surface_dans_elem_voisin = surface_interface_elements_voisins_[elem_voisin];
1669
1670 surface_totale += surface_dans_elem_voisin;
1671 surface_par_element[elem_loc] += surface_dans_elem_voisin;
1672 assert (std::fabs(surface_dans_elem_voisin-surface_interface_elements_voisins_[elem_voisin])<=1.e-15);
1673
1674 fichier_transport << "l'element " << elem_voisin
1675 << " traverse par l'interface de surface : "
1676 << surface_interface_elements_voisins_[elem_voisin] << finl;
1677
1678 }//fin du for sur "elem_loc"
1679
1680
1681 fichier_transport << "La surface totale est donc de : " << surface_totale
1682 << " ou " << surface_interface_elements_voisins_[elem]
1683 << finl;
1684
1685 assert(std::fabs(surface_totale-surface_interface_elements_voisins_[elem])<=1.e-14);
1686
1687 //Repartition du volume selon les principes enonces.
1688 for (int elem_loc=0; elem_loc<nb_voisins_a_distance_plus_petite; elem_loc++)
1689 {
1690 const int elem_voisin = voisins_a_distance_plus_petite[elem_loc];
1691
1692 // assert(distance_interface_elem_voisin!=-1);
1693 assert(distance_interface_elem-distance_interface_element_eulerien_[elem_voisin]==1);
1694
1695 copie_volume_perdu_[elem_voisin]+=copie_volume_perdu_[elem]
1696 *surface_interface_elements_voisins_[elem_voisin]/surface_interface_elements_voisins_[elem];
1697
1698 fichier_transport << "L'element " << elem_voisin << " recoit de la part de l'element " << elem
1699 << " le volume : "
1700 << copie_volume_perdu_[elem]*surface_interface_elements_voisins_[elem_voisin]/surface_interface_elements_voisins_[elem]
1701 << finl;
1702 fichier_transport << "Le nouveau volume perdu par l'element " << elem_voisin
1703 << " est donc : " << copie_volume_perdu_[elem_voisin] << finl;
1704 }//fin du for sur "elem_loc"
1705
1706 //remise a zero pour plus de surete
1707 copie_volume_perdu_[elem]=0.;
1708
1709 fichier_transport << "Le volume perdu par l'element " << elem
1710 << " est maintenant nul : " << copie_volume_perdu_[elem] << finl;
1711
1712 fichier_transport << "*******************************************************" << finl;
1713 fichier_transport << "*******************************************************" << finl;
1714
1715 break;
1716
1717
1718
1719 default :
1720
1721 assert(nb_voisins_a_distance_plus_petite!=0 || elem>=nb_elem);
1722 assert(nb_voisins_a_distance_plus_petite<=nombre_de_voisins_plus_proches_[elem]);
1723 if (elem<nb_elem) assert(nb_voisins_a_distance_plus_petite==nombre_de_voisins_plus_proches_[elem]);
1724
1725 fichier_transport << "Default" << finl;
1726 fichier_transport << "L'element " << elem << " est a distance " << distance_interface_elem
1727 << " de l'interface et a perdu le volume : " << copie_volume_perdu_[elem] << finl;
1728 fichier_transport << "Il a " << nombre_de_voisins_plus_proches_[elem]
1729 << " voisins plus proches de l'interface." << finl;
1730 fichier_transport << "Ces voisins sont : " << finl;
1731
1732 //Repartition du volume selon les principes enonces.
1733 for (int elem_loc=0; elem_loc<nombre_de_voisins_plus_proches_[elem]; elem_loc++)
1734 {
1735 const int elem_voisin = voisins_a_distance_plus_petite[elem_loc];
1736
1737 // assert(distance_interface_elem_voisin!=-1);
1738 assert(distance_interface_elem-distance_interface_element_eulerien_[elem_voisin]==1);
1739 copie_volume_perdu_[elem_voisin]+=copie_volume_perdu_[elem]/nombre_de_voisins_plus_proches_[elem];
1740
1741 fichier_transport << "l'element " << elem_voisin
1742 << " qui recoit le volume perdu : "
1743 << copie_volume_perdu_[elem]/nombre_de_voisins_plus_proches_[elem] << finl;
1744 fichier_transport << "Le nouveau volume perdu par l'element " << elem_voisin
1745 << " est donc : " << copie_volume_perdu_[elem_voisin] << finl;
1746 }//fin du for sur "elem_loc"
1747
1748 //remise a zero pour plus de surete
1749 copie_volume_perdu_[elem]=0.;
1750
1751 fichier_transport << "Le volume perdu par l'element " << elem
1752 << " est maintenant nul : " << copie_volume_perdu_[elem] << finl;
1753
1754 fichier_transport << "*******************************************************" << finl;
1755 fichier_transport << "*******************************************************" << finl;
1756
1757 break;
1758
1759 }//fin du switch sur "distance_interface_elem"
1760
1761 }//fin du for sur "elem"
1762
1763 copie_volume_perdu_.echange_espace_virtuel();
1764
1765 }//fin du for sur "distance
1766
1767 fichier_transport << finl;
1768 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1769 fichier_transport << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1770
1771 double volume_total_perdu = 0.;
1772 for (int elem=0; elem<nb_elem; elem++)
1773 volume_total_perdu += copie_volume_perdu_[elem];
1774
1775 fichier_transport << "Affichage du volume perdu total transporte : " << Process::mp_sum(volume_total_perdu) << finl;
1776}
1777
1778
1779
1780void Remailleur_Collision_FT_Thomas::tester_volume_par_sommet(const Maillage_FT_Disc& maillage, const DoubleTab& copie_volume_perdu_) const
1781{
1782 Nom nom("Volume_sommet_proc_");
1783 nom+=Process::me();
1784 nom+=".txt";
1785
1786 SFichier fichier_volume(nom.getChar());
1787
1788 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1789 const Domaine& domaine = domaine_VF.domaine();
1790
1791 const Intersections_Elem_Facettes& intersections =
1792 maillage.intersections_elem_facettes();
1793
1794 const ArrOfInt& index_elem = intersections.index_elem();
1795 const IntTab& facettes = maillage.facettes();
1796
1797 const int nb_elem = domaine.nb_elem();
1798 const int nb_elem_tot = domaine.nb_elem_tot();
1799 const int nb_sommets_interface = maillage.nb_sommets();
1800
1801 ArrOfDoubleFT volume_perdu_par_sommet(nb_sommets_interface);
1802 volume_perdu_par_sommet = 0.;
1803
1804
1805 fichier_volume << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1806 fichier_volume << "Nombre d'elements reels : " << nb_elem << finl;
1807 fichier_volume << "Nombre d'elements virtuels : " << nb_elem_tot << finl;
1808 fichier_volume << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1809 fichier_volume << finl;
1810 fichier_volume << finl;
1811
1812
1813 fichier_volume << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1814 double volume_total_avant = 0.;
1815 for (int elem=0; elem<nb_elem; elem++)
1816 volume_total_avant += copie_volume_perdu_[elem];
1817
1818 fichier_volume << "Affichage du volume perdu avant tester_volume_par_sommet() : "
1819 << Process::mp_sum(volume_total_avant) << finl;
1820 fichier_volume << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1821 fichier_volume << finl;
1822 fichier_volume << finl;
1823 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
1824
1825 for (int elem=0; elem<nb_elem; elem++)
1826 {
1827 assert(copie_volume_perdu_.dimension_tot(0)==nb_elem_tot);
1828
1829 const double surface_interface_dans_elem = surface_interface_elements_voisins_[elem];
1830
1831 const double volume_perdu_elem = copie_volume_perdu_[elem];
1832
1833 fichier_volume << "L'element " << elem << " a perdu le volume " << copie_volume_perdu_[elem] << finl;
1834 fichier_volume << "La surface d'interface le coupant est de : " << surface_interface_dans_elem << finl;
1835
1836 //Boucle sur les faces qui traversent l'element:
1837 int index = index_elem[elem];
1838
1839 while (index >= 0)
1840 {
1841 const Intersections_Elem_Facettes_Data& data =
1842 intersections.data_intersection(index);
1843
1844 //Calcul du volume perdu associe a "facette"
1845 // i.e. volume perdu*(surface de "facette" dans "elem")/(surface totale de l'interface dans "elem")
1847 {
1848 const int facette = data.numero_facette_;
1849 const double coeff_surface = data.fraction_surface_intersection_*surface_facettes[facette]/surface_interface_dans_elem;
1850 const double volume_perdu_surfacique = volume_perdu_elem*coeff_surface;
1851
1852 fichier_volume << "La facette " << facette << " coupant l'element " << elem
1853 << " a une surface dans l'element de " << data.fraction_surface_intersection_*surface_facettes[facette] << finl;
1854 fichier_volume << "Cela represente " << coeff_surface << " de la surface totale" << finl;
1855 fichier_volume << "La facette " << facette << " recoit donc un volume surfacique de "
1856 << volume_perdu_surfacique << finl;
1857 fichier_volume << "-------------------------------------------------------" << finl;
1858
1859 for (int som_loc=0; som_loc<Objet_U::dimension; som_loc++)
1860 {
1861 //Recuperation d'un sommet de "facette" et des coodonnees barycentrique
1862 //du barycentre du centre de gravite de l'intersection entre l'interface
1863 //et "elem"
1864 const int sommet = facettes(facette,som_loc);
1865 assert(sommet<nb_sommets_interface);
1866
1867 fichier_volume << "La coordonnee barycentrique du barycentre "
1868 << "de la surface de l'interface dans l'element " << elem
1869 << " par rapport au sommet " << sommet << " est : " << data.barycentre_[som_loc]
1870 << finl;
1871 fichier_volume << "Le sommet " << sommet << " de la facette " << facette
1872 << " recoit donc le volume : " << volume_perdu_surfacique*data.barycentre_[som_loc];
1873 fichier_volume << finl;
1874
1875 volume_perdu_par_sommet[sommet]+=volume_perdu_surfacique*data.barycentre_[som_loc];
1876
1877 }//fin du for sur "som_loc"
1878
1879 fichier_volume << "-------------------------------------------------------" << finl;
1880
1881 }//fin du if
1882
1883 index = data.index_facette_suivante_;
1884
1885 }//fin du while
1886
1887 fichier_volume << "*******************************************************" << finl;
1888 fichier_volume << "*******************************************************" << finl;
1889 fichier_volume << finl;
1890
1891 }//fin du for sur "elem"
1892
1893 fichier_volume << finl;
1894 fichier_volume << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1895 fichier_volume << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1896
1897 //Pour le parallele
1898 maillage.desc_sommets().collecter_espace_virtuel(volume_perdu_par_sommet, MD_Vector_tools::EV_SOMME);
1899
1900 double volume_perdu_total = 0.;
1901 for (int som=0; som<nb_sommets_interface; som++)
1902 if (!maillage.sommet_virtuel(som)) volume_perdu_total+=volume_perdu_par_sommet[som];
1903
1904 fichier_volume << "Le volume perdu par sommet total est : " << Process::mp_sum(volume_perdu_total) << finl;
1905}
1906
1907// Fonction qui dimensionne les attributs de type IntTab et DoubleTab
1909{
1910 const Domaine_VF& domaine_VF = ref_cast(Domaine_VF,domaine_dis(maillage));
1911 const Domaine& domaine = domaine_VF.domaine();
1912
1913 const int nb_elem_tot = domaine.nb_elem_tot();
1914 const int nb_som_elem = domaine.nb_som_elem();
1915 const int nb_som_tot = domaine.nb_som_tot();
1916
1917 //On dimensionne les donnees
1918 distance_interface_element_eulerien_.reset();
1919 nombre_de_voisins_plus_proches_.reset();
1920 surface_interface_elements_voisins_.reset();
1921 volume_perdu_.reset();
1922 domaine.creer_tableau_elements(distance_interface_element_eulerien_, RESIZE_OPTIONS::NOCOPY_NOINIT);
1923 distance_interface_element_eulerien_=-1;
1924 domaine.creer_tableau_elements(nombre_de_voisins_plus_proches_);
1925 domaine.creer_tableau_elements(surface_interface_elements_voisins_);
1926 domaine.creer_tableau_elements(volume_perdu_);
1927
1928 //On dimensionne les donnees
1929 voisinage_sommet_.resize(nb_som_tot, RESIZE_OPTIONS::NOCOPY_NOINIT);
1930 next_elem_.resize(nb_elem_tot*nb_som_elem, RESIZE_OPTIONS::NOCOPY_NOINIT);
1931
1932 //On leur attribue une valeur
1933 voisinage_sommet_ = -1;
1934 construire_voisinage_sommet(maillage) ;
1935
1936 return (est_dimensionne_=1);
1937}
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
void collecter_espace_virtuel(ArrOfDouble &tab, MD_Vector_tools::Operations_echange op) const
int nb_som_elem() const
Renvoie le nombre de sommets des elements geometriques constituants le domaine.
Definition Domaine.h:474
int_t nb_elem_tot() const
Definition Domaine.h:132
int_t nb_elem() const
Definition Domaine.h:131
class Domaine_VF
Definition Domaine_VF.h:44
double volumes(int i) const
Definition Domaine_VF.h:113
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
: class Intersections_Elem_Facettes
const ArrOfInt & index_elem() const
Renvoie un tableau de taille domaine.
const ArrOfInt & index_facette() const
Renvoie un tableau de taille "nombre de facettes de l'interface" pour un element 0 <= facette < nb_fa...
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 ...
: class Maillage_FT_Disc Cette classe decrit un maillage:
Transport_Interfaces_FT_Disc & equation_transport()
void mesh_tag_increase() const
int nb_sommets() const
renvoie le nombre de sommets (reels et virtuels) (egal a sommets().
int nb_facettes() const
renvoie le nombre de facettes (reelles et virtuelles) (egal a facettes().
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 parcourir_maillage()
Remplit la structure intersections_elem_facettes_.
int sommet_virtuel(int i) const
const Intersections_Elem_Facettes & intersections_elem_facettes() const
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...
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_
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
static double mp_min(double)
Definition Process.cpp:386
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 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 Remailleur_Collision_FT_Juric Classe implementant un remailleur d'interfaces entrees en collis...
int traite_RuptureCoalescenceInterfaces(Maillage_FT_Disc &maillage, int nb_fa7Intersectees, const IntTab &couples_fa7Intersectees, const DoubleTab &segmentsInter_fa7Intersectees, Champ_base &indicatrice) override
: class Remailleur_Collision_FT_Thomas Cette classe implemente les procedures de remaillage des inter...
int mettre_a_jour_data(const Maillage_FT_Disc &)
int transport_volume_perdu_sur_element(const int, const Maillage_FT_Disc &)
int nb_elements_voisins(const int, const Domaine_dis_base &) const
int traite_RuptureCoalescenceInterfaces_Conservatif(Maillage_FT_Disc &, Champ_base &) override
algorithme de remaillage qui tente de conserver le volume.
int transport_volume_perdu_sur_sommet(const int, ArrOfDouble &, const Maillage_FT_Disc &) const
int elements_voisins(const int, ArrOfInt &, const Domaine_dis_base &) const
int elements_voisins_a_distance_plus_petite2(const int, ArrOfInt &) const
int construire_voisinage_sommet(const Maillage_FT_Disc &)
int nb_elements_voisins_a_distance_plus_petite(const int, const Domaine_dis_base &) const
Classe de base des flux de sortie.
Definition Sortie.h:52
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
void update_indicatrice_normale_distance()
Updates normals and distances to interface, then updates indicatrice.
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.
const Maillage_FT_Disc & maillage_interface() const