TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Remaillage_FT.cpp
1/****************************************************************************
2* Copyright (c) 2022, 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 <Remaillage_FT.h>
17#include <TRUST_Deriv.h>
18#include <Motcle.h>
19#include <Domaine_VF.h>
20#include <Domaine.h>
21#include <Triangle.h>
22#include <Rectangle.h>
23#include <Rectangle_2D_axi.h>
24#include <Hexaedre.h>
25#include <Tetraedre.h>
26#include <Comm_Group.h>
27#include <Transport_Interfaces_FT_Disc.h>
28#include <EcritureLectureSpecial.h>
29#include <Param.h>
30#include <Array_tools.h>
31#include <DebogFT.h>
32
33#include <TRUST_2_PDI.h>
34
35Implemente_instanciable_sans_constructeur(Remaillage_FT,"Remaillage_FT",Objet_U);
36
37
41
42/*! @brief Lecture des parametres de remaillage
43 *
44 */
46{
47 Param p(que_suis_je());
48 set_param(p);
49 double critere_remaillage_compat=-1;
50 p.ajouter("critere_remaillage",& critere_remaillage_compat);
51 p.ajouter("equilateral", &equilateral_);
54
55 p.lire_avec_accolades_depuis(is);
56
57 if ( critere_remaillage_compat!=-1)
58 Process::exit("Error: critere_remaillage keyword did nothing and is therefore obsolete, remove it from your datafile");
59
61 {
62 Cerr << "Error: Obsolete syntax read in the datafile:" << finl;
63 Cerr << " \"lissage_courbure_iterations " << lissage_courbure_iterations_old_ << "\"" << finl;
64 Cerr << "To keep pre v1.9.6 behavior, replace it with:" << finl;
65 Cerr << " lissage_courbure_iterations_systematique " << lissage_courbure_iterations_old_ <<finl;
66 Cerr << " lissage_courbure_iterations_si_remaillage " << lissage_courbure_iterations_old_ << finl;
68 }
69
71 {
72 // ok on utilisera facteur_longueur_ideale_
73 }
74 else if (facteur_longueur_ideale_ == -1. && valeur_longueur_fixe_ > 0.)
75 {
76 // ok on utilisera longueur fixe
77 }
78 else if (facteur_longueur_ideale_ == -1. && valeur_longueur_fixe_ == -1.)
79 {
80 // Valeur par defaut:
81 if (dimension == 3)
83 else
85 }
86 else
87 {
88 Cerr << "Error in Remaillage_FT::readOn: It is an error to specify both facteur_longueur_ideale"
89 << " and critere_longueur_fixe parameters." << finl;
91 }
92 return is;
93}
94
95/*! @brief Cette fonction ne doit pas etre appelee
96 *
97 */
99{
100 Cerr << "Erreur : ::printOn n'est pas code." << finl;
101 assert(0);
102 return os;
103}
104
106{
107 Nom motlu;
108 is >> motlu;
109 if (motlu != que_suis_je())
110 {
111 Cerr << "Erreur dans Remaillage_FT::reprendre\n";
112 Cerr << " On attendait le motcle " << que_suis_je();
113 Cerr << "\n On a trouve " << motlu << finl;
114 assert(0);
116 }
118 {
119 Cerr << "Remaillage_FT::reprendre Format PDI not supported yet" << finl;
121 return 0;
122 }
123
126 return 1;
127}
128
130{
131 int special, afaire;
132 const int format_xyz = EcritureLectureSpecial::is_ecriture_special(special, afaire);
133 if (format_xyz)
134 {
136 {
137 os << que_suis_je() << finl;
138 os << temps_dernier_remaillage_ << finl;
139 os << temps_dernier_lissage_ << finl;
140 }
141 }
143 {
144 Cerr << "Remaillage_FT::sauvegarder Format PDI not supported yet" << finl;
146 }
147 else
148 {
149 os << que_suis_je() << finl;
150 os << temps_dernier_remaillage_ << finl;
151 os << temps_dernier_lissage_ << finl;
152 }
153 return 0;
154}
155
156/*! @brief Methode appelee par readOn.
157 *
158 * Declaration des parametres a lire dans le .data
159 *
160 */
162{
163 p.ajouter("pas", &dt_remaillage_);
164 p.ajouter("pas_lissage", &dt_lissage_);
165 p.ajouter("nb_iter_remaillage", &nb_iter_remaillage_);
166 p.ajouter("nb_iter_barycentrage", &nb_iter_barycentrage_);
167 p.ajouter("nb_iter_correction_volume", &nb_iter_bary_volume_seul_);
168 p.ajouter("seuil_dvolume_residuel", &seuil_dvolume_residuel_);
169 p.ajouter("relax_barycentrage", &relax_barycentrage_);
170 p.ajouter("critere_arete", &critere_arete_);
171 p.ajouter("impr", &impr_);
172 p.ajouter("critere_longueur_fixe", &valeur_longueur_fixe_);
173 p.ajouter("facteur_longueur_ideale", &facteur_longueur_ideale_);
174 p.ajouter("lissage_courbure_coeff", &lissage_courbure_coeff_);
175 // lissage_courbure_iterations est un synonyme de lissage_courbure_iterations_systematique
176 p.ajouter("lissage_courbure_iterations", &lissage_courbure_iterations_old_);
177 p.ajouter("lissage_courbure_iterations_systematique", &lissage_courbure_iterations_systematique_);
178 p.ajouter("lissage_courbure_iterations_si_remaillage", &lissage_courbure_iterations_si_remaillage_);
179 p.ajouter("lissage_critere", &lissage_critere_);
180}
181
182/*! @brief Cette fonction stocke le domaine_dis dans refdomaine_dis_
183 *
184 * @param (domaine_dis) domaine discretisee de calcul
185 * @return le flot d'entree
186 */
188{
189 Cerr<<"Remaillage_FT::associer_domaine_dis"<<finl;
190 refdomaine_VF_ = ref_cast(Domaine_VF,domaine_dis);
191}
192
193int Remaillage_FT::a_remailler(double temps, const Maillage_FT_Disc& maillage) const
194{
195 int res = 0;
196 if (dt_remaillage_ > 0.)
197 if (temps > (temps_dernier_remaillage_ + dt_remaillage_) * (1.-1e-15))
198 res = 1;
199 return res;
200}
201
202int Remaillage_FT::a_lisser(double temps) const
203{
204 int res = 0;
205 if ((dt_lissage_ > 0.) && (temps > (temps_dernier_lissage_ + dt_lissage_) * (1.-1e-15)))
206 res = 1;
207 return res;
208}
209
210/*! @brief Verifie les criteres de remaillage locaux (longueur des aretes) et effectue les remaillages locaux si necessaires.
211 *
212 */
214{
215 statistics().create_custom_counter("Remaillage_local_interface",3,"FrontTracking");
216 statistics().begin_count("Remaillage_local_interface",statistics().get_last_opened_counter_level()+1);
217
219
221 maillage.check_mesh();
222 //boucle sur les remaillages
223 int iter;
224 ArrOfDoubleFT varVolume;
225 for (iter = 0; iter < nb_iter_remaillage_; iter++)
226 {
227 const int nb_sommets = maillage.nb_sommets();
228 varVolume.resize_array(nb_sommets);
229 varVolume = 0.;
231 // n = nombre de sommets supprimes
232 const int n = supprimer_petites_aretes(maillage,varVolume);
234 maillage.check_mesh();
235 if (n > 0)
236 {
237 supprimer_doublons_facettes(maillage); // Marque les facettes mais ne les supprime pas effectivement.
239 maillage.check_mesh();
240 // On a supprime les petites aretes en deplacant un noeud sur
241 // un autre, la variation de volume engendree a ete mise dans varVolume:
242 // On barycentre et on lisse, notamment pour recuperer cette variation.
243 barycentrer_lisser_apres_remaillage(maillage, varVolume);
245 maillage.check_mesh();
246 }
247 const int m = diviser_grandes_aretes(maillage);
249 maillage.check_mesh();
250 if (m > 0)
251 {
252 varVolume.resize_array(maillage.nb_sommets());
253 varVolume = 0.;
254 barycentrer_lisser_apres_remaillage(maillage, varVolume);
256 maillage.check_mesh();
257 }
259 Journal() << "remaillage_local_interface t= " << temps << " suppressions: " << n << " divisions: " << m << finl;
260 }
261 nettoyer_maillage(maillage);
262 statistics().end_count("Remaillage_local_interface");
263}
264
265
266/*! @brief Cette fonction calcule les connectivites sommet ->facettes voisines Les facettes voisines des sommets sont stockees dans le tableau fa7VoisinesSom_data
267 *
268 * sous forme de liste chainee.
269 * Pour le sommet som, le premier index de la liste est index = fa7VoisinesSom_index[som]
270 * la premiere facette est alors fa7VoisinesSom_data(index,1)
271 * et l'indice suivant index = fa7VoisinesSom_data(index,0)
272 * La chaine est terminee lorsque index==-1.
273 *
274 * @param (maillage) maillage a barycentrer
275 * @param (fa7VoisinesSom_index) premier index pour le sommet som
276 * @param (fa7VoisinesSom_data) premier liste des index et facettes voisines pour le sommet som
277 * @return (int) le nombre de connectivites trouvees
278 */
280 ArrOfInt& fa7VoisinesSom_index,
281 IntTab& fa7VoisinesSom_data) const
282{
283 int compteur = 0;
284
285 const int nb_som = maillage.nb_sommets();
286 const int nb_facettes = maillage.nb_facettes();
287 const IntTab& facettes = maillage.facettes();
288 const int nb_som_par_facette = facettes.dimension(1);
289
290 int fa7, isom, som, trouve, index, index0 = -1;
291
292 //initialisation
293 for (som=0 ; som<nb_som ; som++)
294 {
295 fa7VoisinesSom_index[som] = -1;
296 }
297
298 //on balaye les facettes
299 for (fa7=0 ; fa7<nb_facettes ; fa7++)
300 {
301 //puis on balayes les sommets des facettes
302 for (isom=0 ; isom<nb_som_par_facette ; isom++)
303 {
304 som = facettes(fa7,isom);
305 //on va ensuite balayer la liste des facettes voisines du sommet som
306 //pour voir si la facette fa7 est deja stockee
307 index = fa7VoisinesSom_index[som];
308 if (index==-1)
309 {
310 //le sommet n'a pas encore de fa7 voisine stockee :
311 //l'ajoute a la premiere place dispo = compteur
312 fa7VoisinesSom_index[som] = compteur;
313 fa7VoisinesSom_data(compteur,0) = -1;
314 fa7VoisinesSom_data(compteur,1) = fa7;
315 compteur++;
316 }
317 else
318 {
319 //sinon : balaye la liste des facettes voisines du sommet som
320 trouve = -1;
321 while (index>=0 && trouve==-1)
322 {
323 index0 = index;
324 if (fa7VoisinesSom_data(index,1) == fa7)
325 trouve = index;
326 else
327 index = fa7VoisinesSom_data(index,0);
328 }
329 if (trouve==-1)
330 {
331 //fa7 non encore stockee
332 assert(index==-1 && index0!=-1);
333 //l'ajoute a la premiere place dispo = compteur
334 fa7VoisinesSom_data(index0,0) = compteur;
335 fa7VoisinesSom_data(compteur,0) = -1;
336 fa7VoisinesSom_data(compteur,1) = fa7;
337 compteur++;
338 }
339 }
340 }
341 }
342
343 return compteur;
344}
345
346/*! @brief Calcul de la differentielle du volume de phase 0 par rapport au deplacement de chaque sommet de l'interface.
347 *
348 * C'est une forme
349 * lineaire qu'on exprime sous la forme d'un vecteur v tel que
350 * differentielle(deplacement) = deplacement scalaire v.
351 * En un certain sens, v est la normale a l'interface evaluee aux sommets.
352 * Si on deplace le sommet dans un plan orthogonal au vecteur, le volume
353 * des phases est conserve a l'ordre 1 par rapport a l'amplitude du
354 * deplacement.
355 *
356 * @param (maillage)
357 * @param (differentielle_volume)
358 * @return (int (1))
359 */
361 const Maillage_FT_Disc& maillage,
362 DoubleTab& differentielle_volume) const
363{
364 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
365 const int nb_sommets = maillage.nb_sommets();
366 const int nb_facettes = maillage.nb_facettes();
367 const IntTab& facettes = maillage.facettes();
368 const int nb_som_par_facette = facettes.dimension(1);
369 int isom, fa7, k;
370
371 const int dim = Objet_U::dimension;
372 const double angle_bidim_axi = Maillage_FT_Disc::angle_bidim_axi();
373
374 differentielle_volume.resize(nb_sommets, dim);
375 differentielle_volume = 0.;
376
377 const double facteur = 1. / (double) dim;
378
379 // on balaye les facettes reelles : la differentielle du volume
380 // par rapport au deplacement d'un sommet est la somme des
381 // differentielles de volume engendre par chaque facette voisine
382 // du sommet. Pour une facette la differentielle de volume
383 // est :
384 if (!bidim_axi)
385 {
386 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
387 // normale_unitaire * surface / nb_sommets_par_facette
388 double normale[3] = { 0., 0., 0. };
389 for (fa7 = 0; fa7 < nb_facettes; fa7++)
390 {
391 if (maillage.facette_virtuelle(fa7))
392 continue;
393 //on balaye ses sommets
394 double surf = surface_facettes[fa7];
395 double x = surf * facteur;
396 for (k = 0; k < dim; k++)
397 normale[k] = normale_facettes(fa7, k);
398 // Ajout de la contribution de la facette a chacun des trois sommets.
399 for (isom=0 ; isom<nb_som_par_facette ; isom++)
400 {
401 int som = facettes(fa7,isom);
402 for (k = 0; k < dim; k++)
403 differentielle_volume(som,k) += x * normale[k];
404 }
405 }
406 }
407 else
408 {
409 const double un_tiers = 1. / 3.;
410 const double un_sixieme = 1. / 6.;
411 const DoubleTab& sommets = maillage.sommets();
412 // Cas bidim_axi
413 for (int facette = 0; facette < nb_facettes; facette++)
414 {
415 if (maillage.facette_virtuelle(facette))
416 continue;
417 const int s1 = facettes(facette, 0);
418 const int s2 = facettes(facette, 1);
419 const double r1 = sommets(s1, 0);
420 const double y1 = sommets(s1, 1);
421 const double r2 = sommets(s2, 0);
422 const double y2 = sommets(s2, 1);
423 const double L2 = (r2-r1)*(r2-r1) + (y2-y1)*(y2-y1);
424 const double L = sqrt(L2);
425 const double nx = normale_facettes(facette, 0);
426 const double ny = normale_facettes(facette, 1);
427 const double dv_dn1 = L * (r1 * un_tiers + r2 * un_sixieme) * angle_bidim_axi;
428 const double dv_dn2 = L * (r2 * un_tiers + r1 * un_sixieme) * angle_bidim_axi;
429 differentielle_volume(s1, 0) += nx * dv_dn1;
430 differentielle_volume(s1, 1) += ny * dv_dn1;
431 differentielle_volume(s2, 0) += nx * dv_dn2;
432 differentielle_volume(s2, 1) += ny * dv_dn2;
433 }
434 }
435 // Collection des donnees des sommets virtuels
436 const Desc_Structure_FT& desc = maillage.desc_sommets();
437 desc.collecter_espace_virtuel(differentielle_volume, MD_Vector_tools::EV_SOMME);
438 desc.echange_espace_virtuel(differentielle_volume);
439
440 return 1;
441}
442
443/*! @brief Cette fonction calcule la difference de volume au niveau d'une facette par rapport a une position initiale des sommets
444 *
445 * version 2D
446 *
447 * @param (fa7) indice de la facette de calcul
448 * @param (maillage) maillage a barycentrer
449 * @param (position_initiale) position initiale des sommets
450 * @return (double) la variation de volume
451 */
453 const DoubleTab& position_initiale) const
454{
455 const ArrOfInt& pe_owner = maillage.sommet_PE_owner();
456 const IntTab& facettes = maillage.facettes();
457 const DoubleTab& sommets = maillage.sommets();
458
459#if DEBUG_CONSERV_VOLUME
460#if VERBEUX
461 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
462 const DoubleTab& normales_facettes = maillage.get_update_normale_facettes();
463#endif
464#endif
465 double coord_som0[2], coord_som1[2], coord_som_opp[2];
466 const int som0 = facettes(fa7,0);
467 const int som1 = facettes(fa7,1);
468
469 const double angle_bidim_axi = bidim_axi ? Maillage_FT_Disc::angle_bidim_axi() : 0.;
470 const double un_tiers = 1. / 3.;
471
472 if (som0==som1)
473 {
474 //facette de surface nulle : sort
475 return 0.;
476 }
477
478 //on decompose la variation de volume en 2 triangles, lies aux deplacements successifs des sommets
479 int ordre = 0;
480 if ( (pe_owner[som0]==pe_owner[som1] && som0>som1) || (pe_owner[som0]>pe_owner[som1]) )
481 {
482 //l'ordre est inverse si :
483 // - les 2 sommets sont sur le meme proc, mais l'indice du sommet1 est plus petit que celui du sommet0
484 // - ou si le numero du proc du sommet1 est plus petit que celui du proc du sommet0
485 ordre = 1;
486 }
487 //premier triangle
488 coord_som0[0] = position_initiale(som0,0);
489 coord_som0[1] = position_initiale(som0,1);
490 coord_som1[0] = position_initiale(som1,0);
491 coord_som1[1] = position_initiale(som1,1);
492 if (ordre==0)
493 {
494 coord_som_opp[0] = sommets(som0,0);
495 coord_som_opp[1] = sommets(som0,1);
496 }
497 else
498 {
499 coord_som_opp[0] = sommets(som1,0);
500 coord_som_opp[1] = sommets(som1,1);
501 }
502 double v1 = FTd_calculer_aire_triangle(coord_som0,coord_som1,coord_som_opp);
503 if (bidim_axi)
504 // x_G : x coordinate of the centre of gravity is located at a third of the position of all vertex.
505 // Guldin's Theorem :
506 v1 *= (coord_som0[0] + coord_som1[0] + coord_som_opp[0]) * un_tiers * angle_bidim_axi;
507
508 //second triangle
509 if (ordre==0)
510 {
511 coord_som0[0] = sommets(som0,0);
512 coord_som0[1] = sommets(som0,1);
513 coord_som1[0] = position_initiale(som1,0);
514 coord_som1[1] = position_initiale(som1,1);
515 coord_som_opp[0] = sommets(som1,0);
516 coord_som_opp[1] = sommets(som1,1);
517 }
518 else
519 {
520 coord_som0[0] = position_initiale(som0,0);
521 coord_som0[1] = position_initiale(som0,1);
522 coord_som1[0] = sommets(som1,0);
523 coord_som1[1] = sommets(som1,1);
524 coord_som_opp[0] = sommets(som0,0);
525 coord_som_opp[1] = sommets(som0,1);
526 }
527 double v2 = FTd_calculer_aire_triangle(coord_som0,coord_som1,coord_som_opp);
528 if (bidim_axi)
529 v2 *= (coord_som0[0] + coord_som1[0] + coord_som_opp[0]) * un_tiers * angle_bidim_axi;
530#if DEBUG_CONSERV_VOLUME
531#if VERBEUX
532// On calcule pour comparaison la variation de volume dv par difference simple entre les
533// volumes initiaux et finaux (avant vs apres mouvement).
534// Je n'ai pas verifie si la somme est la meme in fine, sur le maillage.
535// En tout cas, sur un seul segment, les deux methodes different car lorsque la projection
536// sur dy du segment change, le volume genere par cette facette change, au detriment de sa voisine.
537// Mais in fine, ca n'a pas d'effet au global.
538// La methode standard, originelle, ne considere pas le mouvement d'un sommet selon la direction de la
539// facette comme generatrice de variation de volume. C'est mieux ainsi, de voir le transfert d'une facette
540// a l'autre comme globalement conservatif, donc pas comme une variation de volume.
541// Donc v1+v2 c'est mieux :D
542 if (bidim_axi)
543 {
544 const double un_sixieme = 1. / 6.;
545 double dy = position_initiale(som0,1)-position_initiale(som1,1);
546 double x0 = position_initiale(som0,0);
547 double x1 = position_initiale(som1,0);
548 // On n'a pas la vieille normale et la vieille surface pour calculer dy par s*nx
549 // ON S'APPUIE SUR ORDRE en esperant que ca marche.
550 const double vp1 = angle_bidim_axi * un_sixieme *dy*(x1*x1+x0*x0+x1*x0);
551
552 // Apres deplacement :
553 dy = sommets(som0,1)-sommets(som1,1);
554 x0 = sommets(som0,0);
555 x1 = sommets(som1,0);
556
557 //const double vp2 = angle_bidim_axi * un_sixieme *s*normale_scalaire_direction_x*(x1*x1+x0*x0+x1*x0);
558 const double vp2 = angle_bidim_axi * un_sixieme *dy*(x1*x1+x0*x0+x1*x0);
559
560 // Si tout va bien, on devrait avoir le meme signe :
561 const double s = surface_facettes[fa7];
562 const double normale_scalaire_direction_x = normales_facettes(fa7, 0);
563 Cerr << "dy=" << dy << " s.nx " << s*normale_scalaire_direction_x << finl;
564 assert(normale_scalaire_direction_x*dy>=0.);
565
566 const double dv = vp2 - vp1;
567
568 Cerr << "Remaillage_FT::calculer_variation_volume_facette_2D" << finl;
569 Cerr << "Positions ini(x;y) -> fin(x;y) "
570 << "som0(" << position_initiale(som0,0)<< ";"<< position_initiale(som0,1)<< ") "
571 "som1(" << position_initiale(som1,0)<< ";"<< position_initiale(som1,1)<< ") "
572 << " -> "
573 "som0(" << sommets(som0,0)<< ";"<< sommets(som0,1)<< ") "
574 "som1(" << sommets(som1,0)<< ";"<< sommets(som1,1)<< ") "
575 << finl;
576 Cerr << "v1= " << v1 << finl;
577 Cerr << "v2= " << v2 << finl;
578 Cerr << "v1+v2= " << v1+v2 << finl;
579 Cerr << "vp1= " << vp1 << finl;
580 Cerr << "vp2= " << vp2 << finl;
581 Cerr << "dv= " << dv << finl;
582 return v1+v2; // quand meme !
583 //return dv;
584 }
585#endif
586#endif
587 return v1 + v2;
588}
589
590/*! @brief Cette fonction calcule la difference de volume au niveau d'une facette par rapport a une position initiale des sommets
591 *
592 * Methode corrigee le 11 juillet 2013 par B.M: dans la version precedente, l'implementation
593 * du tri des trois sommets en fonction de l'indice global des sommets etait faux
594 * d'ou de petites et rares erreurs de conservation du volume en parallele.
595 * version 3D
596 *
597 * @param (fa7) indice de la facette de calcul
598 * @param (maillage) maillage a barycentrer
599 * @param (position_initiale) position initiale des sommets
600 * @return (double) la variation de volume
601 */
602static inline double calculer_volume_facette_3D_avec_ordre(const DoubleTab& position_initiale,
603 const DoubleTab& position_finale,
604 int facette[3],
605 int ordre_sommets[3])
606{
607 double v = 0.;
608 // On va couper le prisme en 3 tetraedres.
609 // 4 sommets du tetraedre courant:
610 FTd_vecteur3 sommets_base[3], sommet4;
611 // Initialisation des sommets de la base avec la facette en position initiale:
612 {
613 for (int i = 0; i < 3; i++)
614 for (int j = 0; j < 3; j++)
615 sommets_base[i][j] = position_initiale(facette[i], j);
616 }
617 for (int tetra = 0; tetra < 3; tetra++)
618 {
619 // Indice du 4e sommet dans la facette courante (sur le maillage deplace)
620 const int indice_sommet4 = ordre_sommets[tetra];
621 // Position du 4e sommet:
622 {
623 for (int i = 0; i < 3; i++)
624 sommet4[i] = position_finale(facette[indice_sommet4], i);
625 }
626 v += FTd_calculer_volume_tetraedre(sommets_base[0], sommets_base[1], sommets_base[2], sommet4);
627 {
628 for (int i = 0; i < 3; i++)
629 sommets_base[indice_sommet4][i] = sommet4[i];
630 }
631 }
632 return v;
633}
634
636 const DoubleTab& position_initiale) const
637{
638 double varVolume = 0.;
639 int facette[3];
640 {
641 const IntTab& facettes = maillage.facettes();
642 for (int i = 0; i < 3; i++)
643 facette[i] = facettes(fa7, i);
644 }
645 const DoubleTab& position_finale = maillage.sommets();
646#ifdef ALGO_NON_PARALLELE
647 int ordre_sommets[3] = { 0, 1, 2 };
648 // Calcul de l'ordre dans lequel on va construire les 3 tetraedres (ordre croissant des indices globaux
649 // des sommets (indice global = numero du pe_owner, numero sommet sur le pe_owner)
650 // Ce tri est important pour que le volume construit en extrudant le triangle de l'ancienne position a la
651 // nouvelle, approxime par des tetraedres, soit jointif avec les volumes construits pour les triangles
652 // voisins.
653 // En triant, on s'assure que pour chaque arete du maillage en triangle, le premier sommet choisi comme sommet4
654 // est le meme pour les deux triangles adjacents a l'arete (c'est le plus petit en indice global).
655 {
656 long long indice_global[3];
657 for (int i = 0; i < 3; i++)
658 {
659 int isom = facette[i];
660 indice_global[i] = ((long long) maillage.sommet_PE_owner_[isom]) << 32;
661 indice_global[i] += maillage.sommet_num_owner_[isom];
662 }
663 // Tri dans l'ordre croissant des indices_globaux (tri a bulles immediat)
664#define check_swap(i,j) \
665if (indice_global[ordre_sommets[i]] > indice_global[ordre_sommets[j]]) \
666 { int x = ordre_sommets[i]; ordre_sommets[i] = ordre_sommets[j]; ordre_sommets[j] = x; }
667 check_swap(0,1);
668 check_swap(1,2);
669 check_swap(0,1);
670#undef check_swap
671 }
672 varVolume = calculer_volume_facette_3D_avec_ordre(position_initiale, position_finale, facette, ordre_sommets);
673#else
674 {
675 // Calcul le volume avec toutes les permutations possibles de l'ordre des sommets, devient independant de l'ordre
676 // des sommets du maillage, donc du decoupage
677 int ordre_sommets[6][3] =
678 {
679 { 0, 1, 2 },
680 { 0, 2, 1 },
681 { 1, 2, 0 },
682 { 1, 0, 2 },
683 { 2, 0, 1 },
684 { 2, 1, 0 }
685 };
686 for (int i = 0; i < 6; i++)
687 varVolume += calculer_volume_facette_3D_avec_ordre(position_initiale, position_finale, facette, ordre_sommets[i]);
688 varVolume /= 6.;
689 }
690#endif
691 return varVolume;
692}
693
694/*! @brief Cette fonction calcule le volume de phase 0 engendre par chaque sommet lors du deplacement de l'interface entre la position initiale et la position actuelle
695 *
696 * du maillage (le volume engendre est positif si l'interface se deplace dans la
697 * direction de la normale aux facettes).
698 * On definit d'abord le volume engendre par le deplacement de chaque facette :
699 * C'est le volume d'un polyedre construit comme reunion de trois tetraedres,
700 * engendres par deplacement successifs des trois sommets
701 * dans un ordre conventionnel (deux sommets d'une arete sont toujours deplaces
702 * dans le meme ordre pour que les deux triangles voisins engendrent des
703 * tetraedres conformes, sans laisser de trous et sans se chevaucher)
704 * Ensuite, le volume engendre par chaque facette est divise en trois parts egales
705 * et reparti sur les trois sommets de la facette.
706 *
707 * @param (maillage) maillage
708 * @param (position_initiale) position initiale des sommets (doit avoir la meme taille que maillage.sommets(), et l'espace virtuel doit etre a jour)
709 * @param (varVolume) la variation de volume pour chaque sommet (on lui donne la bonne taille et on met a jour l'espace virtuel)
710 * @return (double) Variation de volume totale sur l'ensemble du domaine.
711 */
713 const DoubleTab& position_initiale,
714 ArrOfDouble& varVolume) const
715{
716 double dvolume_total = 0.;
717
718 const int nb_facettes = maillage.nb_facettes();
719 const int nb_sommets = maillage.nb_sommets();
720 const IntTab& facettes = maillage.facettes();
721 const int nb_som_par_facette = facettes.dimension(1);
722 const double inv_som_facette = 1. / (double) nb_som_par_facette;
723
724 varVolume.resize_array(nb_sommets);
725 varVolume = 0.;
726
727 int fa7;
728 const int dimension3 = (Objet_U::dimension==3);
729
730 for (fa7 = 0; fa7 < nb_facettes; fa7++)
731 {
732 // Traitement des facettes reelles uniquement:
733 if (maillage.facette_virtuelle(fa7))
734 continue;
735
736 double dv;
737 if (dimension3)
738 dv = calculer_variation_volume_facette_3D(fa7,maillage,position_initiale);
739 else
740 dv = calculer_variation_volume_facette_2D(fa7,maillage,position_initiale);
741 dvolume_total += dv;
742 // Redistributes the volume variation to the ndim vertices (2 or 3).
743 // Some volume will end on virtual vertices; hence, we'll have to "collect" contribution in the end.
744 dv *= inv_som_facette;
745 int isom;
746 for (isom = 0 ; isom < nb_som_par_facette ; isom++)
747 {
748 const int sommet = facettes(fa7, isom);
749 varVolume[sommet] += dv;
750 }
751 }
752 // Collecting varVolume contributions on virtual space.
753 // and finally add it to the real contribution.
754 const Desc_Structure_FT& desc = maillage.desc_sommets();
756 desc.echange_espace_virtuel(varVolume);
757
758 dvolume_total = mp_sum(dvolume_total);
759 return dvolume_total;
760}
761
762/*! @brief Cette fonction calcule une correction sur un deplacement liee a une variation de volume imposee
763 * Utile pour IJK
764 *
765 * @param (deplacement) delacement a corriger
766 * @param (varVolume) la variation de volume
767 * @param (deplacement_varVolume) la normale au plan de conservation de volume
768 * @param (norme2_deplacement_varVolume) carre de la normale au plan
769 * @return (int) 1 si le barycentrage s'est deroule correctement, 0 sinon
770 */
772 const ArrOfDouble& varVolume,
773 const DoubleTab& deplacement_varVolume,
774 const ArrOfDouble& norme2_deplacement_varVolume) const
775{
776 int res = 1;
777 const int nb_som = deplacement.dimension(0);
778 int som,k;
779 double scal, dvn;
780#ifndef NDEBUG
781 if (impr_>1000)
782 {
783 Process::Journal()<<"Remaillage_FT::calculer_correction_deplacement nb_som="<<nb_som<<" variation_volume_= "<<variation_volume_;
784 Process::Journal()<<" surface_interface_= "<<surface_interface_<<" ->depl= "<<variation_volume_/surface_interface_<<finl;
785 }
786#endif
787
788 double coeff_depl,coeff_varV;
789#ifndef NDEBUG
790 double depl,depl_max = 0.;
791#endif
792
793 coeff_depl = 1.;
794 coeff_varV = 1.; //correction due a la variation de volume deconnectee
795
796 for (som=0 ; som<nb_som ; som++)
797 {
798 if (norme2_deplacement_varVolume[som]!=0.)
799 {
800 //si norme2_deplacement_varVolume[som]==0., on ne modifie pas le deplacement,
801 //ca peut arriver lors d'etape de remaillage (c'est sommet supprime en fait, et qui
802 //n'est plus lie a aucune facette)
803 scal = 0.;
804 for (k=0 ; k<dimension ; k++)
805 {
806 scal += deplacement(som,k) * deplacement_varVolume(som,k);
807 }
808
809#ifndef NDEBUG
810 if (impr_>9000)
811 {
812 if (varVolume[som]!=0.)
813 Process::Journal()<<"correcDepl sommet "<<som<<" varVolume= "<<varVolume[som]<<" scal= "<<scal<<finl;
814 }
815#endif
816#if 1
817 // cas avec correction par sommet
818 double norme = sqrt(norme2_deplacement_varVolume[som]);
819 for (k=0 ; k<dimension ; k++)
820 {
821 dvn = deplacement_varVolume(som,k) / norme2_deplacement_varVolume[som];
822 deplacement(som,k) = relax_barycentrage_ * (
823 coeff_depl * ( deplacement(som,k) - scal * dvn ) -
824 coeff_varV * varVolume[som] * deplacement_varVolume(som,k)/norme );
825 }
826#else
827 //cas avec correction globale
828 double norme = sqrt(norme2_deplacement_varVolume[som]);
829 for (k=0 ; k<dimension ; k++)
830 {
831 dvn = deplacement_varVolume(som,k) / norme2_deplacement_varVolume[som];
832 deplacement(som,k) = relax_barycentrage_ * (
833 coeff_depl * ( deplacement(som,k) - scal * dvn ) -
834 coeff_varV * variation_volume_/surface_interface_ * deplacement_varVolume(som,k)/norme );
835 }
836#endif
837#ifndef NDEBUG
838 if (impr_>5000)
839 {
840 depl = 0.;
841 for (k=0 ; k<dimension ; k++)
842 {
843 depl += deplacement(som,k) * deplacement(som,k);
844 }
845 depl = sqrt(depl);
846 if (depl>depl_max)
847 {
848 depl_max = depl;
849 }
850 }
851#endif
852 }
853 }
854
855#ifndef NDEBUG
856 if (impr_>5000)
857 {
858 Process::Journal()<<" variation_volume_depl_max="<<depl_max<<finl;
859 }
860#endif
861
862 return res;
863}
864
865/*! @brief Cette fonction calcule pour chaque sommet le barycentre de l'ensemble des facettes voisines du sommet.
866 *
867 * Les "dimension" premieres colonnes
868 * contiennent les coordonnees du barycentre, la colonne "dimension"
869 * contient la somme des surfaces des facettes voisines du sommet.
870 *
871 * @param (maillage) maillage a barycentrer
872 * @param (barycentres) par sommet, barycentres de ses facettes voisines
873 * @return (int) toujours 1...
874 */
876 DoubleTab& barycentres) const
877{
878 int res = 1;
879 const int nb_facettes = maillage.nb_facettes();
880 const int nb_sommets = maillage.nb_sommets();
881 const IntTab& facettes = maillage.facettes();
882 const DoubleTab& sommets = maillage.sommets();
883 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
884
885 // colonnes 1..dimension - 1 : coordonnees du barycentre
886 // colonne dimension : surface des facettes voisines
887 barycentres.resize(nb_sommets, dimension+1);
888 barycentres = 0.;
889
890 const int dim = Objet_U::dimension;
891 const double inv_dim = 1. / (double) dim;
892
893 int fa7, som, isom, k;
894 for (fa7=0 ; fa7<nb_facettes ; fa7++)
895 {
896 if (maillage.facette_virtuelle(fa7))
897 continue;
898
899 double bary[3] = {0., 0., 0.};
900 for (isom = 0; isom < dim; isom++)
901 {
902 const int sommet = facettes(fa7, isom);
903 for (k = 0; k < dim; k++)
904 bary[k] += sommets(sommet,k);
905 }
906 const double surface = surface_facettes[fa7];
907 const double surface_inv_dim = surface * inv_dim;
908 for (isom = 0; isom < dim; isom++)
909 {
910 const int sommet = facettes(fa7, isom);
911 for (k = 0; k < dim; k++)
912 barycentres(sommet, k) += bary[k] * surface_inv_dim;
913 barycentres(sommet, dim) += surface;
914 }
915 }
916
917 //sommation des surf*barycentre et surfaces des fa7 voisines
918 const Desc_Structure_FT& desc = maillage.desc_sommets();
920
921 //normalisation par la surface totale des facettes voisines
922 for (som=0 ; som<nb_sommets ; som++)
923 {
924 if (maillage.sommet_virtuel(som))
925 continue;
926
927 const double surface = barycentres(som, dim);
928 if (surface <= 0.)
929 {
930 // Surface nulle (pas impossible), le barycentre est le sommet
931 for (k=0 ; k<dim ; k++)
932 {
933 barycentres(som,k) = sommets(som,k);
934 }
935 }
936 else
937 {
938 const double inverse_surface = 1. / surface;
939 for (k=0 ; k<dimension ; k++)
940 barycentres(som,k) *= inverse_surface;
941 }
942 }
943 desc.echange_espace_virtuel(barycentres);
944
945 return res;
946}
947
948#if DEBUG_CONSERV_VOLUME
949// Beware, this algorithm is only efficient
950// IF the interfaces are closed in the direction considered
951// (for the normal as well as for the coordinate)!
952// OR IF the opening face is at the value zero of the coordinate?
953double Remaillage_FT::calculer_volume_mesh(const Maillage_FT_Disc& mesh) const
954{
955 const int n = mesh.nb_facettes();
956 double volume = 0.;
957 const ArrOfDouble& surfaces_facettes = mesh.get_update_surface_facettes();
958 const DoubleTab& normales_facettes = mesh.get_update_normale_facettes();
959 const IntTab& facettes = mesh.facettes();
960 const DoubleTab& sommets = mesh.sommets();
961 const int DIR_projection = 0; // On projette sur (0->x ou 1->y ou 2->z if DIM=3)
962 for (int i = 0; i < n; i++)
963 {
964 if (mesh.facette_virtuelle(i))
965 continue;
966 const double s = surfaces_facettes[i];
967 const double normale_scalaire_direction = normales_facettes(i, DIR_projection);
968 // Coordonnee du centre de gravite de la facette
969 const int i0 = facettes(i,0);
970 const int i1 = facettes(i,1);
971 double coord_centre_gravite_DIR = sommets(i0,DIR_projection) + sommets(i1,DIR_projection) ;
972 if (Objet_U::dimension==3)
973 {
974 const int i2 = facettes(i,2);
975 coord_centre_gravite_DIR += sommets(i2,DIR_projection);
976 }
977 coord_centre_gravite_DIR /= (float) Objet_U::dimension;
978 //const double coord_centre_gravite_i = (sommets(i0,0) + sommets(i1,0) + sommets(i2,0)) / 3.;
979 //const double coord_centre_gravite_k = (sommets(i0,2) + sommets(i1,2) + sommets(i2,2)) / 3.;
980 double volume_prisme=0;
982 {
983 const double angle_bidim_axi = Objet_U::bidim_axi ? Maillage_FT_Disc::angle_bidim_axi() : 0.;
984 const double x0 = sommets(i0,0);
985 const double x1 = sommets(i1,0);
986 // The volume can actually be negative when normale_scalaire_direction is negative.
987 volume_prisme = angle_bidim_axi / 6. * (s * normale_scalaire_direction) * (x0*x0+x1*x1+x0*x1);
988 }
989 else
990 {
991 volume_prisme = coord_centre_gravite_DIR * s * normale_scalaire_direction; // coord_centre_gravite_DIR, where dir should be the
992 }
993 volume += volume_prisme;
994 }
995 volume = Process::mp_sum(volume);
996 return volume;
997}
998
999double Remaillage_FT::calculer_somme_dvolume(const Maillage_FT_Disc& mesh, const ArrOfDouble& dvolume) const
1000{
1001
1002 const int n = dvolume.size_array();
1003 assert(n == mesh.nb_sommets());
1004 double somme = 0.;
1005 for (int i = 0; i < n; i++)
1006 {
1007 if (!mesh.sommet_virtuel(i))
1008 {
1009 somme += dvolume[i];
1010 }
1011 }
1012 somme = Process::mp_sum(somme);
1013 return somme;
1014}
1015#endif
1016
1017/*! @brief Deplace les sommets du maillage pour les redistribuer de facon homogene.
1018 *
1019 * Le deplacement est la somme d'une composante tangentielle et d'une composante
1020 * normale a l'interface. La composante tangentielle ramene le sommet vers le
1021 * barycentre des facettes voisines du sommet. La composante normale est calculee
1022 * de sorte a produire la variation de volume imposee.
1023 * Traitement des lignes de contact: le deplacement est decompose en une composante
1024 * normale a la ligne de contact et une composante tangente.
1025 *
1026 * @param (maillage) le maillage a redistribuer (il retourne dans l'etat minimal)
1027 * @param (relaxation_direction_tangente) si ce parametre vaut 1, le sommet est deplace sur le barycentre. le parametre fixe la fraction du deplacement a realiser.
1028 * @param (relaxation_direction_normale)
1029 */
1031 const double relaxation_direction_tangente,
1032 const double relaxation_direction_normale,
1033 ArrOfDouble& var_volume_impose,
1034 ArrOfDouble& var_volume_obtenu) const
1035{
1036
1037 var_volume_impose.resize_array(maillage.nb_sommets());
1038 assert(relaxation_direction_tangente >= 0. && relaxation_direction_tangente <= 1.);
1039 assert(relaxation_direction_normale >= 0. && relaxation_direction_normale <= 1.);
1040 assert(var_volume_impose.size_array() == maillage.sommets().dimension(0));
1041
1042 const int nb_som = maillage.nb_sommets();
1043 const int dim = Objet_U::dimension;
1044
1045 DoubleTabFT differentielle_volume;
1046 DoubleTabFT barycentres;
1047 DebogFT::verifier_maillage_ft("Remaillage_FT::redistribuer_sommets maillage initial", maillage);
1048 DebogFT::verifier_tableau_sommets("Remaillage_FT::redistribuer_sommets var_volume_impose", maillage, var_volume_impose);
1049 calculer_differentielle_volume (maillage, differentielle_volume);
1050 DebogFT::verifier_tableau_sommets("Remaillage_FT::redistribuer_sommets differentielle volume", maillage, differentielle_volume);
1051 calculer_barycentre_facettes_voisines(maillage, barycentres);
1052 DebogFT::verifier_tableau_sommets("Remaillage_FT::redistribuer_sommets barycentres", maillage, barycentres);
1053
1054
1055 // Copie du tableau des sommets pour calculer la variation de volume a posteriori:
1056 DoubleTabFT sommets(maillage.sommets());
1057 DoubleTabFT deplacement(nb_som, dim);
1058
1059 // Estimation du deplacement a realiser
1060 // Dans la direction tangente, on va vers le barycentre des facettes voisines.
1061 // Dans la direction normale, on va pour obtenir la variation de volume impose.
1062 // Le vecteur normal (direction de deplacement pour faire varier le volume)
1063 double normale[3] = { 0., 0., 0. };
1064 // Differentielle du volume par rapport au deplacement
1065 double diff[3] = {0., 0., 0.};
1066 // Le deplacement tangent (direction de deplacement qui conserve le volume)
1067 double dtangent[3] = { 0., 0., 0. };
1068 double depl[3] = { 0., 0., 0. };
1069 int sommet, k;
1070 int clipped_move = 0; // Compteur de deplacements tronques
1071 const int dim3 = (Objet_U::dimension==3);
1072 const Parcours_interface& parcours = maillage.refparcours_interface_.valeur();
1073
1074 for (sommet = 0; sommet < nb_som; sommet++)
1075 {
1076 // Calcul des sommets reels uniquement :
1077 if (maillage.sommet_virtuel(sommet))
1078 continue;
1079 // Calcul de la direction du deplacement normal:
1080 // Pour une ligne de contact c'est la projection de la differentielle
1081 // du volume sur le bord (composante normale a la ligne de contact)
1082 // Sinon c'est la differentielle du volume
1083 normale[0] = diff[0] = differentielle_volume(sommet, 0);
1084 normale[1] = diff[1] = differentielle_volume(sommet, 1);
1085 if (dim3)
1086 normale[2] = diff[2] = differentielle_volume(sommet, 2);
1087 const int face_bord = maillage.sommet_face_bord_[sommet];
1088 if (face_bord >= 0)
1089 parcours.projeter_vecteur_sur_face(face_bord, normale[0], normale[1], normale[2]);
1090
1091 // Normaliser le vecteur "normale".
1092 double norme2_n = normale[0]*normale[0] + normale[1] * normale[1] + normale[2]*normale[2];
1093 if (norme2_n == 0.)
1094 {
1095 // Le maillage est mal foutu, on va vers le barycentre sans se
1096 // preoccuper de conserver le volume.
1097 }
1098 else
1099 {
1100 double x = 1. / sqrt(norme2_n);
1101 normale[0] *= x;
1102 normale[1] *= x;
1103 normale[2] *= x;
1104 }
1105
1106 // Produit scalaire normale * differentielle:
1107 // (is actually equal to the norm of the differential IF we're not on a contact line)
1108 const double normale_scal_diff = normale[0] * diff[0] + normale[1] * diff[1] + normale[2] * diff[2];
1109 const double i_normale_scal_diff = (normale_scal_diff == 0.) ? 0. : 1./normale_scal_diff;
1110 // Produit scalaire de deplacement tangent avec la normale:
1111 double dtangent_scalaire_n = 0.;
1112 for (k = 0; k < dim; k++)
1113 {
1114 double x = barycentres(sommet,k) - sommets(sommet, k);
1115 dtangent[k] = x;
1116 dtangent_scalaire_n += x * normale[k];
1117 }
1118 const double a = dtangent_scalaire_n;
1119 // Amplitude du deplacement normal a realiser pour obtenir la variation de volume impose
1120 const double b = var_volume_impose[sommet] * i_normale_scal_diff;
1121 double norme2_deplacement = 0.;
1122 for (k = 0; k < dim; k++)
1123 {
1124 // Deplacement dans la direction tangente (projection du vecteur
1125 // "sommets -> barycentres" sur le plan orthogonal a la normale :
1126 double dt = (dtangent[k] - normale[k] * a) * relaxation_direction_tangente;
1127 // Deplacement dans la direction normale (tel que la variation
1128 // du volume soit egale a la variation imposee)
1129 double dn = normale[k] * b * relaxation_direction_normale;
1130 double x = dt + dn;
1131 depl[k] = x;
1132 norme2_deplacement += x * x;
1133 }
1134 {
1135 // Si l'amplitude du deplacement est superieure a la taille caracteristique
1136 // des facettes, alors on tronque le deplacement.
1137 double facteur = 1.;
1138 double surface_totale_sommet = barycentres(sommet, dim);
1139 if (norme2_deplacement > barycentres(sommet, dim))
1140 {
1141 clipped_move++;
1142 facteur = sqrt(surface_totale_sommet / norme2_deplacement);
1143 }
1144 for (k = 0; k < dim; k++)
1145 deplacement(sommet,k) = depl[k] * facteur;
1146 }
1147 }
1148 if (clipped_move > 0)
1149 {
1150 Journal() << "Remaillage_FT::redistribuer_sommets clipped_move "
1151 << clipped_move << " / " << nb_som << finl;
1152 }
1153 DebogFT::verifier_tableau_sommets("Remaillage_FT::redistribuer_sommets deplacement", maillage, deplacement);
1154 // Deplacement des sommets du maillage.
1155 const Desc_Structure_FT& desc = maillage.desc_sommets();
1156 desc.echange_espace_virtuel(deplacement);
1157 maillage.preparer_tableau_avant_transport(var_volume_impose, desc);
1158 maillage.preparer_tableau_avant_transport(sommets, desc);
1159
1160#if DEBUG_CONSERV_VOLUME
1161 double volume_init = calculer_volume_mesh(maillage);
1162 double dvol_init = calculer_somme_dvolume(maillage, var_volume_impose);
1163#endif
1164 maillage.transporter(deplacement);
1165#if DEBUG_CONSERV_VOLUME
1166 double volume_apres = calculer_volume_mesh(maillage);
1167#endif
1168 const int new_nb_som = maillage.nb_sommets();
1169 maillage.update_tableau_apres_transport(var_volume_impose, new_nb_som, desc);
1170 maillage.update_tableau_apres_transport(sommets, new_nb_som, desc);
1171
1172 DebogFT::verifier_maillage_ft("Remaillage_FT::redistribuer_sommets maillage final", maillage);
1173 // Calcul de la variation de volume obtenue :
1174 double dvolume_tot = calculer_variation_volume(maillage, sommets, var_volume_obtenu);
1175#if DEBUG_CONSERV_VOLUME
1176 double volume_apres2 = calculer_volume_mesh(maillage);
1177 double dvol_obtenu = calculer_somme_dvolume(maillage, var_volume_obtenu);
1178 Cerr << "Remaillage_FT::redistribuer_sommets BILAN "
1179 << " volume avt= " << volume_init
1180 << " apres= " << volume_apres
1181 << " apres2= " << volume_apres2
1182 << " dvolume demande= " << dvol_init
1183 << " obtenu= " << dvol_obtenu << finl;
1184#endif
1185 return dvolume_tot;
1186}
1187
1188/*! @brief deplacement des sommets se sorte a produire la variation de volume prescrite a chaque sommet.
1189 *
1190 * Precondition: pas de facettes virtuelles
1191 */
1192void Remaillage_FT::corriger_volume(Maillage_FT_Disc& maillage, ArrOfDouble& var_volume)
1193{
1194 corriger_volume_(maillage, var_volume, nb_iter_bary_volume_seul_);
1195}
1196void Remaillage_FT::corriger_volume_(Maillage_FT_Disc& maillage, ArrOfDouble& var_volume, const int nb_iter_corrections_vol)
1197{
1198 regulariser_maillage(maillage, var_volume,
1199 0., /* pas de deplacement tangent des sommets */
1200 0.,
1201 0, /* pas de barycentrage */
1202 0, /* pas de lissage */
1203 nb_iter_corrections_vol,
1205 supprimer_facettes_bord(maillage);
1206 nettoyer_maillage(maillage);
1207}
1208
1209/*! @brief applique barycentrage, lissage et correction de volume.
1210 *
1211 * On applique le nombre d'iterations de lissage systematique.
1212 *
1213 * Precondition: pas de facettes virtuelles
1214 */
1216{
1217 statistics().create_custom_counter("Barycentrer_lisser_sys",3,"FrontTracking");
1218 statistics().begin_count("Barycentrer_lisser_sys",statistics().get_last_opened_counter_level()+1);
1220 Journal() << "barycentrer_lisser_systematique" << finl;
1221 temps_dernier_lissage_ = temps;
1222 ArrOfDoubleFT var_volume(maillage.nb_sommets());
1223 var_volume = 0.;
1224 regulariser_maillage(maillage,
1225 var_volume,
1232 supprimer_facettes_bord(maillage);
1233 nettoyer_maillage(maillage);
1234 statistics().end_count("Barycentrer_lisser_sys");
1235}
1236
1237/*! @brief idem mais avec le nombre d'iterations de lissage si remaillage
1238 *
1239 * Precondition: pas d'elements virtuels (on doit avoir appele nettoyer_elements_virtuels())
1240 *
1241 */
1243{
1244 statistics().create_custom_counter("Barycentrer_lisser_apres_rem",3,"TrioCFD");
1245 statistics().begin_count("Barycentrer_lisser_apres_rem",statistics().get_last_opened_counter_level()+1);
1247 Journal() << "barycentrer_lisser_apres_remaillage" << finl;
1248 regulariser_maillage(maillage, var_volume,
1255 supprimer_facettes_bord(maillage);
1256 nettoyer_maillage(maillage);
1257 statistics().end_count("Barycentrer_lisser_apres_rem");
1258}
1259
1260/*! @brief Algorithme general de lissage du maillage.
1261 *
1262 * Permet de barycentrer, regulariser la courbure, et d'appliquer une correction de volume en deplacant
1263 * les noeuds dans la direction normale.
1264 *
1265 * @param (maillage) maillage a barycentrer
1266 * @param (var_volume) pour chaque sommet du maillage initial, variation de volume a obtenir lors du deplacement. En retour, on y met le residu (difference entre var_volume initial et var_volume obtenu lors du deplacement).
1267 * @return (double) erreur sur la variation totale de volume obtenue (en m3)
1268 */
1270 ArrOfDouble& var_volume,
1271 const double facteur_barycentrage_tangent,
1272 const double coeff_lissage,
1273 const int nb_iter_barycentrage,
1274 const int nb_iter_lissage,
1275 const int max_nb_iter_correction_volume,
1276 const double seuil_dvolume) const
1277{
1278 ArrOfDoubleFT var_volume_obtenu;
1279 // on boucle les barycentrages tant que les sommets sont deplaces
1280 double dvolume = 0.;
1281 int iteration = 0;
1282 int iteration_correction_volume = 0;
1283 for(iteration = 0; 1; iteration++)
1284 {
1285#if DEBUG_CONSERV_VOLUME
1286 double volume_initial=0, volume_final=0, dvol_init=0, dvol_redistributed=0;
1287 double dvol_apres_regulariser=0, dvol_obtenu=0, dvol_futur=0;
1288 double volume_interm1=0, volume_interm2=0, volume_interm3=0;
1289 {
1290 double vol = calculer_volume_mesh(maillage);
1291 volume_initial = vol;
1292 double dvol = calculer_somme_dvolume(maillage, var_volume);
1293 dvol_init = dvol;
1294 Cerr.precision(16);
1295 Cerr << "Remaillage_FT::regulariser_maillage iteration " << iteration
1296 << " volume= " << vol << " dvolume= " << dvol << finl;
1297
1298 }
1299#endif
1300 DebogFT::verifier_tableau_sommets("Remaillage_FT::regulariser var_vol initial", maillage, var_volume);
1301 if (iteration > 0)
1302 // Ne pas lisser la variation de volume demandee a la premiere iteration.
1303 // Ensuite, on repartit la correction de volume sur les noeuds voisins
1304 // pour eviter les singularites de deplacement des sommets:
1305 lisser_dvolume(maillage, var_volume, 1);
1306 DebogFT::verifier_tableau_sommets("Remaillage_FT::regulariser var_vol apres lisser", maillage, var_volume);
1307
1308#if DEBUG_CONSERV_VOLUME
1309 {
1310 volume_interm1 = calculer_volume_mesh(maillage);
1311 double dvol = calculer_somme_dvolume(maillage, var_volume);
1312 dvol_redistributed = dvol;
1313 Cerr << "Remaillage_FT::regulariser_maillage apres lisser dvolume "
1314 << " dvolume= " << dvol << finl;
1315
1316 }
1317#endif
1318 // A la premiere iteration, on ne regularise pas la courbure
1319 // (maillage risque d'etre vraiment pourri avec petites aretes partout)
1320 // regulariser_courbure() ne change pas le maillage, cette methode remplit
1321 // le tableau dv_courbure. Le deplacement est realise par redistribuer_sommets()
1322 if (iteration > 0 && iteration < nb_iter_lissage + 1)
1323 {
1324 ArrOfDoubleFT dv_courbure(maillage.nb_sommets());
1325 regulariser_courbure(maillage,
1327 dv_courbure);
1328 const int n = var_volume.size_array();
1329 for (int i = 0; i < n; i++)
1330 var_volume[i] += dv_courbure[i];
1331
1332 DebogFT::verifier_tableau_sommets("Remaillage_FT::regulariser var_vol apres ajout dv", maillage, var_volume);
1333#if DEBUG_CONSERV_VOLUME
1334 {
1335 volume_interm2 = calculer_volume_mesh(maillage);
1336 double dvol = calculer_somme_dvolume(maillage, dv_courbure);
1337 double dvolnew = calculer_somme_dvolume(maillage, var_volume);
1338 dvol_apres_regulariser = dvolnew;
1339 Cerr << "Remaillage_FT::regulariser_maillage apres calcul dvcourbure "
1340 << " dv courbure= " << dvol << finl;
1341
1342 }
1343#endif
1344
1345 }
1346
1347 // Faut-il barycentrer ?
1348 double facteur = facteur_barycentrage_tangent;
1349 if (iteration >= nb_iter_barycentrage)
1350 // non, on a fini les iterations de barycentrage
1351 facteur = 0.;
1352
1353 dvolume =
1354 redistribuer_sommets(maillage,
1355 facteur, // relaxation_direction_tangente
1356 1., // relaxation_direction_normale
1357 var_volume /* imposed */,
1358 var_volume_obtenu /* resulting */);
1359#if DEBUG_CONSERV_VOLUME
1360 {
1361 volume_interm3 = calculer_volume_mesh(maillage);
1362 double dvol = calculer_somme_dvolume(maillage, var_volume);
1363 dvol_obtenu = calculer_somme_dvolume(maillage, var_volume_obtenu);
1364 Cerr << "Remaillage_FT::regulariser_maillage apres redistribuer_sommets " << iteration
1365 << " dvolume demande= " << dvol
1366 << " dvolume obtenu= " << dvol_obtenu << finl;
1367 }
1368#endif
1369 DebogFT::verifier_tableau_sommets("Remaillage_FT::regulariser var_vol_obtenu", maillage, var_volume_obtenu);
1370
1371 // Calcul de la correction de volume a realiser a l'iteration suivante:
1372 var_volume -= var_volume_obtenu;
1373#if DEBUG_CONSERV_VOLUME
1374 {
1375 double vol = calculer_volume_mesh(maillage);
1376 volume_final = vol;
1377 double vvol = calculer_somme_dvolume(maillage, var_volume_obtenu);
1378 double dvol = calculer_somme_dvolume(maillage, var_volume);
1379 dvol_futur = dvol;
1380 Cerr << "Remaillage_FT::regulariser_maillage apres redistribuer_sommets " << iteration
1381 << " volume= " << vol
1382 << " var_vol obtenu= " << vvol
1383 << " dvolume= " << dvol
1384 << " variation calculee= " << volume_final-volume_initial << finl;
1385
1386 Cerr << "Remaillage_FT::regulariser_maillage "
1387 << "iteration " << iteration << finl
1388 << "volume_initial " << volume_initial << finl
1389 << "volume_final " << volume_final << finl
1390 << "dvol_init " << dvol_init << finl
1391 << "dvol_redistributed " << dvol_redistributed << finl//par lisser_dvol
1392 << "dvol_apres_regulariser " << dvol_apres_regulariser << finl // apres le lissage de la courbure
1393 << "dvol_obtenu " << dvol_obtenu << finl // uniquement celui engendre par redistribuer_sommets
1394 << "dvol_futur " << dvol_futur << finl // celui pour l'iteration future.
1395 << finl;
1396
1397 Cerr << "Remaillage_FT::regulariser_maillage VOLUMES "
1398 << "iteration " << iteration << finl
1399 << "volume_initial " << volume_initial << finl
1400 << "volume_interm1 " << volume_interm1 << finl
1401 << "volume_interm2 " << volume_interm2 << finl
1402 << "volume_interm3 " << volume_interm3 << finl
1403 << "volume_final " << volume_final << finl
1404 << finl;
1405
1406 }
1407#endif
1408
1409 if (iteration >= nb_iter_barycentrage-1 && iteration >= nb_iter_lissage)
1410 {
1411 // On a termine le barycentrage et le lissage de courbure.
1412 iteration_correction_volume++;
1413 // On s'arrete apres avoir converge en volume ou apres avoir atteint le nombre
1414 // max d'iterations de correction.
1415 if (iteration_correction_volume > max_nb_iter_correction_volume
1416 || std::fabs(dvolume) < seuil_dvolume)
1417 break;
1418 }
1419 };
1420
1421 return dvolume;
1422}
1423
1424/*! @brief Regularise le champ scalaire "var_volume" defini aux sommets du "maillage".
1425 *
1426 * On regularise en faisant calculant une valeur moyenne par facette,
1427 * puis en recalculant une moyenne aux sommets en fonction de la moyenne
1428 * aux faces. Les moyennes sont ponderees par la surface des facettes...
1429 * Le lissage est repete un nombre donne de fois.
1430 * Cette methode est utilisee pour lisser les corrections de volume et eviter
1431 * l'apparition de pointes sur les interfaces.
1432 *
1433 * @param (maillage) le support du champ a regulariser
1434 * @param (var_volume) le champ a regulariser (champ aux sommets du maillage)
1435 * @param (nb_iterations) nombre d'iterations de l'operation de regularisation.
1436 */
1438 ArrOfDouble& var_volume,
1439 const int nb_iterations) const
1440{
1441 DoubleTabFT barycentres;
1442 calculer_barycentre_facettes_voisines(maillage, barycentres);
1443 const ArrOfDouble& surfaces = maillage.get_update_surface_facettes();
1444 const int nb_facettes = maillage.nb_facettes();
1445 const IntTab& facettes = maillage.facettes();
1446 ArrOfDoubleFT dv_facettes(nb_facettes);
1447 const int dim = Objet_U::dimension;
1448 const double inv_dim = 1. / (double) dim;
1449 int facette, j, iter;
1450 for (iter = 0; iter < nb_iterations; iter++)
1451 {
1452 // Repartition de dvolume sur les faces au prorata de la
1453 // surface de la face
1454 dv_facettes = 0.;
1455 for (facette = 0; facette < nb_facettes; facette++)
1456 {
1457 if (maillage.facette_virtuelle(facette))
1458 continue;
1459 const double surface = surfaces[facette];
1460 for (j = 0; j < dim; j++)
1461 {
1462 int sommet = facettes(facette, j);
1463 double surface_tot = barycentres(sommet, dim);
1464 if (surface_tot > 0.)
1465 dv_facettes[facette] += surface / surface_tot * var_volume[sommet];
1466 }
1467 }
1468 // Ne pas faire echange espace virtuel (inutile car on n'utilise pas la partie virtuelle)
1469 // Repartition de dv_facettes aux sommets
1470 var_volume = 0.;
1471 for (facette = 0; facette < nb_facettes; facette++)
1472 {
1473 if (maillage.facette_virtuelle(facette))
1474 continue;
1475 double dv = dv_facettes[facette] * inv_dim;
1476 for (j = 0; j < dim; j++)
1477 {
1478 int sommet = facettes(facette, j);
1479 var_volume[sommet] += dv;
1480 }
1481 }
1482 const Desc_Structure_FT& desc_s = maillage.desc_sommets();
1484 desc_s.echange_espace_virtuel(var_volume);
1485 }
1486}
1487
1488/*! @brief Cette fonction permet de gerer le decollement de l'interface de la paroi Si un sommet de bord n'a pas de sommet voisin de bord
1489 *
1490 * et que son deplacement tend a le faire rentrer dans le domaine,
1491 * il est marque comme sommet interne
1492 *
1493 * @param (maillage) maillage a traiter
1494 * @param (deplacement) vecteur deplacement des sommets
1495 * @return (int) 1 si le remaillage s'est deroule correctement, 0 sinon
1496 */
1497int Remaillage_FT::traite_decollement(Maillage_FT_Disc& maillage, const DoubleTab& deplacement) const
1498{
1499 int res = 1;
1500 //fonction non utilisee en dimension 2
1501 if (dimension<3)
1502 {
1503 return 1;
1504 }
1505 const int nb_sommets = maillage.nb_sommets();
1506 const int nb_facettes = maillage.nb_facettes();
1507 const IntTab& facettes = maillage.facettes();
1508 const int nb_som_par_facette = facettes.dimension(1);
1509 ArrOfIntFT nbSomVois_bord(nb_sommets);
1510 nbSomVois_bord = 0;
1511 int fa7,som, nb_som_bord, isom;
1512
1513 for (fa7=0 ; fa7<nb_facettes ; fa7++)
1514 {
1515 nb_som_bord = 0;
1516 for (isom=0 ; isom<nb_som_par_facette ; isom++)
1517 {
1518 som = facettes(fa7,isom);
1519 if (maillage.sommet_ligne_contact(som))
1520 {
1521 nb_som_bord++;
1522 }
1523 }
1524 if (nb_som_bord>1)
1525 {
1526 nb_som_bord--;
1527 for (isom=0 ; isom<nb_som_par_facette ; isom++)
1528 {
1529 som = facettes(fa7,isom);
1530 if (maillage.sommet_ligne_contact(som))
1531 {
1532 nbSomVois_bord[som] += nb_som_bord;
1533 }
1534 }
1535 }
1536 }
1538
1539 const DoubleTab& sommets = maillage.sommets();
1540 const DoubleTab& xp = refdomaine_VF_->xp();
1541 double x,y,z=0., scal;
1542 for (som=0 ; som<nb_sommets ; som++)
1543 {
1544 const int elem = maillage.sommet_elem_[som];
1545 if (elem >= 0 /* sommet reel */
1546 && maillage.sommet_ligne_contact(som)
1547 && nbSomVois_bord[som]==0)
1548 {
1549 //sommet de bord, sans autre sommet voisin de bord
1550 //teste si le deplacement fait entrer le sommet dans le domaine
1551 //calcul de la normale entrante du domaine : vecteur sommet-cdg(elem)
1552 x = xp(elem,0) - sommets(som,0);
1553 y = xp(elem,1) - sommets(som,1);
1554 scal = x * deplacement(som,0) + y * deplacement(som,1);
1555 if (dimension==3)
1556 {
1557 z = xp(elem,2) - sommets(som,2);
1558 scal += z * deplacement(som,2);
1559 }
1560 if (scal>0.)
1561 {
1562#ifndef NDEBUG
1563 if (impr_>900)
1564 {
1565 Process::Journal()<<"Remaillage_FT::traite_decollement : decollement detecte"<<finl;
1566 maillage.printSom(som,Process::Journal());
1567 Process::Journal()<<" decoll= "<<deplacement(som,0)<<" "<<deplacement(som,1)<<" "<<deplacement(som,2)<<finl;
1568 }
1569#endif
1570 maillage.sommet_face_bord_[som] = -1;
1571 }
1572 }
1573 }
1575
1577 return res;
1578}
1579/*! @brief Cette fonction permet de gerer l'adherence de l'interface a la paroi Si une facette possede 3 sommets sur un paroi, elle est supprimee
1580 *
1581 * @param (maillage) maillage a traiter
1582 * @return (int) 1 si le remaillage s'est deroule correctement, 0 sinon
1583 */
1585{
1586 int res = 1;
1587 if (supprimer_facettes_bord(maillage)==1)
1588 {
1589#ifndef NDEBUG
1590 Process::Journal()<<"Remaillage_FT::traite_adherence : adherence detectee"<<finl;
1591#endif
1592 nettoyer_maillage(maillage);
1593 }
1595 return res;
1596}
1597
1598inline double produit_scalaire(const FTd_vecteur3& a, const FTd_vecteur3& b)
1599{
1600 return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
1601}
1602
1603inline void produit_vectoriel(const FTd_vecteur3& a, const FTd_vecteur3& b, FTd_vecteur3& resu)
1604{
1605 resu[0] = a[1]*b[2] - a[2]*b[1];
1606 resu[1] = a[2]*b[0] - a[0]*b[2];
1607 resu[2] = a[0]*b[1] - a[1]*b[0];
1608}
1609
1610/*! @brief Cette fonction marque a supprimer les facettes ayant leurs 3 sommets de bord Marquer a supprimer = condenser les 3 sommets en un seul (le sommet 0)
1611 *
1612 * MODIF GB 21/07/2015 : Pour le cas sloshing par exemple, si le domaine a des coins,
1613 * l'interface peut contenir un element dont les 3 sommets sont sur le bord
1614 * sans pour autant que la facette soit integralement sur le bord. Elle peut
1615 * avoir son 3eme cote dans le domaine. Dans ce cas, on la conserve.
1616 *
1617 * @param (maillage) maillage a remailler
1618 * @return (int) 1 si le remaillage s'est deroule correctement, 0 sinon
1619 */
1621{
1622
1623 int res = 0;
1624 if (!get_is_solid_particle())
1625 {
1626 const int nb_facettes = maillage.nb_facettes();
1627 IntTab& facettes = maillage.facettes_;
1628 const int nb_som_par_facette = facettes.dimension(1);
1629 // Raccourci vers les coordonnees des sommets du maillage eulerien
1630#define CONSERVER_FACETTES_COINS
1631#ifdef CONSERVER_FACETTES_COINS
1632 const int dim = Objet_U::dimension;
1633 const DoubleTab& normale_facettes = maillage.get_update_normale_facettes();
1634 const DoubleTab& sommets = maillage.sommets();
1635 const Parcours_interface& parcours = maillage.refparcours_interface_.valeur();
1636#endif
1637
1638 //DoubleTab xsom(3,3); // coords des sommets de la face: xs(isom_eul, direction)
1639 int fa7, isom, som =0, nb_bord;
1640 for (fa7=0 ; fa7<nb_facettes ; fa7++)
1641 {
1642 nb_bord = 0;
1643 for (isom=0 ; isom<nb_som_par_facette ; isom++)
1644 {
1645 som = facettes(fa7,isom);
1646 if (maillage.sommet_ligne_contact(som))
1647 {
1648 nb_bord++;
1649 }
1650 }
1651 if (nb_bord==dimension)
1652#ifndef CONSERVER_FACETTES_COINS
1653 {
1654 //facette de bord : supprimer
1655 res = 1;
1656#ifndef NDEBUG
1657 if (impr_>9000)
1658 {
1659 Process::Journal()<<" fa7_bord -> Supp ";
1660 maillage.printFa7(fa7,0,Process::Journal());
1661 }
1662#endif
1663
1664 for (isom=1 ; isom<nb_som_par_facette ; isom++)
1665 {
1666 facettes(fa7,isom) = facettes(fa7,0);
1667 }
1668 }
1669#else
1670 {
1671 //facette de bord : a supprimer ou pas? Pas si simple...
1672 // Pour le savoir, on regarde la normale a chacune des faces tour a tour.
1673 for (isom=0 ; isom<nb_som_par_facette ; isom++)
1674 {
1675 som = facettes(fa7,isom);
1676 const int face = maillage.sommet_face_bord_[som];
1677 FTd_vecteur3 v4= {0.,0.,0.};
1678 double s2 = 0.;
1679 if (dim==3) s2=sommets(som,2);
1680 parcours.calculer_normale_face_bord(face,
1681 sommets(som,0), sommets(som,1), s2,
1682 v4[0], v4[1], v4[2]);
1683 double ps=0.;
1684 for (int direction = 0; direction < dim; direction++)
1685 {
1686 ps += v4[direction]*normale_facettes(fa7,direction);
1687 }
1688 const double tol = 1.e-10;
1689 if (1. - std::fabs(ps)> tol)
1690 {
1691 // facette et face_bord ne sont pas coplanaires, on conserve la facette!
1692 }
1693 else
1694 {
1695 // facette et face_bord sont dans le meme plan, il faut supprimer cette facette
1696 // car c'est bien une facette de bord.
1697 res = 1;
1698#ifndef NDEBUG
1699 if (impr_>9000)
1700 {
1701 Process::Journal()<<" fa7_bord -> Supp ";
1702 maillage.printFa7(fa7,0,Process::Journal());
1703 }
1704#endif
1705 for (isom=1 ; isom<nb_som_par_facette ; isom++)
1706 {
1707 facettes(fa7,isom) = facettes(fa7,0);
1708 }
1709 // Attention, il semble important de sortir sinon, on reinterroge une facette nulle...
1710 // gain de temps et semble risque sinon..
1711 break;
1712 }
1713 }
1714 }
1715#endif
1716 }
1717
1718 maillage.check_mesh();
1719
1720 if (mp_sum(res) > 0)
1721 res = 1;
1722 }
1723 return res;
1724}
1725
1726/*! @brief fonction outil utilisee par Remaillage_FT::supprimer_petites_aretes.
1727 *
1728 * (SPA = Supprimer Petites Aretes)
1729 * Cette fonction parcourt le tableau "tab_aretesMarquees" qui est un resultat
1730 * de "marquer_aretes". tab_aretesMarquees contient une liste d'aretes
1731 * trop petites qu'on veut supprimer.
1732 * On supprime ces aretes en remplacant l'un des sommets de l'arete par l'autre
1733 * extremite. En general, deux triangles disparaissent (sauf arete
1734 * de bord). Plusieurs aretes adjacentes au meme point peuvent etre supprimees.
1735 * Pour chaque arete, on choisit le sommet a supprimer et le sommet a conserver.
1736 * Puis on verifie qu'un sommet supprime n'est pas utilise par une autre arete
1737 * pour etre conserve (non trivial en parallele).
1738 *
1739 * @param (sommets_remplacement) On resize le tableau a (maillage.nb_sommets(), 2), puis on y stocke pour chaque sommet: - sommets_remplacement(i,0) = -1, sommets_remplacement(i,1) = -1 (sommet non supprime) - sommets_remplacement(i,0) = PE, sommets_remplacement(i,1) = j (sommet a remplacer par le sommet reel d'indice local j sur PE) En sortie, sommets_remplacement a son espace_virtuel a jour.
1740 */
1741static void SPA_choisir_sommets_remplacement(const Maillage_FT_Disc& maillage,
1742 const IntTab& tab_aretesMarquees,
1743 IntTab& sommets_remplacement)
1744{
1745 const int nb_sommets = maillage.nb_sommets();
1746 const IntTab& facettes = maillage.facettes();
1747 const ArrOfInt& sommet_PE_owner = maillage.sommet_PE_owner();
1748 const ArrOfInt& sommet_num_owner = maillage.sommet_num_owner();
1749
1750 sommets_remplacement.resize(nb_sommets, 2);
1751 // On initialise le tableau a "no_PE": on mettra ensuite
1752 // les processeurs d'accord entre eux avec un
1753 // "collecter(Descripteur_FT::MIN_COLONNE1)"
1754 // Si tout le monde contient "no_PE", alors le noeud ne devra pas etre remplace.
1755 const int no_PE = Process::nproc();
1756 sommets_remplacement = no_PE;
1757
1758 // Pour chaque sommet, y a-t-il un processeur qui veut le conserver ?
1759 // (le sommet sert a remplacer d'autres sommets)
1760 // 0 => non sinon => oui
1761 ArrOfIntFT sommets_conserves(nb_sommets);
1762 sommets_conserves = 0;
1763
1764 // Parcours de la liste des aretes a supprimer. Pour chacune, on choisit
1765 // un sommet a conserver et un sommet a supprimer (le plus petit en numerotation
1766 // globale pour que le choix soit identique pour les deux triangles adjacents).
1767 const int n = tab_aretesMarquees.dimension(0);
1768 const int nb_som_par_facette = facettes.dimension(1);
1769 int i;
1770 for (i = 0; i < n; i++)
1771 {
1772 const int fa7 = tab_aretesMarquees(i,0);
1773 const int isom = tab_aretesMarquees(i,1);
1774 assert(isom >= 0 && isom < nb_som_par_facette);
1775 const int isom_s = (isom + 1 < nb_som_par_facette) ? isom + 1 : 0;
1776 const int som = facettes(fa7, isom);
1777 const int som_s = facettes(fa7, isom_s);
1778 const int bord = maillage.sommet_ligne_contact(som);
1779 const int bord_s = maillage.sommet_ligne_contact(som_s);
1780
1781 int somRempl = -1; // Le sommet de remplacement (num_owner)
1782 int somSupp = -1; // Le sommet supprime (indice local)
1783 if (bord == bord_s)
1784 {
1785 //les deux sommets sont sur le bord ou les 2 sont internes
1786 //on compare alors leur numero global
1787 const int pe = sommet_PE_owner[som];
1788 const int pe_s = sommet_PE_owner[som_s];
1789 const int numOwner = sommet_num_owner[som];
1790 const int numOwner_s = sommet_num_owner[som_s];
1791 if (FTd_compare_sommets_global(pe, numOwner, pe_s, numOwner_s) > 0)
1792 {
1793 //som_s>som : on garde som, on supprime som_s
1794 somRempl = som;
1795 somSupp = som_s;
1796 }
1797 else
1798 {
1799 //som_s<=som : on garde som_s, on supprime som
1800 somRempl = som_s;
1801 somSupp = som;
1802 }
1803 }
1804 else if (bord==1)
1805 {
1806 //som est de bord : on garde som, on supprimer som_s
1807 somRempl = som;
1808 somSupp = som_s;
1809 }
1810 else
1811 {
1812 //som_s est de bord : on garde som_s, on supprime som
1813 somRempl = som_s;
1814 somSupp = som;
1815 }
1816 // Remplacement du sommet si
1817 // * le sommet a supprimer ne l'a pas encore ete
1818 // * le sommet de remplacement n'a pas encore ete supprime
1819 // * le sommet a supprimer n'est pas utilise pour en remplacer un autre
1820 if ( sommets_remplacement(somRempl, 0) == no_PE
1821 && sommets_remplacement(somSupp, 0) == no_PE
1822 && sommets_conserves[somSupp] == 0)
1823 {
1824 const int pe = sommet_PE_owner[somRempl];
1825 const int le_som = sommet_num_owner[somRempl];
1826 sommets_remplacement(somSupp, 0) = pe;
1827 sommets_remplacement(somSupp, 1) = le_som;
1828 sommets_conserves[somRempl] = 1;
1829 }
1830 }
1831
1832 // Si un sommet est conserve sur un processeur, il ne doit etre supprime
1833 // sur aucun processeur. On fait la somme pour tous les processeurs
1834 // de "sommets_conserves" : si un sommet est conserve sur l'un, il devra
1835 // etre conserve sur tous.
1836 const Desc_Structure_FT& desc_sommets = maillage.desc_sommets();
1837 desc_sommets.collecter_espace_virtuel(sommets_conserves,
1839 desc_sommets.echange_espace_virtuel(sommets_conserves);
1840
1841 // On met aussi tous les processeurs d'accord sur le sommet de remplacement.
1842 // Choix arbitraire de l'un des sommets de remplacement parmi ceux
1843 // proposes par les differents processeurs.
1844 desc_sommets.collecter_espace_virtuel(sommets_remplacement,
1846 desc_sommets.echange_espace_virtuel(sommets_remplacement);
1847
1848 // Mise a jour de sommets_remplacement : -1 pour les sommets a conserver
1849 for (i = 0; i < nb_sommets; i++)
1850 {
1851 const int a_conserver = sommets_conserves[i];
1852 const int non_remplace = (sommets_remplacement(i,0) == no_PE);
1853 if (a_conserver || non_remplace)
1854 {
1855 sommets_remplacement(i,0) = -1;
1856 sommets_remplacement(i,1) = -1;
1857 }
1858 }
1859}
1860
1861/*! @brief A l'aide de "marquer_aretes", on determine les aretes trop petites du maillage.
1862 *
1863 * On les supprime en remplacant un sommet
1864 * d'une extremite de l'arete par le sommet de l'autre extremite.
1865 * Pour cela, on cree des sommets virtuels, des facettes nulles (deux ou
1866 * trois sommets confondus) et on change le volume des phases.
1867 * La variation de volume engendree est ajoutee a varVolume.
1868 *
1869 * @param (maillage) Le maillage a optimiser. Le maillage retourne a l'etat minimal, Le volume change, Certaines facettes sont "nulles" (plusieurs sommets confondus), On cree des sommets virtuels.
1870 * @param (varVolume) Un tableau de taille nb_sommets() contenant une valeur initiale de variation de volume. On augmente la taille du tableau (creation de sommets virtuels) et on ajoute la variation de volume du maillage due a la suppression des aretes. L'espace virtuel est a jour. Valeur de retour: nombre total (sur tous les procs) de sommets du maillage supprimes
1871 */
1873 ArrOfDouble& varVolume) const
1874{
1875 statistics().create_custom_counter("Supprimer_petites_aretes",3,"TrioCFD");
1876 statistics().begin_count("Supprimer_petites_aretes",statistics().get_last_opened_counter_level()+1);
1877 int nb_sommets_supprimes_tot = 0;
1878 int nb_sommets_supprimes = 0;
1879 do
1880 {
1881
1882 // Pour chaque sommet a remplacer:
1883 // colonne0: indice local du sommet a remplacer
1884 // colonne1: indice local du sommet de remplacement
1885 IntTabFT remplacement_ilocal(0,2);
1886
1887 {
1888 // ******************************************************
1889 // Recherche des aretes trop petites
1890 IntTabFT tab_aretesMarquees;
1891 {
1892 ArrOfIntFT tab_somD; // Inutilise
1893 DoubleTabFT tab_deplacement_somD; // Inutilise
1894 marquer_aretes(maillage,
1895 tab_aretesMarquees,
1896 tab_somD,
1897 tab_deplacement_somD,
1898 -1 /* marquage des aretes trop petites */);
1899 }
1900
1901 // ******************************************************
1902 // On supprime les aretes en remplacant une extremite par l'autre
1903 // (genere des triangles dont deux sommets sont confondus)
1904 // Determination des sommets a remplacer et des sommets de remplacement
1905 // en numerotation globale.
1906 IntTabFT sommets_remplacement;
1907 SPA_choisir_sommets_remplacement(maillage,
1908 tab_aretesMarquees,
1909 sommets_remplacement);
1910
1911 // ******************************************************
1912 // Certains sommets de remplacement n'existent pas encore sur le processeur local.
1913 // Creation de la liste des sommets de remplacement virtuels dont on aura besoin
1914 ArrOfIntFT request_sommets_pe;
1915 ArrOfIntFT request_sommets_num;
1916 int i;
1917 const int nb_sommets = maillage.nb_sommets();
1918 const int moi = Process::me();
1919 assert(nb_sommets == sommets_remplacement.dimension(0));
1920 for (i = 0; i < nb_sommets; i++)
1921 {
1922 const int pe = sommets_remplacement(i,0);
1923 const int som= sommets_remplacement(i,1);
1924 if (pe >= 0)
1925 {
1926 int j;
1927 if (pe != moi) // Le sommet de remplacement est virtuel
1928 {
1929 request_sommets_pe.append_array(pe);
1930 request_sommets_num.append_array(som);
1931 j = -1;
1932 }
1933 else
1934 {
1935 j = som;
1936 }
1937 remplacement_ilocal.append_line(i, j);
1938 }
1939 }
1940 // ******************************************************
1941 // Creation des sommets virtuels qui remplaceront les sommets supprimes
1942 // (certains existent peut-etre deja, ils ne seront pas recrees)
1943
1944 maillage.creer_sommets_virtuels_numowner(request_sommets_pe,
1945 request_sommets_num);
1946 // On a cree de nouveaux sommets virtuels. Mise a jour de varVolume:
1947 // Inutile de mettre a jour l'espace virtuel, l'echange sera fait
1948 // apres le calcul de dvolume
1949 {
1950 const int old_size = varVolume.size_array();
1951 const int new_size = maillage.nb_sommets();
1952 varVolume.resize_array(new_size);
1953 int ii;
1954 for (ii = old_size; ii < new_size; ii++)
1955 varVolume[ii] = 0.;
1956 }
1957 // ******************************************************
1958 // Calcul de l'indice local des sommets de remplacement
1959 ArrOfIntFT request_sommets_ilocal;
1960
1961 maillage.convertir_numero_distant_local(maillage.desc_sommets(),
1962 maillage.sommet_num_owner(),
1963 request_sommets_num,
1964 request_sommets_pe,
1965 request_sommets_ilocal);
1966 int j = 0;
1967 const int n_rempl = remplacement_ilocal.dimension(0);
1968 for (i = 0; i < n_rempl; i++)
1969 {
1970 int som_new = remplacement_ilocal(i,1);
1971 if (som_new < 0) // Le sommet de remplacement est virtuel ?
1972 {
1973 som_new = request_sommets_ilocal[j];
1974 remplacement_ilocal(i,1) = som_new;
1975 j++;
1976 }
1977 }
1978 }
1979 // ******************************************************
1980 // Determination de la variation de volume liee a la suppression des aretes
1981 // On calcule la variation de volume correspondant au deplacement des
1982 // noeuds remplaces vers les noeuds de remplacement.
1983 {
1984 const DoubleTab& sommets = maillage.sommets();
1985 // Nombre de sommets a remplacer
1986 const int n_rempl = remplacement_ilocal.dimension(0);
1987 DoubleTabFT position_finale(sommets); // Copie du tableau.
1988 int i;
1989 const int dim = Objet_U::dimension;
1990 for (i = 0; i < n_rempl; i++)
1991 {
1992 const int som_old = remplacement_ilocal(i,0);
1993 const int som_new = remplacement_ilocal(i,1);
1994 int j;
1995 for (j = 0; j < dim; j++)
1996 position_finale(som_old, j) = position_finale(som_new, j);
1997 }
1998 {
1999 ArrOfDoubleFT dvolume;
2001 position_finale,
2002 dvolume);
2003
2004 // Avant d'affecter la variation de volume des noeuds remplaces aux noeuds
2005 // de remplacement: certains sommets de remplacement sont virtuels,
2006 // il faut donc "collecter" les contributions a la fin. Donc il faut
2007 // annuler la valeur de varVolume pour les sommets virtuels avant
2008 // de commencer.
2009 const int n = maillage.nb_sommets();
2010 for (i = 0; i < n; i++)
2011 {
2012 if (maillage.sommet_virtuel(i))
2013 varVolume[i] = 0.;
2014 else
2015 varVolume[i] += dvolume[i];
2016 }
2017 }
2018 for (i = 0; i < n_rempl; i++)
2019 {
2020 const int som_old = remplacement_ilocal(i,0);
2021 const int som_new = remplacement_ilocal(i,1);
2022 const double dv = varVolume[som_old];
2023 varVolume[som_new] += dv;
2024 varVolume[som_old] = 0;
2025 }
2026 const Desc_Structure_FT& desc = maillage.desc_sommets();
2028 desc.echange_espace_virtuel(varVolume);
2029 }
2030
2031 // ******************************************************
2032 // Remplacement des sommets dans le tableau des facettes,
2033 // On rend invalides les facettes qui disparaissent (deux sommets confondus)
2034 {
2035 const int nb_som = maillage.nb_sommets();
2036 // Creation d'une table de remplacement de sommets:
2037 ArrOfIntFT table_old_new(nb_som);
2038 table_old_new = -1;
2039 int i;
2040 const int nb_rempl = remplacement_ilocal.dimension(0);
2041 for (i = 0; i < nb_rempl; i++)
2042 {
2043 const int som_old = remplacement_ilocal(i,0);
2044 const int som_new = remplacement_ilocal(i,1);
2045 table_old_new[som_old] = som_new;
2046 }
2047 IntTab& facettes = maillage.facettes_;
2048 const int nb_facettes = facettes.dimension(0);
2049 const int nb_som_par_facette = facettes.dimension(1);
2050 for (i = 0; i < nb_facettes; i++)
2051 {
2052 int j;
2053 int flag = 0;
2054 for (j = 0; j < nb_som_par_facette; j++)
2055 {
2056 const int i_sommet = facettes(i,j);
2057 const int new_sommet = table_old_new[i_sommet];
2058 if (new_sommet >= 0)
2059 {
2060 facettes(i,j) = new_sommet;
2061 flag = 1;
2062 }
2063 }
2064 // En dimension2, une facette est invalide si les deux sommets
2065 // sont identiques. En dimension 3, si deux sommets sont confondus,
2066 // il faut invalider la facette (sommet0 == sommet1)
2067 if (flag && nb_som_par_facette == 3)
2068 {
2069 // Facette modifiee, on teste si elle disparait
2070 const int s0 = facettes(i,0);
2071 const int s1 = facettes(i,1);
2072 const int s2 = facettes(i,2);
2073 if (s0 == s2 || s1 == s2)
2074 {
2075 facettes(i,1) = s0;
2076 facettes(i,2) = s0;
2077 }
2078 }
2079 }
2080
2081 }
2082 nb_sommets_supprimes = remplacement_ilocal.dimension(0);
2083 nb_sommets_supprimes = Process::check_int_overflow(Process::mp_sum(nb_sommets_supprimes));
2084 nb_sommets_supprimes_tot += nb_sommets_supprimes;
2085 }
2086 while (nb_sommets_supprimes > 0);
2087
2089 // corriger_proprietaires_facettes() cree eventuellement des sommets virtuels.
2090 // => Mise a jour de varVolume
2091 varVolume.resize_array(maillage.nb_sommets());
2092 maillage.desc_sommets().echange_espace_virtuel(varVolume);
2093
2095 statistics().end_count("Supprimer_petites_aretes");
2096 return nb_sommets_supprimes_tot;
2097}
2098
2099/*! @brief Cette fonction marque a supprimer les facettes en double.
2100 *
2101 * Lorsque 2 facettes se trouvent avoir 3 de leur sommets en commun,
2102 * il faut supprimer les 2 facettes?
2103 * Marquer a supprimer = condenser les 3 sommets en un seul (le sommet 0)
2104 *
2105 * Precondition:
2106 * Le maillage doit verifier la propriete "proprietaire facette = premier sommet"
2107 *
2108 * @param (maillage) maillage a remailler
2109 * @return (int) Le nombre de facettes supprimees
2110 */
2112{
2113 if (Comm_Group::check_enabled()) maillage.check_mesh();
2114
2115 const int nb_sommets = maillage.nb_sommets();
2116 const int nb_facettes = maillage.nb_facettes();
2117 IntTab& facettes = maillage.facettes_;
2118 const int nb_som_par_facette = facettes.dimension(1);
2119
2120 // Marqueurs des facettes supprimees:
2121 ArrOfIntFT facettes_a_supprimer(nb_facettes);
2122 facettes_a_supprimer = 0;
2123
2124 ArrOfIntFT fa7VoisinesSom_index;
2125 IntTabFT fa7VoisinesSom_data;
2126
2127 fa7VoisinesSom_index.resize_array(nb_sommets);
2128 fa7VoisinesSom_data.resize(3*nb_facettes,2); //estimation nb connectivites = 3 x nb de facettes
2129
2130 //on commence par recalculer les connectivites sommet -> facettes voisines
2131 calculer_connectivites_sommetFacettes(maillage, fa7VoisinesSom_index,fa7VoisinesSom_data);
2132
2133 //puis on balaye les sommets
2134 int som, index, index2, fa7,fa72, compteur, isom,isom2, trouve;
2135 for (som=0 ; som<nb_sommets ; som++)
2136 {
2137 index = fa7VoisinesSom_index[som];
2138 while (index>=0)
2139 {
2140 //recupere la facette voisine
2141 fa7 = fa7VoisinesSom_data(index,1);
2142 if (facettes(fa7,0)!=facettes(fa7,1))
2143 {
2144 //facette valide
2145 index2 = fa7VoisinesSom_data(index,0);
2146 while (index2>=0)
2147 {
2148 //recupere la facette voisine
2149 fa72 = fa7VoisinesSom_data(index2,1);
2150 if (facettes(fa72,0)!=facettes(fa72,1))
2151 {
2152 //facette valide
2153 //compte le nombre de sommet communs entre les facettes
2154 compteur = 0;
2155 trouve = 0;
2156 for (isom=0 ; isom<nb_som_par_facette && trouve==0 ; isom++)
2157 {
2158 for (isom2=0 ; isom2<nb_som_par_facette && trouve==0 ; isom2++)
2159 {
2160 if (facettes(fa7,isom) == facettes(fa72,isom2))
2161 {
2162 trouve = 1;
2163 }
2164 }
2165 if (trouve==1)
2166 {
2167 //on a bien trouve le sommet facettes(fa7,isom) dans fa72
2168 compteur++;
2169 trouve = 0; //pour pouvoir continuer le test pour le sommet suivant de fa7
2170 }
2171 else
2172 {
2173 //on n'a pas trouve le sommet facettes(fa7,isom) dans fa72
2174 //on peut donc arreter le test ici
2175 trouve = -1;
2176 }
2177 }
2178 if (compteur==nb_som_par_facette)
2179 {
2180#ifndef NDEBUG
2181 if (impr_>5000)
2182 {
2183 Process::Journal()<<"Facettes superposees : doublon a supprimer"<<finl;
2184 Process::Journal()<<" ";
2185 maillage.printFa7(fa7,0,Process::Journal());
2186 Process::Journal()<<" ";
2187 maillage.printFa7(fa72,0,Process::Journal());
2188 }
2189#endif
2190 index2 = -1;
2191 //marque les facettes a supprimer, ie ses 3 sommets sont identiques
2192 facettes_a_supprimer[fa7] = 1;
2193 facettes_a_supprimer[fa72] = 1;
2194 }
2195 else
2196 {
2197 //index suivant
2198 index2 = fa7VoisinesSom_data(index2,0);
2199 }
2200 }
2201 else
2202 {
2203 //index suivant
2204 index2 = fa7VoisinesSom_data(index2,0);
2205 }
2206 }
2207 }
2208 //index suivant
2209 index = fa7VoisinesSom_data(index,0);
2210 }
2211 }
2212 // Mise a jour des espaces virtuels pour supprimer les facettes sur tous les procs
2213 {
2214 const Desc_Structure_FT& desc_facettes = maillage.desc_facettes();
2215 desc_facettes.echange_espace_virtuel(facettes_a_supprimer);
2216 }
2217 // On rend les facettes a supprimer invalides (trois sommets identiques)
2218 {
2219 int i, j;
2220 for (i = 0; i < nb_facettes; i++)
2221 {
2222 if (facettes_a_supprimer[i])
2223 {
2224 const int sommet0 = facettes(i, 0);
2225 for (j = 1; j < nb_som_par_facette; j++)
2226 facettes(i, j) = sommet0;
2227 }
2228 }
2229 }
2231
2232 return 1;
2233}
2234
2235
2236/*! @brief Cette fonction calcule le carre de la longueur ideale d'une arete Dans un premier, cette longueur ideale est la racine cubique (en 3D) de la moyenne
2237 *
2238 * des volumes des elements euleriens contenant les sommets
2239 *
2240 * @param (som0) indice du 1er sommet de l'arete
2241 * @param (som1) indice du 2e sommet de l'arete
2242 * @return (double) carre de la longueur idealede l'arete
2243 */
2245 int som0,
2246 double x, double y, double z) const
2247{
2248 double lgrId2 = 0.;
2249 if (facteur_longueur_ideale_ > 0.)
2250 {
2251 // La longueur ideale est un multiple de la taille locale des
2252 // elements euleriens.
2253 const int elem0 = maillage.sommet_elem_[som0];
2254
2255 const Elem_geom_base& elem_geom = refdomaine_VF_->domaine().type_elem().valeur();
2256
2257 if (sub_type(Triangle, elem_geom))
2258 {
2259 double vol = refdomaine_VF_->volumes(elem0);
2260 lgrId2 = 2. * vol;
2261
2262 }
2263 else if (sub_type(Tetraedre, elem_geom))
2264 {
2265
2266 double vol = refdomaine_VF_->volumes(elem0);
2267 lgrId2 = 2. * pow(vol,2./dimension);
2268
2269 }
2270 else if (sub_type(Rectangle, elem_geom)
2271 || sub_type(Hexaedre, elem_geom))
2272 {
2273
2274 const DoubleTab& sommets = maillage.sommets();
2275 const DoubleTab& xv = refdomaine_VF_->xv();
2276 const IntTab& elem_faces = refdomaine_VF_->elem_faces();
2277 int k;
2278 FTd_vecteur3 v = {0., 0., 0.};
2279 FTd_vecteur3 xyz = {x, y, z};
2280 FTd_vecteur3 delta_xv = {0., 0., 0.};
2281 const int dim = Objet_U::dimension;
2282 double norme2 = 0.;
2283 for (k = 0; k < dim; k++)
2284 {
2285 v[k] = xyz[k] - sommets(som0, k);
2286 norme2 += v[k] * v[k];
2287 const int face0 = elem_faces(elem0,k);
2288 const int face1 = elem_faces(elem0,k+dim);
2289 delta_xv[k] = xv(face1,k) - xv(face0,k);
2290 }
2291 if (equilateral_)
2292 {
2293 // On calcul la diagonale de l'element eulerien. Puis longueur au carre.
2294 norme2 = 0.;
2295 for (k = 0; k < dim; k++)
2296 norme2 += delta_xv[k] * delta_xv[k];
2297 }
2298 else
2299 {
2300 // On calcul la projection de la diagonale de l'element eulerien
2301 // sur l'arete de la facette. Puis longueur au carre.
2302 if (norme2 == 0)
2303 {
2304 v[0] = 1.;
2305 v[1] = 1.;
2306 v[2] = dim==3 ? 1. : 0.;
2307 norme2 = dim;
2308 }
2309 double f = 1. / sqrt(norme2);
2310 norme2 = 0.;
2311 for (k = 0; k < dim; k++)
2312 {
2313 v[k] *= f * delta_xv[k];
2314 norme2 += v[k] * v[k];
2315 }
2316 }
2317 lgrId2 = norme2;
2318
2319 }
2320 else
2321 {
2322 Cerr << "Remaillage_FT::calculer_longueurIdeale2_arete non implemente pour les elements "
2323 << elem_geom.que_suis_je() << finl;
2324 assert(0==1);
2325 Process::exit();
2326 }
2327
2329 }
2330 else if (valeur_longueur_fixe_ > 0.)
2331 {
2332 // La longueur ideale est imposee en valeur absolue dans le jeu de donnees
2333 // (valeur en metres)
2335 }
2336 else
2337 {
2338 Cerr << "Erreur Remaillage_FT::calculer_longueurIdeale2_arete" << finl;
2339 Process::exit();
2340 }
2341 return lgrId2;
2342}
2343
2344/*! @brief Cette fonction calcule la variation de volume liee a la suppression de sommets
2345 *
2346 * @param (maillage) maillage a barycentrer
2347 * @param (tab_somSupp) tableau des sommets a supprimer tab[som] < 0 : sommet a conserver tab[som] >=0 : sommet a remplacer par tab[som]
2348 * @param (varVolume) la variation de volume
2349 * @return (double) volume total supprime
2350 */
2351double Remaillage_FT::calculer_volume_sommets_supprimes(const Maillage_FT_Disc& maillage, const ArrOfInt& tab_somSupp,
2352 ArrOfDouble& varVolume) const
2353{
2354 double res = 0.;
2355
2356 const int nb_facettes = maillage.nb_facettes();
2357 const DoubleTab& sommets = maillage.sommets();
2358 const IntTab& facettes = maillage.facettes();
2359 const int nb_som_par_facette = facettes.dimension(1);
2360
2361 int isom,som, som_rempl,fa7, k;
2362 double volume;
2363 FTd_vecteur3 som0,som1,som2,som3;
2364
2365 //const int nb_sommets = maillage.nb_sommets();
2366 //for (som=0 ; som<nb_sommets ; som++) {
2367 // varVolume[som] = 0.;
2368 //}
2369
2370 //on balaye les facettes
2371 for (fa7=0 ; fa7<nb_facettes ; fa7++)
2372 {
2373 //on balaye ses sommets
2374 for (isom=0 ; isom<nb_som_par_facette ; isom++)
2375 {
2376 som = facettes(fa7,isom);
2377 som_rempl = tab_somSupp[som];
2378 if (som_rempl>=0)
2379 {
2380 //sommet som a remplacer par som_rempl
2381 //la variation de volume est alors egale au volume genere par les facettes voisines
2382 //de som (et le 4e sommet des tetraedres = som_rempl)
2383 //on recupere les coordonnees des sommets de la facette et du sommet de remplacement
2384 for (k=0 ; k<dimension ; k++)
2385 {
2386 som0[k] = sommets(facettes(fa7,0),k);
2387 som1[k] = sommets(facettes(fa7,1),k);
2388 som2[k] = sommets(facettes(fa7,2),k);
2389 som3[k] = sommets(som_rempl,k);
2390 }
2391 //on calcule le volume du tetraedre som0/som1/som2/som_rempl
2392 volume = FTd_calculer_volume_tetraedre(som0,som1,som2,som3);
2393 res += volume;
2394 varVolume[som] = volume;
2395 }
2396 }
2397 }
2398
2399#ifndef NDEBUG
2400 if (impr_>9000)
2401 {
2402 const int nb_sommets = maillage.nb_sommets();
2403 for (som=0 ; som<nb_sommets ; som++)
2404 {
2405 if (tab_somSupp[som]!=-1)
2406 Process::Journal()<<"Som_apresSupp "<<tab_somSupp[som]<<" "<<som<<" varVolume= "<<varVolume[som]<<finl;
2407 }
2408 }
2409#endif
2410#ifndef NDEBUG
2411 if (impr_>5000)
2412 {
2413 Process::Journal()<<"calculer_volume_sommets_supprimes : varVolume_global= "<<res<<finl;
2414 }
2415#endif
2416 return res;
2417}
2418
2419/*! @brief Cette fonction effectue des permutations d'aretes afin d'ameliorer la qualite du maillage
2420 *
2421 * @param (maillage) maillage a remailler
2422 * @return (int) 1 si le remaillage s'est deroule correctement, 0 sinon
2423 */
2425{
2426 int res = 1;
2427 if (dimension!=3)
2428 {
2429 //ceci n'est valable qu'en 3D
2430 return res;
2431 }
2432
2433
2435 return res;
2436}
2437
2438//=============================================================================================
2439// FONCTIONS DE DIVISION DES GRANDES ARETES
2440
2441/*! @brief Cette fonction divise les grandes aretes en 2
2442 *
2443 * @param (maillage) maillage a remailler
2444 * @return (int) 1 si le remaillage s'est deroule correctement, 0 sinon
2445 */
2447{
2448 statistics().create_custom_counter("Diviser_grandes_aretes",3,"TrioCFD");
2449 statistics().begin_count("Diviser_grandes_aretes",statistics().get_last_opened_counter_level()+1);
2450
2451 static int compteur = 0;
2452 static int test_val = -1;
2453
2454 Process::Journal()<<"Remaillage_FT::diviser_grandes_aretes "<<temps_<<" nb_som="<<maillage.nb_sommets()<<finl;
2455 Process::Journal()<<" Compteur = " << compteur << finl;
2456 compteur++;
2457 if (compteur == test_val)
2458 {
2459 Process::Journal() << " STOP." << finl;
2460 }
2461 // int res = 1;
2462
2463 maillage.nettoyer_elements_virtuels();
2464
2465 //tableaux de stockage
2466 IntTabFT tab_aretesMarquees;
2467 ArrOfIntFT tab_somD;
2468 DoubleTabFT tab_deplacement_somD;
2469
2470 //on commence par marquer les grandes aretes
2471 marquer_aretes(maillage,
2472 tab_aretesMarquees,
2473 tab_somD,
2474 tab_deplacement_somD,
2475 1 /* marquage des aretes trop grandes */);
2476 // resultat = tab_aretesMarquees : [ fa7 iarete pe som ]
2477
2478 const int nb_aretes_divis = tab_aretesMarquees.dimension(0);
2479
2480
2481 int nb_facettes = maillage.nb_facettes();
2482 const int nb_facettes0 = nb_facettes;
2483 IntTab& facettes = maillage.facettes_;
2484 const int nb_som_par_facette = facettes.dimension(1);
2485
2486 const ArrOfInt& sommet_num_owner = maillage.sommet_num_owner_;
2487 int fa7,iarete, isom,som,isom_s,som_s,isom_ss,som_ss, pe_somD,numOwner_somD,somD,somD_s,somD_ss;
2488
2489 const int dimension3 = (dimension==3);
2490 const int nb_aretes_par_facette = (dimension3)?3:1;
2491 //tableau stockant le sommet servant a decouper l'arete (ou -1 si arete non divisee)
2492 IntTabFT tab_fa7Divis(nb_facettes,nb_aretes_par_facette);
2493 for (fa7=0 ; fa7<nb_facettes ; fa7++)
2494 {
2495 for (isom=0 ; isom<nb_aretes_par_facette ; isom++)
2496 {
2497 tab_fa7Divis(fa7,isom) = -1;
2498 }
2499 }
2500
2501 //on va balayer les aretes a memoriser l'ensemble des aretes a scinder
2502 for (iarete=0 ; iarete<nb_aretes_divis ; iarete++)
2503 {
2504 fa7 = tab_aretesMarquees(iarete,0);
2505 isom = tab_aretesMarquees(iarete,1);
2506 isom_s = (isom+1)%nb_som_par_facette;
2507 //sommet qui va rester dans fa7
2508 som = facettes(fa7,isom);
2509 //sommet qui va aller dans une nouvelle facette
2510 som_s = facettes(fa7,isom_s);
2511 //sommet a inserer dans l'arete
2512 pe_somD = tab_aretesMarquees(iarete,2);
2513 numOwner_somD = tab_aretesMarquees(iarete,3);
2514
2515 if (pe_somD!=me())
2516 {
2517 //je ne connais pas l'indice du sommet a inserer dans me()
2518 maillage.convertir_numero_distant_local(maillage.desc_sommets(),sommet_num_owner,numOwner_somD,pe_somD,somD);
2519 assert(somD >= 0);
2520 }
2521 else
2522 {
2523 //je suis le proprietaire de somD : je connais donc le bon indice du sommet a inserer
2524 somD = numOwner_somD;
2525 }
2526
2527 tab_fa7Divis(fa7,isom) = somD;
2528 }
2529
2530 //on va ensuite balayer les facettes et les scinder
2531 //la configuration depend du nb d'aretes a scinder par facette
2532 int nb_areteScinder, isom0=-1,isom1=-1;
2533 for (fa7=0 ; fa7<nb_facettes0 ; fa7++)
2534 {
2535 //on compte le nombre d'aretes a scinder
2536 nb_areteScinder = 0;
2537 for (isom=0 ; isom<nb_aretes_par_facette ; isom++)
2538 {
2539 if (tab_fa7Divis(fa7,isom)>=0)
2540 {
2541 if (nb_areteScinder==0)
2542 {
2543 isom0 = isom;
2544 }
2545 else
2546 {
2547 isom1 = isom;
2548 }
2549 nb_areteScinder++;
2550 }
2551 }
2552 if (nb_areteScinder==1)
2553 {
2554 //s'il n'y a qu'une arete a scinder
2555 somD = tab_fa7Divis(fa7,isom0);
2556 //on modifie la facettes d'origine
2557 isom_s = (isom0+1)%nb_som_par_facette;
2558 som_s = facettes(fa7,isom_s);
2559 facettes(fa7,isom_s) = somD;
2560 //on cree une nouvelle facette
2561 if (nb_facettes>=facettes.dimension(0))
2562 {
2563 //Redimensionnement
2564 facettes.resize(nb_facettes+10,facettes.dimension(1));
2565 }
2566 isom_ss = (isom_s+1)%nb_som_par_facette;
2567 som_ss = facettes(fa7,isom_ss);
2568 if (dimension==2)
2569 {
2570 facettes(nb_facettes,isom0) = somD;
2571 facettes(nb_facettes,isom_s) = som_s;
2572 }
2573 else
2574 {
2575 facettes(nb_facettes,0) = som_ss;
2576 facettes(nb_facettes,1) = somD; //sommet insere
2577 facettes(nb_facettes,2) = som_s;
2578 }
2579 nb_facettes++;
2580 }
2581 else if (nb_areteScinder==2)
2582 {
2583 //si 2 aretes sont a scinder
2584 //on cree deux nouvelles facettes
2585 if (nb_facettes+2>=facettes.dimension(0))
2586 {
2587 //Redimensionnement
2588 facettes.resize(nb_facettes+12,facettes.dimension(1));
2589 }
2590 //on positionne isom et isom_s tq elles soient les aretes a scinder
2591 if (isom1==(isom0+1)%nb_som_par_facette)
2592 {
2593 isom = isom0;
2594 isom_s = isom1;
2595 }
2596 else
2597 {
2598 isom = isom1;
2599 isom_s = isom0;
2600 }
2601 isom_ss = ((isom_s+1)%nb_som_par_facette);
2602 som = facettes(fa7,isom);
2603 som_s = facettes(fa7,isom_s);
2604 som_ss = facettes(fa7,isom_ss);
2605 somD = tab_fa7Divis(fa7,isom);
2606 somD_s = tab_fa7Divis(fa7,isom_s);
2607 somD_ss = tab_fa7Divis(fa7,isom_ss);
2608 //on modifie la facette existante
2609 facettes(fa7,0) = som;
2610 facettes(fa7,1) = somD;
2611 facettes(fa7,2) = som_ss;
2612 //premiere nouvelle facette
2613 facettes(nb_facettes,0) = somD;
2614 facettes(nb_facettes,1) = som_s;
2615 facettes(nb_facettes,2) = somD_s;
2616 nb_facettes++;
2617 //seconde nouvelle facette
2618 facettes(nb_facettes,0) = somD;
2619 facettes(nb_facettes,1) = somD_s;
2620 facettes(nb_facettes,2) = som_ss;
2621 nb_facettes++;
2622 }
2623 else if (nb_areteScinder==3)
2624 {
2625 //si toutes les aretes sont a scinder
2626 //on cree trois nouvelles facettes
2627 if (nb_facettes+3>=facettes.dimension(0))
2628 {
2629 //Redimensionnement
2630 facettes.resize(nb_facettes+13,facettes.dimension(1));
2631 }
2632 isom = 0;
2633 isom_s = 1;
2634 isom_ss = 2;
2635 som = facettes(fa7,isom);
2636 som_s = facettes(fa7,isom_s);
2637 som_ss = facettes(fa7,isom_ss);
2638 somD = tab_fa7Divis(fa7,isom);
2639 somD_s = tab_fa7Divis(fa7,isom_s);
2640 somD_ss = tab_fa7Divis(fa7,isom_ss);
2641 //on modifie la facette existante
2642 facettes(fa7,0) = som;
2643 facettes(fa7,1) = somD;
2644 facettes(fa7,2) = somD_ss;
2645 //premiere nouvelle facette
2646 facettes(nb_facettes,0) = somD;
2647 facettes(nb_facettes,1) = som_s;
2648 facettes(nb_facettes,2) = somD_s;
2649 nb_facettes++;
2650 //seconde nouvelle facette
2651 facettes(nb_facettes,0) = somD_s;
2652 facettes(nb_facettes,1) = som_ss;
2653 facettes(nb_facettes,2) = somD_ss;
2654 nb_facettes++;
2655 //troisieme nouvelle facette
2656 facettes(nb_facettes,0) = somD;
2657 facettes(nb_facettes,1) = somD_s;
2658 facettes(nb_facettes,2) = somD_ss;
2659 nb_facettes++;
2660 }
2661 }
2662 //Redimensionnement
2663 facettes.resize(nb_facettes,facettes.dimension(1));
2664 maillage.desc_facettes_.calcul_schema_comm(nb_facettes);
2666
2667 ArrOfIntFT liste_sommets_sortis;
2668 ArrOfIntFT numero_face_sortie;
2669 maillage.deplacer_sommets(tab_somD,tab_deplacement_somD,liste_sommets_sortis,numero_face_sortie);
2671
2672 Process::Journal()<<"FIN Remaillage_FT::diviser_grandes_aretes "<<temps_<<" nb_som="<<maillage.nb_sommets()
2673 <<" nb_aretes_divisees="<< nb_aretes_divis<<finl;
2674 int nb_aretes_divis_tot = Process::check_int_overflow(Process::mp_sum(nb_aretes_divis));
2675
2676 Process::Journal()<<"FIN Remaillage_FT::diviser_grandes_aretes " <<" nb_aretes_divisees_tot="<< nb_aretes_divis_tot<<finl;
2677
2679 statistics().end_count("Diviser_grandes_aretes");
2680 // return res;
2681 return nb_aretes_divis_tot;
2682}
2683
2684//cette fonction insere une ligne de "requete arete" dans le tableau
2685//renvoie l'indice ou cela a ete mis dans le tableau
2686int Remaillage_FT::inserer_tab_aretes(int& nb_tab_aretes,IntTab& tab_aretes, DoubleTab& tab_criteres,
2687 int pe0, int numOwner0, int pe1, int numOwner1, int sommet_face_bord1,
2688 int peRequete, int fa7_peR, int iarete_fa7_peR) const
2689{
2690 int res = nb_tab_aretes;
2691 //Redimensionnement eventuel
2692 if (nb_tab_aretes>=tab_aretes.dimension(0))
2693 {
2694 tab_aretes.resize(nb_tab_aretes+10,tab_aretes.dimension(1));
2695 tab_criteres.resize(nb_tab_aretes+10,tab_criteres.dimension(1));
2696 }
2697 //insertion des donnees a la fin
2698 tab_aretes(nb_tab_aretes,0) = pe0;
2699 tab_aretes(nb_tab_aretes,1) = numOwner0;
2700 tab_aretes(nb_tab_aretes,2) = pe1;
2701 tab_aretes(nb_tab_aretes,3) = numOwner1;
2702 tab_aretes(nb_tab_aretes,4) = sommet_face_bord1;
2703 tab_aretes(nb_tab_aretes,5) = peRequete;
2704 tab_aretes(nb_tab_aretes,6) = fa7_peR;
2705 tab_aretes(nb_tab_aretes,7) = iarete_fa7_peR;
2706
2707 nb_tab_aretes++;
2708
2709 return res;
2710}
2711
2712//Partant de l'indice index (dans tab_index), cette fonction renvoie l'index suivant correspondant a l'arete (pe0/som0,pe1/som1) passee
2713//Premiere utilisation : passer index = -1
2714//Renvoie tmp=-1 s'il n'y a pas d'arete correspondante
2715int Remaillage_FT::chercher_arete_tab(int tmp, const ArrOfInt& tab_index, const IntTab& tab_aretes,
2716 int pe0, int numOwner0, int pe1, int numOwner1) const
2717{
2718 int pe0_=-1,numOwner0_=-1, pe1_=-1,numOwner1_=-1;
2719 int iarete;
2720 const int nb_tab_aretes = tab_index.size_array();
2721 tmp++;
2722 if (tmp>=nb_tab_aretes)
2723 {
2724 return -1;
2725 }
2726 int trouve = -1;
2727 while (tmp<nb_tab_aretes && trouve==-1)
2728 {
2729 iarete = tab_index[tmp];
2730 pe0_ = tab_aretes(iarete,0);
2731 numOwner0_ = tab_aretes(iarete,1);
2732 pe1_ = tab_aretes(iarete,2);
2733 numOwner1_ = tab_aretes(iarete,3);
2734 if ( pe0_<pe0 || (pe0_==pe0 && numOwner0_<numOwner0)
2735 || (pe0_==pe0 && numOwner0_==numOwner0 && pe1_<pe1)
2736 || (pe0_==pe0 && numOwner0_==numOwner0 && pe1_==pe1 && numOwner1_<numOwner1) )
2737 {
2738 tmp++;
2739 }
2740 else
2741 {
2742 trouve = 0;
2743 }
2744 }
2745 if (! (pe0_==pe0 && numOwner0_==numOwner0 && pe1_==pe1 && numOwner1_==numOwner1) )
2746 {
2747 tmp = -1;
2748 }
2749
2750 return tmp;
2751}
2752
2753//Methode qui permet de collecter la liste des aretes marquees.
2754// ATTENTION : creation de sommets supplementaires au milieu des aretes trop longues
2755//
2756//Si drap > 0 : les facettes marquees sont celles qui sont trop grandes,
2757// ie elles ne verifient pas le critere suivant:
2758//
2759// (L_arete)^2
2760// ------------------------- < 1.
2761// (L_ideale^2 x (1 + C)^2
2762//
2763//Si drap < 0 : les facettes marquees sont celles qui sont trop petites,
2764// ie elles ne verifient pas le critere suivant:
2765//
2766// (L_arete)^2
2767// ------------------------- > 1.
2768// (L_ideale^2 x (1 - C)^2
2769//
2770//La methode remplit le tableau tab_aretesMarquees, dont les colonnes sont
2771// [ fa7 iarete pe som ]
2772// ou
2773// -fa7 : indice de la facette contenant l'arete marquee
2774// -iarete : indice localc de l'arete marquee
2775// -peD/somD : numerotation globale du sommet a utiliser lors d'une division d'arete
2776//
2777//Rq : les deplacement des sommets peD/somD est a realiser en-dehors de cette fonction (liste des sommets dans tab_somD)
2778//en utilisant le tableau tab_deplacement_somD, et apres avoir realise la subdivision des aretes
2779int Remaillage_FT::marquer_aretes(Maillage_FT_Disc& maillage, IntTab& tab_aretesMarquees,
2780 ArrOfInt& tab_somD, DoubleTab& tab_deplacement_somD, int drap) const
2781{
2782 int res = 1;
2783 int nb_aretesMarquees = 0;
2784 tab_aretesMarquees.resize(10,4); //tableau des aretes marquees [fa7 iarete pe som]
2785 //ou pe som est le sommet a utiliser lors d'une division d'arete
2786
2787 int nb_somD = 0;
2788 tab_somD.resize_array(10);
2789 tab_deplacement_somD.resize(10,dimension);
2790 static IntTabFT tab_arete_somD(10,4);
2791 static IntTabFT tab_aretes(10,10); //tableau [0=pe0 1=ind0 2=pe1 3=ind1 4=face_bord1 5=peReq 6=fa7 7=iarete 8=critere 9=som]
2792 //ou (pe0) som est le sommet a utiliser lors d'une division d'arete
2793 int nb_tab_aretes = 0;
2794 static DoubleTabFT tab_criteres(10,6); //tableau [pox posy posz L^2 LI0^2 LI1^2]
2795
2796 const int dimension3 = (dimension==3);
2797
2798 const int nb_sommets = maillage.nb_sommets();
2799 const int nb_facettes = maillage.nb_facettes();
2800 const IntTab& facettes = maillage.facettes();
2801 DoubleTab& sommets = maillage.sommets_;
2802 ArrOfInt& sommet_elem = maillage.sommet_elem_;
2803 ArrOfInt& sommet_face_bord = maillage.sommet_face_bord_;
2804 ArrOfInt& sommet_PE_owner = maillage.sommet_PE_owner_;
2805 ArrOfInt& sommet_num_owner = maillage.sommet_num_owner_;
2806 ArrOfInt& drapeaux_sommets = maillage.drapeaux_sommets_;
2807 const int nb_som_par_facette = facettes.dimension(1);
2808 const int nb_aretes_par_facette = (dimension3)?3:1;
2809 const int _MOI_ = me();
2810
2811 //on commence par recuperer le schema de communication
2812 //on prend le schema inverse du descripteur de sommets car
2813 const Schema_Comm& comm = maillage.desc_sommets_.schema_comm_inverse();
2814 //initialise la communication
2815 comm.begin_comm();
2816
2817 int fa7, isom,som,pe,numOwner, isom_s,som_s,pe_s,numOwner_s, indice, tmp;
2818 double x,y,z=0.;
2819 //on balaye les facettes reelles
2820 for (fa7=0 ; fa7<nb_facettes ; fa7++)
2821 {
2822 //on balaye les aretes de la facette
2823 if (!maillage.facette_virtuelle(fa7) && facettes(fa7,0)!=facettes(fa7,1))
2824 {
2825 //facette non virtuelle et non supprimee
2826 //on balaye les aretes de la facette
2827 for (isom=0 ; isom<nb_aretes_par_facette ; isom++)
2828 {
2829 //on recupere les sommets de l'arete
2830 isom_s = (isom+1)%nb_som_par_facette;
2831 som = facettes(fa7,isom);
2832 som_s = facettes(fa7,isom_s);
2833 pe = sommet_PE_owner[som];
2834 numOwner = sommet_num_owner[som];
2835 pe_s = sommet_PE_owner[som_s];
2836 numOwner_s = sommet_num_owner[som_s];
2837 tmp = FTd_compare_sommets_global(pe,numOwner,pe_s,numOwner_s);
2838 assert(tmp!=0);
2839 if (tmp>0)
2840 {
2841 //on a en fait som>som_s : on permute les sommets
2842 tmp = som;
2843 som = som_s;
2844 som_s = tmp;
2845 pe = sommet_PE_owner[som];
2846 numOwner = sommet_num_owner[som];
2847 pe_s = sommet_PE_owner[som_s];
2848 numOwner_s = sommet_num_owner[som_s];
2849 }
2850 if (pe!=_MOI_)
2851 {
2852 //on envoie les informations au processeur possedant som
2853 //pour qu'il puisse calculer sa partie du critere
2854 Sortie& buffer = comm.send_buffer(pe);
2855 //-les numerotations globales des sommets
2856 buffer << pe << numOwner << pe_s << numOwner_s << sommet_face_bord[som_s];
2857 //-les indices de la fa7 et de 'larete
2858 buffer << fa7 << isom;
2859 //-la position du sommet som_s
2860 buffer << sommets(som_s,0) << sommets(som_s,1);
2861 if (dimension3)
2862 buffer << sommets(som_s,2);
2863 }
2864 else
2865 {
2866 //je suis pe le proprietaire de som
2867 //on ajoute la ligne de donnees aux tableaux
2868 //insere le tableau en tant que requete, avec moi comme requerant
2869 tmp = inserer_tab_aretes(nb_tab_aretes,tab_aretes,tab_criteres,pe,numOwner,pe_s,numOwner_s, sommet_face_bord[som_s], _MOI_,fa7,isom);
2870 tab_criteres(tmp,0) = sommets(som_s,0);
2871 tab_criteres(tmp,1) = sommets(som_s,1);
2872 tab_criteres(tmp,2) = (dimension3) ? sommets(som_s,2) : 0;
2873 tab_criteres(tmp,3) = tab_criteres(tmp,4) = tab_criteres(tmp,5) = -1.;
2874 }
2875 if (pe_s!=pe)
2876 {
2877 //test pour eviter de refaire le bloc ci-dessus
2878 if (pe_s!=_MOI_)
2879 {
2880 //on envoie aussi les informations au processeur possedant som_s
2881 //pour qu'il puisse calculer sa partie du critere
2882 Sortie& buffer = comm.send_buffer(pe_s);
2883 //-les numerotations globales des sommets
2884 buffer << pe << numOwner << pe_s << numOwner_s << sommet_face_bord[som_s];
2885 //-les indices de la fa7 et de l'arete
2886 buffer << fa7 << isom;
2887 //-la position du sommet som
2888 buffer << sommets(som,0) << sommets(som,1);
2889 if (dimension3)
2890 buffer << sommets(som,2);
2891 }
2892 else
2893 {
2894 //je suis pe_s le proprietaire de som_s (et la ligne n'a pas deja ete ajoutee ci-dessu)
2895 //on ajoute la ligne de donnees aux tableaux
2896 //insere le tableau en tant que requete, avec moi comme requerant
2897 tmp =inserer_tab_aretes(nb_tab_aretes,tab_aretes,tab_criteres,pe,numOwner,pe_s,numOwner_s, sommet_face_bord[som_s], -1,-1,-1);
2898 tab_criteres(tmp,0) = sommets(som,0);
2899 tab_criteres(tmp,1) = sommets(som,1);
2900 tab_criteres(tmp,2) = (dimension3) ? sommets(som,2) : 0;
2901 tab_criteres(tmp,3) = tab_criteres(tmp,4) = tab_criteres(tmp,5) = -1.;
2902 }
2903 }
2904 } //fin du balayage des aretes de la facette
2905 } //fin facette non virtuelle
2906 } //fin du balayage des facettes
2907
2908 int peV, pe0,numOwner0, pe1,numOwner1, iarete, face_bord1;
2909 //on lance l'echange des messages
2911
2912 //on recupere les messages
2913 //il s'agit de message que l'on m'a envoye si je suis
2914 // -le proprietaire du sommet 0 de l'arete ou
2915 // -le proprietaire du sommet 1 de l'arete
2916 //le message est constitue de pe0 / numOwner0 / pe1 / numOwner1 / fa7 / isom / posx / posy / posz
2917 //ou
2918 // -fa7 est l'indice dans le pe envoyant de la facette contenant l'arete
2919 // -isom est l'indeice de l'arete dans cette facette
2920 // -(posX, posy, posz) est la position
2921 // -du sommet 1 si je suis pe0
2922 // -du sommet 0 si je suis pe1
2923 {
2924 const ArrOfInt& pe_voisins = comm.get_recv_pe_list();
2925 const int nb_pe_voisins = pe_voisins.size_array();
2926 z = 0;
2927 for (int indice_pe = 0; indice_pe < nb_pe_voisins; indice_pe++)
2928 {
2929 peV = pe_voisins[indice_pe];
2930 Entree& buffer = comm.recv_buffer(peV);
2931 buffer >> pe0;
2932 while (!buffer.eof())
2933 {
2934 buffer >> numOwner0 >> pe1 >> numOwner1 >> face_bord1;
2935 buffer >> fa7 >> isom;
2936 buffer >> x >> y;
2937 if (dimension3)
2938 buffer >> z;
2939
2940 assert(pe0==_MOI_ || pe1==_MOI_);
2941 //on insere alors la ligne de requete
2942 tmp = inserer_tab_aretes(nb_tab_aretes,tab_aretes,tab_criteres,pe0,numOwner0,pe1,numOwner1,face_bord1, peV,fa7,isom);
2943 tab_criteres(tmp,0) = x;
2944 tab_criteres(tmp,1) = y;
2945 tab_criteres(tmp,2) = z;
2946 tab_criteres(tmp,3) = tab_criteres(tmp,4) = tab_criteres(tmp,5) = -1.;
2947 buffer >> pe0;
2948 }
2949 }
2950 }
2951 //finit cette communication
2952 comm.end_comm();
2953
2954 //Redimensionnements
2955 tab_aretes.resize(nb_tab_aretes,tab_aretes.dimension(1));
2956 tab_criteres.resize(nb_tab_aretes,tab_criteres.dimension(1));
2957
2958 //a la fin de cela, tout processeur proprietaire d'un sommet connait
2959 // -toutes les aretes partant de ce sommet
2960 // -la position de tous les seconds sommets de l'arete
2961
2962 //on va maintenant trier les tableaux tab_aretes et tab_criteres en fonction des numeros globaux des sommets de l'arete
2963 //pour cela on va utiliser un tableau d'indices annexe (pour ne pas modifier les tableaux eux-memes)
2964 ArrOfIntFT tab_index(nb_tab_aretes);
2965 for (indice=0 ; indice<nb_tab_aretes ; indice++)
2966 {
2967 tab_index[indice] = indice;
2968 }
2969 std::sort(tab_index.begin(), tab_index.end(), [&](int a, int b)
2970 {
2971 int cmp = FTd_compare_sommets_global(tab_aretes(a,0), tab_aretes(a,1), tab_aretes(b,0), tab_aretes(b,1));
2972 if (cmp==0)
2973 cmp = FTd_compare_sommets_global(tab_aretes(a,2), tab_aretes(a,3), tab_aretes(b,2), tab_aretes(b,3));
2974 return (cmp==-1);
2975 });
2976 double lgr2=-1.,lgr_ideale02=-1.,lgr_ideale12,d;
2977 int pe0p,numOwner0p,pe1p,numOwner1p;
2978 pe0p = numOwner0p = pe1p = numOwner1p = -1;
2979
2980 //on balaye alors les lignes des tableaux tab_*, pour calculer
2981 // -la longueur de l'arete si je suis le proprietaire du sommet 0
2982 // -la partie 0 de longueur ideale de l'arete si je suis le proprietaire du sommet 0
2983 // -la partie 1 de longueur ideale de l'arete si je suis le proprietaire du sommet 1
2984 //Une partie de longueur ideale est la longueur ideale calculee via l'element eulerien contenant le sommet
2985 for (indice=0 ; indice<nb_tab_aretes ; indice++)
2986 {
2987 iarete = tab_index[indice];
2988 pe0 = tab_aretes(iarete,0);
2989 numOwner0 = tab_aretes(iarete,1);
2990 pe1 = tab_aretes(iarete,2);
2991 numOwner1 = tab_aretes(iarete,3);
2992 if (FTd_compare_sommets_global(pe1,numOwner1,pe1p,numOwner1p)!=0 || FTd_compare_sommets_global(pe0,numOwner0,pe0p,numOwner0p)!=0)
2993 {
2994 //on est sur une arete differente de la precedente
2995 //on va donc recalculer les longueurs
2996 lgr2 = lgr_ideale02 = lgr_ideale12 = -1.;
2997 if (pe0==_MOI_)
2998 {
2999 //je suis le proprietaire du sommet 0
3000 //je dois donc calculer la longueur reelle de l'arete
3001 d = tab_criteres(iarete,0) - sommets(numOwner0,0);
3002 lgr2 = d*d;
3003 d = tab_criteres(iarete,1) - sommets(numOwner0,1);
3004 lgr2 += d*d;
3005 if (dimension3)
3006 {
3007 d = tab_criteres(iarete,2) - sommets(numOwner0,2);
3008 lgr2 += d*d;
3009 }
3010 //je dois aussi calculer ma longueur ideale
3011 lgr_ideale02 = calculer_longueurIdeale2_arete(maillage,numOwner0,tab_criteres(iarete,0),tab_criteres(iarete,1),tab_criteres(iarete,2));
3012 }
3013 if (pe1==_MOI_)
3014 {
3015 //je suis le proprietaire du sommet 1
3016 //je dois donc calculer ma longueur ideale
3017 lgr_ideale12 = calculer_longueurIdeale2_arete(maillage,numOwner1,tab_criteres(iarete,0),tab_criteres(iarete,1),tab_criteres(iarete,2));
3018 }
3019 }
3020 //et on stocke
3021 tab_criteres(iarete,3) = lgr2;
3022 tab_criteres(iarete,4) = lgr_ideale02;
3023 tab_criteres(iarete,5) = lgr_ideale12;
3024 pe0p = pe0;
3025 numOwner0p = numOwner0;
3026 pe1p = pe1;
3027 numOwner1p = numOwner1;
3028 }
3029
3030 //on construit un nouveau schema de communication :
3031 // -un processeur proprietaire du sommet 0 saura qu'il devra recevoir des infos venant du proprietaire du sommet 1
3032 // -un processeur proprietaire du sommet 1 saura qu'il devra envoyer des infos au proprietaire du sommet 0
3033 iarete = 0;
3034 static Schema_Comm comm2;
3035 {
3036 static ArrOfIntFT recv_pe_list; // liste des pe qui recoivent des infos
3037 static ArrOfIntFT send_pe_list; // liste des pe qui envoient des infos
3038 ArrOfIntFT drap_per(Process::nproc());
3039 ArrOfIntFT drap_pes(Process::nproc());
3040 drap_per = 0;
3041 drap_pes = 0;
3042 send_pe_list.resize_array(0);
3043 recv_pe_list.resize_array(0);
3044 //pour cela, on va alors balayer les aretes
3045 for (iarete=0 ; iarete<nb_tab_aretes ; iarete++)
3046 {
3047 pe0 = tab_aretes(iarete,0);
3048 pe1 = tab_aretes(iarete,2);
3049 if (pe0!=pe1)
3050 {
3051 if (pe0==_MOI_)
3052 {
3053 //je suis pe0 : je dois donc m'attendre a recevoir des infos de pe1
3054 if (drap_per[pe1]==0)
3055 recv_pe_list.append_array(pe1);
3056 else
3057 drap_per[pe1] = 1;
3058 }
3059 else
3060 {
3061 //je suis pe1 : je dois donc m'attendre a devoir envoyer des infos a pe0
3062 if (drap_pes[pe0]==0)
3063 send_pe_list.append_array(pe0);
3064 else
3065 drap_pes[pe0] = 1;
3066 }
3067 }
3068 }
3069 array_trier_retirer_doublons(send_pe_list);
3070 array_trier_retirer_doublons(recv_pe_list);
3071 comm2.set_send_recv_pe_list(send_pe_list, recv_pe_list);
3072 }
3073 comm2.begin_comm();
3074
3075 //Les proprietaires de sommet 1 doivent alors envoyer leur partie de longueur ideale
3076 // aux proprietaires des somemts 0 (pour que celui-ci puisse calculer la longueur ideale finale)
3077 pe0p = numOwner0p = pe1p = numOwner1p = -1;
3078 for (indice=0 ; indice<nb_tab_aretes ; indice++)
3079 {
3080 iarete = tab_index[indice];
3081 pe0 = tab_aretes(iarete,0);
3082 pe1 = tab_aretes(iarete,2);
3083 if (pe1==_MOI_ && pe0!=_MOI_)
3084 {
3085 //je suis le proprietaire de numOwner1, mais pas de numOwner0
3086 //je dois donc envoyer a pe0 mon calcul de la longueur ideale
3087 numOwner0 = tab_aretes(iarete,1);
3088 numOwner1 = tab_aretes(iarete,3);
3089 if (FTd_compare_sommets_global(pe1,numOwner1,pe1p,numOwner1p)!=0 || FTd_compare_sommets_global(pe0,numOwner0,pe0p,numOwner0p)!=0)
3090 {
3091 //on est sur une arete differente de la precedente : on doit donc envoyer le message
3092 lgr_ideale12 = tab_criteres(iarete,5);
3093 Sortie& buffer = comm2.send_buffer(pe0);
3094 buffer << pe0 << numOwner0 << pe1 << numOwner1 << lgr_ideale12;
3095 pe0p = pe0;
3096 numOwner0p = numOwner0;
3097 pe1p = pe1;
3098 numOwner1p = numOwner1;
3099 }
3100 }
3101 }
3102 //on lance l'echange des messages
3104
3105 //on recupere les messages :
3106 //ce sont des messages venant des proprietaires de sommets 1
3107 //et m'envoyant leur partie de calcul de la longueur ideale
3108 {
3109 const ArrOfInt& pe_voisins = comm2.get_recv_pe_list();
3110 const int nb_pe_voisins = pe_voisins.size_array();
3111 int peVoi, pe0bis,numOwner0bus, pe1bis,numOwner1bis, trouve;
3112 for (int indice_pe = 0; indice_pe < nb_pe_voisins; indice_pe++)
3113 {
3114 peVoi = pe_voisins[indice_pe];
3115 Entree& buffer = comm2.recv_buffer(peVoi);
3116 buffer >> pe0bis;
3117 while (!buffer.eof())
3118 {
3119 buffer >> numOwner0bus >> pe1bis >> numOwner1bis >> lgr_ideale12;
3120 assert(pe1bis==peVoi && pe0bis!=peVoi);
3121 tmp = -1;
3122 trouve = -1;
3123 do
3124 {
3125 tmp = chercher_arete_tab(tmp,tab_index,tab_aretes, pe0bis,numOwner0bus,pe1bis,numOwner1bis);
3126 if (tmp>=0)
3127 {
3128 trouve = 1;
3129 iarete = tab_index[tmp];
3130 tab_criteres(iarete,5) = lgr_ideale12;
3131 }
3132 }
3133 while (tmp>=0);
3134 if (trouve==-1)
3135 {
3136 Process::Journal()<<"PB : n'a pu insere l'arete ";
3137 Process::Journal()<<" arete=("<<tab_aretes(iarete,0)<<"-"<<tab_aretes(iarete,1)<<" / "<<tab_aretes(iarete,2)<<"-"<<tab_aretes(iarete,3);
3138 Process::Journal()<<" crit=("<<tab_criteres(iarete,3)<<" / "<<tab_criteres(iarete,4)<<" / "<<tab_criteres(iarete,5)<<finl;
3139 tmp = chercher_arete_tab(tmp,tab_index,tab_aretes, pe0bis,numOwner0bus,pe1bis,numOwner1bis);
3140 assert(0==1);
3141 }
3142 buffer >> pe0bis;
3143 }
3144 }
3145 }
3146 //finit la communication
3147 comm2.end_comm();
3148
3149 //a la fin de cela, je connais toutes les infos necessaires pour calculer le critere sur les aretes
3150 //dont je suis proprietaire du sommet 0
3151 //on va donc calculer le critere pour chacune des aretes dont je suis le proprietaire du sommet 0
3152 int NV_nb_sommets = maillage.nb_sommets();
3153 iarete = 0;
3154 {
3155 ArrOfIntFT liste_pe, liste_sommets;
3156 // Rapport entre longueur minimale ou maximale de l'arete et la longueur ideale:
3157 const double tolerance_longueur_arete = 1 + critere_arete_ * ((drap>0) ? 1. : -1);
3158 // Carre de ce rapport (on va comparer le rapport des carres des longueurs):
3159 const double coeff2 = tolerance_longueur_arete * tolerance_longueur_arete;
3160 double critere, lgrIdeale2;
3161 int test=-1;
3162 //pour cela, on va alors balayer les aretes, dans l'ordre trie
3163 pe0p = numOwner0p = pe1p = numOwner1p = -1;
3164 for (indice=0 ; indice<nb_tab_aretes ; indice++)
3165 {
3166 iarete = tab_index[indice];
3167 pe0 = tab_aretes(iarete,0);
3168 if (pe0==_MOI_)
3169 {
3170 //je suis le proprietaire de som0
3171 numOwner0 = tab_aretes(iarete,1);
3172 pe1 = tab_aretes(iarete,2);
3173 numOwner1 = tab_aretes(iarete,3);
3174 if (FTd_compare_sommets_global(pe1,numOwner1,pe1p,numOwner1p) != 0
3175 || FTd_compare_sommets_global(pe0,numOwner0,pe0p,numOwner0p) != 0)
3176 {
3177 //on est sur une arete differente de la precedente
3178 //on va donc recalculer le critere
3179 //on calcule la moyenne des carres des longueurs ideales calculees en chacun des sommets
3180 lgrIdeale2 = 0.5 * (tab_criteres(iarete,4) + tab_criteres(iarete,5));
3181 assert(lgrIdeale2>0);
3182 //calcul du critere : lrg2/ (lgrIdeale2 * coeff2) ou
3183 // -coeff2 = (1+C)^2 si on veut tester les aretes a diviser (drap>0)
3184 // -coeff2 = (1-C)^2 si on veut tester les aretes a supprimer (drap<0)
3185 lgr2 = tab_criteres(iarete,3);
3186 assert(lgr2>=0.);
3187 critere = lgr2 / (lgrIdeale2 * coeff2);
3188 //le test a verifier est
3189 // (critere<1) si on veut tester les aretes a diviser (drap>0)
3190 // (critere>1) si on veut tester les aretes a supprimer (drap<0)
3191 test = (drap>0)? (critere<1) : (critere>1);
3192 }
3193 tab_aretes(iarete,8) = test;
3194 if (drap>0 && !test)
3195 {
3196 // le test n'est pas verifie pour une arete trop grande :
3197 // on doit creer un sommet
3198 // verifie d'abord si le sommet n'a pas deja ete cree
3199 tmp = -1;
3200 for (isom=0 ; isom<nb_somD && tmp==-1 ; isom++)
3201 {
3202 if (FTd_compare_sommets_global(pe0,numOwner0,tab_arete_somD(isom,0),tab_arete_somD(isom,1))==0
3203 && FTd_compare_sommets_global(pe1,numOwner1,tab_arete_somD(isom,2),tab_arete_somD(isom,3))==0)
3204 {
3205 tmp = isom;
3206 }
3207 }
3208 if (tmp==-1)
3209 {
3210 //sommet non trouve : le cree
3211 if (NV_nb_sommets>=sommets.dimension(0))
3212 {
3213 tmp = NV_nb_sommets+10;
3214 sommets.resize(tmp, sommets.dimension(1));
3215 sommet_elem.resize_array(tmp);
3216 sommet_face_bord.resize_array(tmp);
3217 sommet_PE_owner.resize_array(tmp);
3218 sommet_num_owner.resize_array(tmp);
3219 drapeaux_sommets.resize_array(tmp);
3220 }
3221 sommets(NV_nb_sommets,0) = sommets(numOwner0,0);
3222 sommets(NV_nb_sommets,1) = sommets(numOwner0,1);
3223 if (dimension3)
3224 sommets(NV_nb_sommets,2) = sommets(numOwner0,2);
3225 sommet_elem[NV_nb_sommets] = sommet_elem[numOwner0];
3226 face_bord1 = tab_aretes(iarete,4);
3227 maillage.convertir_numero_distant_local(maillage.desc_sommets_,sommet_num_owner,numOwner1,pe1,som_s);
3228 if (face_bord1!=-1)
3229 {
3230 sommet_face_bord[NV_nb_sommets] = sommet_face_bord[numOwner0];
3231 }
3232 else
3233 {
3234 sommet_face_bord[NV_nb_sommets] = -1;
3235 }
3236 sommet_PE_owner[NV_nb_sommets] = sommet_PE_owner[numOwner0];
3237 sommet_num_owner[NV_nb_sommets] = NV_nb_sommets;
3238 drapeaux_sommets[NV_nb_sommets] = drapeaux_sommets[numOwner0];
3239 //on stocke les infos du nouveau sommet
3240 if (nb_somD>=tab_somD.size_array())
3241 {
3242 tmp = nb_somD+10;
3243 tab_somD.resize_array(tmp);
3244 tab_deplacement_somD.resize(tmp,dimension);
3245 tab_arete_somD.resize(tmp,tab_arete_somD.dimension(1));
3246 }
3247 //indice
3248 tab_somD[nb_somD] = NV_nb_sommets;
3249 //deplacement
3250 tab_deplacement_somD(nb_somD,0) = 0.5 * ( tab_criteres(iarete,0) - sommets(NV_nb_sommets,0) );
3251 tab_deplacement_somD(nb_somD,1) = 0.5 * ( tab_criteres(iarete,1) - sommets(NV_nb_sommets,1) );
3252 if (dimension3)
3253 tab_deplacement_somD(nb_somD,2) = 0.5 * ( tab_criteres(iarete,2) - sommets(NV_nb_sommets,2) );
3254 //arete
3255 tab_arete_somD(nb_somD,0) = tab_aretes(iarete,0);
3256 tab_arete_somD(nb_somD,1) = tab_aretes(iarete,1);
3257 tab_arete_somD(nb_somD,2) = tab_aretes(iarete,2);
3258 tab_arete_somD(nb_somD,3) = tab_aretes(iarete,3);
3259 nb_somD++;
3260 tmp = NV_nb_sommets;
3261 NV_nb_sommets++;
3262 }
3263 else
3264 {
3265 tmp = tab_somD[tmp];
3266 }
3267 //on stocke aussi l'indice du sommet dans les infos des aretes
3268 tab_aretes(iarete,9) = tmp;
3269
3270 int peReq = tab_aretes(iarete,5);
3271 if (peReq!=_MOI_)
3272 {
3273 liste_pe.append_array(peReq);
3274 liste_sommets.append_array(tmp);
3275 }
3276 }
3277 }
3278 }
3279 test = (NV_nb_sommets!=nb_sommets);
3280 test = static_cast<int>(Process::mp_sum(test));
3281 if (test>0)
3282 {
3283 //le nb de sommets a ete modifie :
3284 //redimensionnement
3285 tmp = NV_nb_sommets;
3286 sommets.resize(tmp, sommets.dimension(1));
3287 sommet_elem.resize_array(tmp);
3288 sommet_face_bord.resize_array(tmp);
3289 sommet_PE_owner.resize_array(tmp);
3290 sommet_num_owner.resize_array(tmp);
3291 drapeaux_sommets.resize_array(tmp);
3292 maillage.desc_sommets_.calcul_schema_comm(tmp);
3293 //creation des sommets virtuels dans les processeurs le necessitant
3294 const Schema_Comm& comm_ = maillage.desc_sommets().schema_comm();
3295 maillage.creer_sommets_virtuels(liste_sommets,liste_pe,comm_);
3296 }
3297 }
3298
3299 // Les proprietaires des sommets envoient les resultats du test aux
3300 // PEs qui ont demande le test (ce sont les proprietaires des aretes,
3301 // chez qui les sommets sont virtuels). C'est donc le schema de comm direct:
3302 // proprietaire du sommet envoie des donnees aux PEs qui ont des sommets virtuels.
3303 const Schema_Comm& comm_real_to_virt = maillage.desc_sommets_.schema_comm();
3304 comm_real_to_virt.begin_comm();
3305 //on va maintenant balayer les aretes pour stocker celles ne verifiant pas le test
3306 int peReq, test;
3307 pe0p = numOwner0p = pe1p = numOwner1p = -1;
3308 for (indice=0 ; indice<nb_tab_aretes ; indice++)
3309 {
3310 iarete = tab_index[indice];
3311 pe0 = tab_aretes(iarete,0);
3312 if (pe0==_MOI_)
3313 {
3314 //je suis le proprietaire de som0
3315 numOwner0 = tab_aretes(iarete,1);
3316 pe1 = tab_aretes(iarete,2);
3317 numOwner1 = tab_aretes(iarete,3);
3318 if (FTd_compare_sommets_global(pe1,numOwner1,pe1p,numOwner1p)!=0 || FTd_compare_sommets_global(pe0,numOwner0,pe0p,numOwner0p)!=0)
3319 {
3320 //on est sur une arete differente de la precedente
3321 test = tab_aretes(iarete,8);
3322 if (!test)
3323 {
3324 //le critere n'est pas verifie
3325 peReq = tab_aretes(iarete,5);
3326 fa7 = tab_aretes(iarete,6);
3327 isom = tab_aretes(iarete,7);
3328 if (drap>0)
3329 {
3330 //on divise des aretes : un sommet a ajouter
3331 som = tab_aretes(iarete,9);
3332 }
3333 else
3334 {
3335 //on supprime des aretes : pas de sommet a ajouter
3336 som = -1;
3337 }
3338 if( peReq==_MOI_)
3339 {
3340 //je suis aussi celui qui avait besoin de l'info
3341 //je stocke les infos dans mon tableau
3342 if (nb_aretesMarquees>=tab_aretesMarquees.dimension(0))
3343 {
3344 tab_aretesMarquees.resize(nb_aretesMarquees+10,tab_aretesMarquees.dimension(1));
3345 }
3346 tab_aretesMarquees(nb_aretesMarquees,0) = fa7;
3347 tab_aretesMarquees(nb_aretesMarquees,1) = isom;
3348 tab_aretesMarquees(nb_aretesMarquees,2) = _MOI_;
3349 tab_aretesMarquees(nb_aretesMarquees,3) = som;
3350 nb_aretesMarquees++;
3351 }
3352 else
3353 {
3354 //je dois envoyer l'info a celui qui me l'a demandee
3355 Sortie& buffer = comm_real_to_virt.send_buffer(peReq);
3356 buffer << fa7 << isom << som;
3357 }
3358 }
3359 }
3360 }
3361 }
3362
3363 //on lance l'echange des messages
3364 comm_real_to_virt.echange_taille_et_messages();
3365
3366 //on recupere les messages venant des proprietaires des sommets 0
3367 //lorsque ceux-ci ont trouve une arete ne verifiant pas le critere
3368 {
3369 const ArrOfInt& pe_voisins = comm_real_to_virt.get_recv_pe_list();
3370 const int nb_pe_voisins = pe_voisins.size_array();
3371 int peVbis;
3372 for (int indice_pe = 0; indice_pe < nb_pe_voisins; indice_pe++)
3373 {
3374 peVbis = pe_voisins[indice_pe];
3375 Entree& buffer = comm_real_to_virt.recv_buffer(peVbis);
3376 buffer >> fa7;
3377 while (!buffer.eof())
3378 {
3379 buffer >> isom >> som;
3380 assert(_MOI_!=peVbis);
3381 //je stocke les infos dans mon tableau
3382 if (nb_aretesMarquees>=tab_aretesMarquees.dimension(0))
3383 {
3384 tab_aretesMarquees.resize(nb_aretesMarquees+10,tab_aretesMarquees.dimension(1));
3385 }
3386 tab_aretesMarquees(nb_aretesMarquees,0) = fa7;
3387 tab_aretesMarquees(nb_aretesMarquees,1) = isom;
3388 tab_aretesMarquees(nb_aretesMarquees,2) = peVbis;
3389 tab_aretesMarquees(nb_aretesMarquees,3) = som;
3390 nb_aretesMarquees++;
3391 buffer >> fa7;
3392 }
3393 }
3394 }
3395 //termine cette communication
3396 comm_real_to_virt.end_comm();
3397
3398 //Redimensionnement
3399 tab_aretesMarquees.resize(nb_aretesMarquees,tab_aretesMarquees.dimension(1));
3400 tab_somD.resize_array(nb_somD);
3401 tab_deplacement_somD.resize(nb_somD,tab_deplacement_somD.dimension(1));
3402
3404
3405 return res;
3406}
3407
3408
3409/*! @brief Cette methode calcule, pour un triangle donne, sa qualite : celle-ci est comprise dans ]0,1], et vaut 1 pour un triangle equilateral.
3410 *
3411 * @param (som0) id du premier sommet
3412 * @param (som1) id du second sommet
3413 * @param (som2) id du troisieme sommet
3414 * @param (CoordSom) coordonnees des sommets
3415 * @return (double) le coefficient de qualite du triangle.
3416 */
3417double Remaillage_FT::qualiteTriangle(const FTd_vecteur3& som0, const FTd_vecteur3& som1, const FTd_vecteur3& som2, double& aire) const
3418{
3419 int k;
3420
3421 //calcul de perimetre2 = somme des carres de aretes
3422 double perimetre2 = 0.,d;
3423 for (k=0 ; k<dimension ; k++)
3424 {
3425 d = som1[k] - som0[k];
3426 perimetre2 += d*d;
3427 }
3428 for (k=0 ; k<dimension ; k++)
3429 {
3430 d = som2[k] - som1[k];
3431 perimetre2 += d*d;
3432 }
3433 for (k=0 ; k<dimension ; k++)
3434 {
3435 d = som0[k] - som2[k];
3436 perimetre2 += d*d;
3437 }
3438
3439 assert(perimetre2>0.);
3440
3441 //calcul de l'aire du triangle
3442 aire = 0.;
3443 FTd_vecteur3 vect;
3444 vect[0] = (som1[1]-som0[1]) * (som2[2]-som0[2]) - (som1[2]-som0[2]) * (som2[1]-som0[1]);
3445 vect[1] = (som1[2]-som0[2]) * (som2[0]-som0[0]) - (som1[0]-som0[0]) * (som2[2]-som0[2]);
3446 vect[2] = (som1[0]-som0[0]) * (som2[1]-som0[1]) - (som1[1]-som0[1]) * (som2[0]-som0[0]);
3447 for (k=0 ; k<dimension ; k++)
3448 {
3449 aire += vect[k]*vect[k];
3450 }
3451 aire = sqrt(aire)/2.;
3452
3453#ifndef NDEBUG
3454 if (impr_>9000 && aire<=0.)
3455 {
3456 Cerr<<"PB qualiteTriangle :"<<finl;
3457 Cerr<<" som0 "<<" coord= "<<som0[0]<<" "<<som0[1]<<" "<<som0[2]<<finl;
3458 Cerr<<" som1 "<<" coord= "<<som1[0]<<" "<<som1[1]<<" "<<som1[2]<<finl;
3459 Cerr<<" som2 "<<" coord= "<<som2[0]<<" "<<som2[1]<<" "<<som2[2]<<finl;
3460 Cerr<<" perimetre= "<<perimetre2<<finl;
3461 Cerr<<" vect= "<<vect[0]<<" "<<vect[1]<<" "<<vect[2]<<" aire= "<<aire<<finl;
3462 }
3463#endif
3464 // sqrt(3) : erreur sur xlC
3465 const double sq3x4 = sqrt(3.) * 4.;
3466
3467 double qual = sq3x4 * aire / perimetre2;
3468
3469 return qual;
3470}
3471
3472/*! @brief Cette fonction "supprime" les facettes de surface nulle : Elle les reduit a 1 sommet (le sommet 0, pour ne pas changer de processeur)
3473 *
3474 * @param (maillage) maillage a remailler
3475 * @return (int) 1 si le remaillage s'est deroule correctement, 0 sinon
3476 */
3478{
3479 int res = 1;
3480
3481 Process::Journal()<<"Remaillage_FT::supprimer_facettes_nulles nb_fa7="<<maillage.nb_facettes()<<finl;
3482 maillage.check_mesh();
3483
3484 IntTab& facettes = maillage.facettes_;
3485 const ArrOfDouble& surface_facettes = maillage.get_update_surface_facettes();
3486 const int nb_facettes = maillage.nb_facettes();
3487 const int nb_som_par_facette = facettes.dimension(1);
3488
3489 int fa7,isom, nb_fa70 = 0;
3490 //on balaye les facettes pour marquer celles a supprimer
3491 for (fa7=0 ; fa7<nb_facettes ; fa7++)
3492 {
3493 if (surface_facettes[fa7]<=0.)
3494 {
3495 for (isom=1 ; isom<nb_som_par_facette ; isom++)
3496 {
3497 facettes(fa7,isom) = facettes(fa7,0);
3498 }
3499 nb_fa70++;
3500 }
3501 }
3502
3503 // On a modifie le maillage
3505
3506 Process::Journal()<<"Remaillage_FT::supprimer_facettes_nulles nb_fa70="<<nb_fa70<<finl;
3507 maillage.check_mesh();
3508
3509 //lance le nettoyage (statut minimal remis a cet endroit)
3510 nettoyer_maillage(maillage);
3511
3512 Process::Journal()<<"FIN Remaillage_FT::supprimer_facettes_nulles nb_fa7="<<maillage.nb_facettes()<<finl;
3513 return res;
3514}
3515/*! @brief Cette fonction nettoie le maillage : Elle supprime les facettes reduites a 1 sommet
3516 *
3517 * Elle supprime les sommets non utilises
3518 *
3519 * @param (maillage) maillage a remailler
3520 * @return (int) 1 si le remaillage s'est deroule correctement, 0 sinon
3521 */
3523{
3524 int res = 1;
3525
3526 Process::Journal()<<"Remaillage_FT::nettoyer_maillage nb_fa7="<<maillage.nb_facettes()<<finl;
3527
3528 //lance le nettoyage (statut minimal remis a cet endroit)
3529 maillage.nettoyer_maillage();
3530
3531 Process::Journal()<<"FIN Remaillage_FT::nettoyer_maillage nb_fa7="<<maillage.nb_facettes()<<finl;
3532 return res;
3533}
3534
3535/*! @brief Regularise le maillage en deplacant les sommets pour reduire les gradients de courbure.
3536 *
3537 * L'equation d'evolution du maillage est une diffusion de masse le long
3538 * de l'interface proportionnelle au gradient de courbure.
3539 *
3540 */
3542 const double coeff,
3543 ArrOfDouble& dvolume) const
3544{
3545 const IntTab& facettes = maillage.facettes();
3546 const DoubleTab& sommets = maillage.sommets();
3547 const int nb_facettes = facettes.dimension(0);
3548 const int dim = facettes.dimension(1);
3549 const ArrOfDouble& surface_facettes =
3550 maillage.get_update_surface_facettes();
3551
3552 const double angle_bidim_axi = bidim_axi ? Maillage_FT_Disc::angle_bidim_axi() : 0.;
3553 // Calcul de la courbure de l'interface
3554 const ArrOfDouble& courbure = maillage.get_update_courbure_sommets();
3555
3556 // Calcul de la longueur de la plus petite arete
3557 double l_min = 1e10;
3558 int count = 0;
3559 int total_count = 0;
3560 const double one_third = 1. / 3.;
3561
3562 dvolume = 0.;
3563 int i_facette;
3564 for (i_facette = 0; i_facette < nb_facettes; i_facette++)
3565 {
3566 // Ne pas calculer de flux pour les facettes virtuelles:
3567 if (maillage.facette_virtuelle(i_facette))
3568 continue;
3569 if (dim == 2)
3570 {
3571 const int s1 = facettes(i_facette, 0);
3572 const int s2 = facettes(i_facette, 1);
3573 const double x1 = sommets(s1, 0);
3574 const double x2 = sommets(s2, 0);
3575 const double dx = x2 - x1;
3576 const double dy = sommets(s2, 1) - sommets(s1, 1);
3577 const double l2 = dx * dx + dy * dy;
3578 if (l2 > 0.)
3579 {
3580 const double inv_l = 1. / sqrt(l2);
3581 const double inv_l2 = 1. / (l2);
3582 if (l2 < l_min)
3583 l_min = l2;
3584
3585 const double c1 = courbure[s1];
3586 const double c2 = courbure[s2];
3587 const double gradient_c = (c2 - c1) / sqrt(l2);
3588 // We assume that the highest curvature achievable is 1/l (corresponds to an hexagon)
3589 // and that the maximal gradient is a 50%
3590 const double criterion1 = lissage_critere_*0.5*inv_l2;
3591 // Or we assume the variation around mean curvature is at maximum 50% of c_moy
3592 const double criterion2 = lissage_critere_*0.25*std::fabs(c1+c2)*inv_l;
3593 if ((std::fabs(gradient_c)>= criterion1)||(std::fabs(gradient_c)>= criterion2))
3594 {
3595 double h = 1.;
3596 if (bidim_axi)
3597 h = (x1+x2) * 0.5 * angle_bidim_axi;
3598 const double flux = gradient_c * h;
3599 dvolume[s1] += flux;
3600 dvolume[s2] -= flux;
3601 count++;
3602 }
3603 total_count++;
3604 }
3605 }
3606 else
3607 {
3608 int som[3]; // Indices des trois sommets
3609 double c[3]; // Courbure des trois sommets
3610 double coord[3][3]; // Coordonnees
3611 int i, j;
3612 for (i = 0; i < 3; i++)
3613 {
3614 const int s = facettes(i_facette, i);
3615 som[i] = s;
3616 c[i] = courbure[s];
3617 for (j = 0; j < 3; j++)
3618 coord[i][j] = sommets(s, j);
3619 }
3620 const double surface = surface_facettes[i_facette];
3621 int i_suiv = 2;
3622 for (i = 0; i < 3; i++)
3623 {
3624 const double dx = coord[i_suiv][0] - coord[i][0];
3625 const double dy = coord[i_suiv][1] - coord[i][1];
3626 const double dz = coord[i_suiv][2] - coord[i][2];
3627 // Longueur de l'arete au carre
3628 const double l2 = dx * dx + dy * dy + dz * dz;
3629 if (l2 < l_min)
3630 l_min = l2;
3631 const double inv_l = (l2 == 0.) ? 1. : 1. / sqrt(l2);
3632 const double inv_l2 = (l2 == 0.) ? 1. : 1. / (l2);
3633 const double c1 = c[i];
3634 const double c2 = c[i_suiv];
3635 const double gradient_c = (c2 - c1) * inv_l;
3636 // We assume that the highest curvature achievable is 1/l (corresponds to an hexagon)
3637 // and that the maximal gradient is a 50%
3638 const double criterion1 = lissage_critere_*0.5*inv_l2;
3639 // Or we assume the variation around mean curvature is at maximum 50% of c_moy
3640 const double criterion2 = lissage_critere_*0.25*std::fabs(c1+c2)*inv_l;
3641 if ((std::fabs(gradient_c)>= criterion1)||(std::fabs(gradient_c)>= criterion2))
3642 {
3643 // Hauteur d'un tiers du triangle (facette, la base du triangle etant [i,i_suiv])
3644 const double h = (surface * inv_l) * one_third;
3645 // Integrale du flux de masse sur le morceau de volume de controle autour des
3646 // sommets (au coefficient de diffusion pres) :
3647 const double flux = gradient_c * h;
3648
3649 const int s1 = som[i]; // Numero du premier sommet
3650 const int s2 = som[i_suiv]; // Numero du deuxieme sommet
3651 dvolume[s1] += flux;
3652 dvolume[s2] -= flux;
3653 count++;
3654 }
3655 total_count++;
3656 i_suiv = i;
3657 }
3658 }
3659 }
3660 l_min = Process::mp_min(l_min);
3661 if ((total_count)&&(lissage_critere_>DMINFLOAT))
3662 Journal() << "Proportion of smoothed aretes (similar to sommets) " << 100.*count/total_count << " %" << finl;
3663 // Calcul du coefficient de diffusion * pas de temps pour stabilite:
3664 // proportionnel a longueur^4 :
3665 const double coeff_dt = l_min * l_min * coeff;
3666 dvolume *= coeff_dt;
3667
3669
3670 const DoubleVect& volume = refdomaine_VF_->volumes();
3671 int clip=0;
3672 double lost_volume = 0.;
3673 int nb_som_reels = 0;
3674 for (int s = 0; s < maillage.nb_sommets(); s++)
3675 {
3676 if (!maillage.sommet_virtuel(s))
3677 nb_som_reels++;
3678 const int elem = maillage.sommet_elem()[s];
3679 if (elem>=0)
3680 {
3681 // On est dans un element reel
3682 if (dvolume[s]>volume[elem] )
3683 {
3684 lost_volume += dvolume[s]-volume[elem];
3685 dvolume[s] = volume[elem];
3686 clip++;
3687 }
3688 if (-dvolume[s]>volume[elem] )
3689 {
3690 lost_volume += dvolume[s]+volume[elem];
3691 dvolume[s] = -volume[elem];
3692 clip++;
3693 }
3694 }
3695 }
3697 nb_som_reels = Process::check_int_overflow(Process::mp_sum(nb_som_reels));
3698 lost_volume = Process::mp_sum(lost_volume);
3699 if (je_suis_maitre() && clip)
3700 {
3701 Cerr << "[Remaillage_FT::regulariser_courbure] Clipping of var volume in "
3702 << clip << " elems. time = " << maillage.temps()
3703 << " Volume redistributed over the whole interface = "
3704 << lost_volume << finl;
3705 }
3706 if (clip)
3707 {
3708 // On repartit le volume perdu sur toute l'interface:
3709 lost_volume /=nb_som_reels;
3710 for (int s = 0; s < maillage.nb_sommets(); s++)
3711 if (!maillage.sommet_virtuel(s))
3712 dvolume[s] += lost_volume;
3713 }
3714 maillage.desc_sommets().echange_espace_virtuel(dvolume);
3715}
static int check_enabled()
Definition Comm_Group.h:159
static void verifier_tableau_sommets(const char *msg, const Maillage_FT_Disc &, const ArrOfDouble &)
Definition DebogFT.cpp:114
static void verifier_maillage_ft(const char *msg, const Maillage_FT_Disc &)
Definition DebogFT.cpp:103
: class Desc_Structure_FT
void collecter_espace_virtuel(ArrOfDouble &tab, MD_Vector_tools::Operations_echange op) const
void echange_espace_virtuel(ArrOfDouble &tab) const
void calcul_schema_comm(const int nb_items_tot)
const Schema_Comm & schema_comm() const
const Schema_Comm & schema_comm_inverse() const
class Domaine_VF
Definition Domaine_VF.h:44
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
static int is_ecriture_special(int &special, int &a_faire)
indique si le format special a ete demande en lecture active par sauvegarde xyz .
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int eof()
Definition Entree.cpp:256
: class Maillage_FT_Disc Cette classe decrit un maillage:
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.
const ArrOfInt & sommet_num_owner() const
pour postraitement, renvoie le numero des sommets sur le PE proprietaire des sommets
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,
Sortie & printSom(int som, Sortie &os) const
void corriger_proprietaires_facettes()
Sans changer les sommets existants ni la numerotation des facettes, on change le proprietaire des fac...
void update_tableau_apres_transport(ArrOfDouble &tableau, int nb_elements, const Desc_Structure_FT &descripteur) const
Voir preparer_tableau_avant_transport.
ArrOfIntFT sommet_PE_owner_
Desc_Structure_FT desc_facettes_
void creer_sommets_virtuels(const ArrOfInt &liste_sommets, const ArrOfInt &liste_pe, const Schema_Comm &comm)
Envoi des sommets dont le numero est donne dans liste_sommets au processeur dont le numero est donne ...
int nb_facettes() const
renvoie le nombre de facettes (reelles et virtuelles) (egal a facettes().
ArrOfIntFT sommet_face_bord_
int sommet_ligne_contact(int i) const
virtual void nettoyer_maillage()
Retire toutes les facettes virtuelles, toutes les facettes invalides (sommet0 == sommet1) et tous les...
Desc_Structure_FT desc_sommets_
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.
void maillage_modifie(Statut_Maillage nouveau_statut)
Cette methode change le statut du maillage et invalide le cache de valeurs calculees (surface,...
const Desc_Structure_FT & desc_sommets() const
renvoie le descripteur des sommets (espace_distant/virtuel)
virtual int check_mesh(int error_is_fatal=1, int skip_facette_owner=0, int skip_facettes=0) const
ArrOfIntFT sommet_num_owner_
void creer_sommets_virtuels_numowner(const ArrOfInt &request_sommets_pe, const ArrOfInt &request_sommets_num)
Cree chez moi les sommets virtuels specifies par le couple (pe,num) si le sommet n'existe pas encore.
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 convertir_numero_distant_local(const Desc_Structure_FT &descripteur, const ArrOfInt &element_num_owner, const ArrOfInt &numeros_distants, const ArrOfInt &pe_distant, ArrOfInt &numeros_locaux) const
Conversion des couples (numeros_distants, pe) en numeros_locaux.
const Desc_Structure_FT & desc_facettes() const
renvoie le descripteur des facettes (espace_distant/virtuel)
ArrOfIntFT drapeaux_sommets_
int sommet_virtuel(int i) const
const ArrOfInt & sommet_PE_owner() const
pour postraitement, renvoie le numero du PE proprietaire des sommets
virtual void deplacer_sommets(const ArrOfInt &liste_sommets_initiale, const DoubleTab &deplacement_initial, ArrOfInt &liste_sommets_sortis, ArrOfInt &numero_face_sortie, int skip_facettes=0)
Applique un vecteur deplacement aux noeuds dont le numero est dans "liste_noeud", puis echange les es...
virtual void transporter(const DoubleTab &deplacement)
Deplace les sommets de l'interface d'un vecteur "deplacement" fourni, Change eventuellement les somme...
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...
Sortie & printFa7(int fa7, int affsom, Sortie &os) const
static double angle_bidim_axi()
renvoie l'angle solide qui sert a calculer les surfaces et les volumes en bidim_axi
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_
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
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 int bidim_axi
Definition Objet_U.h:102
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
void calculer_normale_face_bord(int num_face, double x, double y, double z, double &nx_, double &ny_, double &nz_) const
void projeter_vecteur_sur_face(const int num_face, double &x_, double &y_, double &z_) const
Methode outil utilisee pour le traitement des lignes de contact.
static double mp_min(double)
Definition Process.cpp:386
static int check_int_overflow(trustIdType)
Definition Process.cpp:428
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 int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static 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
: class Remaillage_FT Cette classe implemente les procedures de remaillage des interfaces pour le Fro...
int calculer_correction_deplacement(DoubleTab &deplacement, const ArrOfDouble &varVolume, const DoubleTab &deplacement_varVolume, const ArrOfDouble &norme2_deplacement_varVolume) const
Cette fonction calcule une correction sur un deplacement liee a une variation de volume imposee Utile...
int supprimer_facettes_bord(Maillage_FT_Disc &maillage) const
Cette fonction marque a supprimer les facettes ayant leurs 3 sommets de bord Marquer a supprimer = co...
double critere_arete_
int diviser_grandes_aretes(Maillage_FT_Disc &maillage) const
Cette fonction divise les grandes aretes en 2.
int sauvegarder(Sortie &) const override
Sauvegarde d'un Objet_U sur un flot de sortie Methode a surcharger.
int chercher_arete_tab(int tmp, const ArrOfInt &tab_index, const IntTab &tab_aretes, int pe0, int numOwner0, int pe1, int numOwner1) const
int lissage_courbure_iterations_old_
int lissage_courbure_iterations_systematique_
double regulariser_maillage(Maillage_FT_Disc &maillage, ArrOfDouble &var_volume, const double facteur_barycentrage_tangent, const double coeff_lissage, const int nb_iter_barycentrage, const int nb_iter_lissage, const int max_nb_iter_correction_volume, const double seuil_dvolume) const
Algorithme general de lissage du maillage.
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 supprimer_facettes_nulles(Maillage_FT_Disc &maillage) const
Cette fonction "supprime" les facettes de surface nulle : Elle les reduit a 1 sommet (le sommet 0,...
void barycentrer_lisser_systematique(double temps, Maillage_FT_Disc &maillage)
applique barycentrage, lissage et correction de volume.
double variation_volume_
int a_remailler(double temps, const Maillage_FT_Disc &maillage) const
int nb_iter_bary_volume_seul_
virtual double calculer_longueurIdeale2_arete(const Maillage_FT_Disc &maillage, int som0, double x, double y, double z) const
Cette fonction calcule le carre de la longueur ideale d'une arete Dans un premier,...
void set_param(Param &p) const override
Methode appelee par readOn.
double calculer_variation_volume_facette_3D(int fa7, const Maillage_FT_Disc &maillage, const DoubleTab &position_initiale) const
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...
double redistribuer_sommets(Maillage_FT_Disc &maillage, const double relaxation_direction_tangente, const double relaxation_direction_normale, ArrOfDouble &var_volume_impose, ArrOfDouble &var_volume_obtenu) const
Deplace les sommets du maillage pour les redistribuer de facon homogene.
int lissage_courbure_iterations_si_remaillage_
int inserer_tab_aretes(int &nb_tab_aretes, IntTab &tab_aretes, DoubleTab &tab_criteres, int pe0, int numOwner0, int pe1, int numOwner1, int face_bord1, int peRequete, int fa7_peR, int iarete_fa7_peR) const
int permuter_aretes(Maillage_FT_Disc &maillage) const
Cette fonction effectue des permutations d'aretes afin d'ameliorer la qualite du maillage.
void associer_domaine(const Domaine_dis_base &domaine_dis)
Cette fonction stocke le domaine_dis dans refdomaine_dis_.
int marquer_aretes(Maillage_FT_Disc &maillage, IntTab &tab_aretesMarquees, ArrOfInt &tab_somD, DoubleTab &tab_deplacement_somD, int drap) const
void remaillage_local_interface(double temps, Maillage_FT_Disc &maillage)
Verifie les criteres de remaillage locaux (longueur des aretes) et effectue les remaillages locaux si...
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...
int nettoyer_maillage(Maillage_FT_Disc &maillage) const
Cette fonction nettoie le maillage : Elle supprime les facettes reduites a 1 sommet.
double calculer_variation_volume_facette_2D(int fa7, const Maillage_FT_Disc &maillage, const DoubleTab &position_initiale) const
Cette fonction calcule la difference de volume au niveau d'une facette par rapport a une position ini...
double lissage_courbure_coeff_
double dt_remaillage_
double facteur_longueur_ideale_
double calculer_volume_sommets_supprimes(const Maillage_FT_Disc &maillage, const ArrOfInt &tab_somSupp, ArrOfDouble &varVolume) const
Cette fonction calcule la variation de volume liee a la suppression de sommets.
int supprimer_doublons_facettes(Maillage_FT_Disc &maillage) const
Cette fonction marque a supprimer les facettes en double.
double qualiteTriangle(const FTd_vecteur3 &som0, const FTd_vecteur3 &som1, const FTd_vecteur3 &som2, double &aire) const
Cette methode calcule, pour un triangle donne, sa qualite : celle-ci est comprise dans ]0,...
double seuil_dvolume_residuel_
int reprendre(Entree &) override
Reprise d'un Objet_U sur un flot d'entree Methode a surcharger.
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".
int a_lisser(double temps) const
void corriger_volume_(Maillage_FT_Disc &maillage, ArrOfDouble &var_volume, const int nb_iter_corrections_vol)
double relax_barycentrage_
double temps_dernier_remaillage_
virtual void regulariser_courbure(Maillage_FT_Disc &maillage, const double coeff, ArrOfDouble &dvolume) const
Regularise le maillage en deplacant les sommets pour reduire les gradients de courbure.
void corriger_volume(Maillage_FT_Disc &maillage, ArrOfDouble &var_volume)
deplacement des sommets se sorte a produire la variation de volume prescrite a chaque sommet.
double temps_dernier_lissage_
int calculer_barycentre_facettes_voisines(const Maillage_FT_Disc &maillage, DoubleTab &barycentres) const
Cette fonction calcule pour chaque sommet le barycentre de l'ensemble des facettes voisines du sommet...
int calculer_connectivites_sommetFacettes(const Maillage_FT_Disc &maillage, ArrOfInt &fa7VoisinesSom_index, IntTab &fa7VoisinesSom_data) const
Cette fonction calcule les connectivites sommet ->facettes voisines Les facettes voisines des sommets...
double valeur_longueur_fixe_
int supprimer_petites_aretes(Maillage_FT_Disc &maillage, ArrOfDouble &varVolume) const
A l'aide de "marquer_aretes", on determine les aretes trop petites du maillage.
void barycentrer_lisser_apres_remaillage(Maillage_FT_Disc &maillage, ArrOfDouble &var_volume)
idem mais avec le nombre d'iterations de lissage si remaillage
int calculer_differentielle_volume(const Maillage_FT_Disc &maillage, DoubleTab &differentielle_volume) const
Calcul de la differentielle du volume de phase 0 par rapport au deplacement de chaque sommet de l'int...
double lissage_critere_
double surface_interface_
const bool & get_is_solid_particle() const
void echange_taille_et_messages() const
Cette methode lance l'echange de donnees entre tous les processeurs.
Sortie & send_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y entasser des donnees a envoyer.
void end_comm() const
Vide les buffers et libere les ressources: on a fini de lire les donnees recues dans les buffers.
Entree & recv_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y lire les donnees recues.
const ArrOfInt & get_recv_pe_list() const
void begin_comm() const
Reserve les buffers de comm pour une nouvelle communication.
void set_send_recv_pe_list(const ArrOfInt &send_pe_list, const ArrOfInt &recv_pe_list, const int me_to_me=0)
Definit la liste des processeurs a qui on va envoyer et de qui on va recevoir des donnees.
Classe de base des flux de sortie.
Definition Sortie.h:52
void append_array(_TYPE_ valeur)
Iterator_ end()
Definition TRUSTArray.h:112
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Iterator_ begin()
Definition TRUSTArray.h:111
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
void append_line(_TYPE_)
Definition TRUSTTab.tpp:213
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
static int is_PDI_checkpoint()
static int is_PDI_restart()