TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Faces_builder.cpp
1/****************************************************************************
2* Copyright (c) 2026, 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 <Connectivite_som_elem.h>
17#include <EcrFicCollecteBin.h>
18#include <Elem_geom_base.h>
19#include <Poly_geom_base.h>
20#include <communications.h>
21#include <NettoieNoeuds.h>
22#include <Faces_builder.h>
23#include <Domaine.h>
24#include <Scatter.h>
25#include <stdio.h>
26#include <vector>
27#include <array>
28#include <map>
29
30template <typename _SIZE_>
32 les_elements_ptr_(0),
33 connectivite_som_elem_ptr_(0),
34 is_polyedre_(-1)
35{
36}
37
38template <typename _SIZE_>
40{
41 les_elements_ptr_ = 0;
42 connectivite_som_elem_ptr_ = 0;
43 faces_element_reference_old_.reset();
44 ref_domaine_.reset();
45 faces_sommets_.reset();
46 face_elem_.reset();
47}
48
49/*! @brief A partir de la description des elements du domaine et des frontieres (bords, raccords, groupe de faces et joints) :
50 *
51 * Remplissage des structures suivantes:
52 * - pour les frontieres du domaine: fixer_num_premiere_face
53 * - les_faces.faces_sommets (faces reeles)
54 * - les_faces.faces_voisins (faces reeles)
55 * - elem_faces (pour les faces reeles des elements reels)
56 * (on initialise elem_faces de taille nb_elem_reels, nb_faces_par_elem)
57 * - joints.items_communs(FACE)
58 *
59 */
60template <typename _SIZE_>
62 const Static_Int_Lists_t& connect_som_elem,
63 Faces_t& les_faces,
64 IntTab_t& elem_faces)
65{
66 les_elements_ptr_ = & domaine.les_elems();
67
68 connectivite_som_elem_ptr_ = & connect_som_elem;
69 // La connectivite doit contenir les sommets virtuels
70 assert(connect_som_elem.get_nb_lists() == domaine.nb_som_tot());
71
72 // Remplissage du tableau des faces de l'element de reference
73
74 is_polyedre_=0;
75 if (sub_type(Poly_geom_base,domaine.type_elem().valeur()))
76 {
77 is_polyedre_=1;
78 }
79 else
80 domaine.type_elem()->get_tab_faces_sommets_locaux(faces_element_reference_old_);
81 // Tableau de taille (nb_faces, nb_sommets par face),
82 // pour chaque face, les indices de ses sommets dans le domaine.
83 // L'ordre des sommets est celui donne par l'element de reference,
84 // pour celui des elements voisins de la face qui a le plus petit
85 // indice.
86 IntTab_t& faces_sommets = les_faces.les_sommets();
87
88 // Tableau de taille (nb_faces, 2) contenant pour chaque face
89 // les indices des deux elements voisins. Si "i_face" a un seul voisin,
90 // faces_voisins_(i_face, 1) = -1;
91 IntTab_t& faces_voisins = les_faces.voisins();
92
93 // Initialisation des references utilisees dans check_erreur_faces
94 faces_sommets_ = faces_sommets;
95 face_elem_ = faces_voisins;
96 ref_domaine_ = domaine;
97
98 // Le tableau des faces des elements:
99 // dimension(0) = nombre d'elements,
100 // dimension(1) = nombre de faces par element
101 // elem_faces(i,j) = indice de la face j de l'element i dans les
102 // tableaux faces_sommets et faces_voisins
103 // (les faces de l'element sont dans l'ordre donne par faces_element_reference)
104 // espaces distants et virtuels appropries pour les elements
105 const int_t nb_elements = les_elements().dimension(0);
106 const int nb_faces_par_element = faces_element_reference(0).dimension(0);
107 elem_faces.resize(nb_elements, nb_faces_par_element);
108 elem_faces = -1;
109
110 const int nb_sommets_par_face = faces_element_reference(0).dimension(1);
111 // On ajoute chaque face avec resize(n+1,...), donc smart_resize:
112 // Calcul du nombre theorique de faces:
113 const int_t nb_faces_front = domaine.nb_faces_frontiere() + domaine.nb_faces_joint();
114 int_t nb_faces_prevision = (nb_elements * nb_faces_par_element + nb_faces_front) / 2;
115 if (is_polyedre_)
116 {
117 // les faces sont toutes deja connues....
118 const Poly_geom_base_t& poly=ref_cast(Poly_geom_base_t,ref_domaine_->type_elem().valeur());
119 nb_faces_prevision=(poly.get_somme_nb_faces_elem()+ nb_faces_front) / 2;;
120 }
121 // Allocation memoire pour le nombre de faces prevu pour eviter de reallouer
122 // de la memoire n fois (voir set_smart_resize)
123
124 faces_sommets.resize(nb_faces_prevision, nb_sommets_par_face);
125 faces_sommets.resize(0, nb_sommets_par_face);
126
127 faces_voisins.resize(nb_faces_prevision, 2);
128 faces_voisins.resize(0, 2);
129
130 // ******** Traitement des frontieres **********
131 // attention, on initialise "num_premiere_face" pour les frontieres !
132
133 // Creation des faces de bord
134 {
135 Bords_t& bords = domaine.faces_bord();
136 const int n = bords.size();
137 for (int i = 0; i < n; i++)
138 {
139 Frontiere_t& frontiere = bords[i];
140
141 creer_faces_frontiere(1, /* un element voisin par face */
142 frontiere,
143 faces_sommets,
144 faces_voisins,
145 elem_faces);
146 }
147 }
148// Raccords
149 {
150 Raccords_t& raccords = domaine.faces_raccord();
151 const int n = raccords.size();
152 for (int i = 0; i < n; i++)
153 {
154 Frontiere_t& frontiere = raccords[i].valeur();
155 creer_faces_frontiere(1, /* un element voisin par face */
156 frontiere,
157 faces_sommets,
158 faces_voisins,
159 elem_faces);
160 }
161 }
162
163// Faces de "bord internes"
164 {
165 Bords_Internes_t& faces_int = domaine.bords_int();
166 const int n = faces_int.size();
167 for (int i = 0; i < n; i++)
168 {
169 Frontiere_t& frontiere = faces_int[i];
170 creer_faces_frontiere(2, /* deux elements voisin par face */
171 frontiere,
172 faces_sommets,
173 faces_voisins,
174 elem_faces);
175 }
176
177 // On duplique les faces internes : pour chaque face qui a deux
178 // voisins, on cree une deuxieme face identique avec le deuxieme voisin,
179 // on efface le deuxieme voisin de la face d'origine et on change
180 // la face voisins de deuxieme voisin:
181 if (n > 0)
182 {
183 Cerr << "Faces_builder_32_64<_SIZE_>::creer_faces_reeles not coded for the internal faces of boundary" << finl;
185 // A faire selon l'ancienne version de domaine2... et a tester !
186 }
187 }
188
189// Faces de joint
190 {
191 Joints_t& joints = domaine.faces_joint();
192 const int n = joints.size();
193 for (int i = 0; i < n; i++)
194 {
195 Frontiere_t& frontiere = joints[i];
196 creer_faces_frontiere(2, /* elements voisins par face */
197 frontiere,
198 faces_sommets,
199 faces_voisins,
200 elem_faces);
201 // Remplissage de items_communs(FACE)
202 // Les faces de joint sont dans le meme ordre en local et sur le voisin.
203 Joint_t& joint = joints[i];
204 ArrOfInt_t& indices_faces =
205 joint.set_joint_item(JOINT_ITEM::FACE).set_items_communs();
206 const int_t nb_faces = joint.nb_faces();
207 indices_faces.resize_array(nb_faces);
208 const int_t num_premiere_face = joint.num_premiere_face();
209 for (int_t i2 = 0; i2 < nb_faces; i2++)
210 indices_faces[i2] = num_premiere_face + i2;
211 }
212 }
213
214// *********************************************
215// Faces internes
216
217 creer_faces_internes(faces_sommets,
218 elem_faces,
219 faces_voisins);
220
221
222// Identification des groupes de faces
223 {
224 Groupes_Faces_t& groupes_faces = domaine.groupes_faces();
225 const int n = groupes_faces.size();
226 for (int i = 0; i < n; i++)
227 {
228 Groupe_Faces_t& groupe_faces = groupes_faces[i];
229 identification_groupe_faces(groupe_faces,
230 elem_faces);
231 }
232 }
233// *********************************************
234// C'est fini: on verifie qu'on a bien le nombre de faces prevu
235 if (faces_sommets.dimension(0) != nb_faces_prevision)
236 {
237 Cerr << "Error in Faces_builder_32_64<_SIZE_>::creer_faces_reeles:\n"
238 << " number of faces does not match predicted number of faces.\n"
239 << " (problem with faces_bords_internes ?)" << finl;
241 }
242
243// RAZ attribut smart_resize des tableaux faces_sommets et faces_voisins.
244
245
246// RAZ des attributs de la classe
247 reset();
248}
249
250/*! @brief methode outil pour creer_faces_frontiere et creer_faces_internes (si liste non vide sur au moins un processeur, affiche un message et exit()).
251 *
252 */
253template <typename _SIZE_>
254void Faces_builder_32_64<_SIZE_>::check_erreur_faces(const char * message,
255 const ArrOfInt_t& liste_faces) const
256{
257 const int nmax = 100;
258 int_t n = liste_faces.size_array();
259 if (n > 0)
260 {
261 Cerr << "==========================" << finl;
262 Cerr << "Error!" << finl << message
263 << "\nSee log file of this PE for detailed info."
264 << finl;
266 J << "Error in Faces_builder_32_64<_SIZE_>::creer_faces_*\n"
267 << message << finl;
268 if (n > nmax)
269 {
270 J << "Too many faces to display (" << n << ") display only " << nmax << " first faces" << finl;
271 n = nmax;
272 }
273 int_t i;
274 J << "Display format:\n"
275 << " facenumber = face index in faces_sommet array\n"
276 << " som1..som4 = node index\n"
277 << " elem1 elem2 = neighbouring element number\n"
278 << "facenumber som1 (x1 y1 z1) som2 (x2 y2 z2) [som3 (x3 y3 z3)...] elem1 elem2" << finl;
279 char s[1000];
280 const DoubleTab_t& coord = ref_domaine_->coord_sommets();
281 const IntTab_t& faces = faces_sommets_.valeur();
282 const IntTab_t& face_elem = face_elem_.valeur();
283 const int dim = Objet_U::dimension;
284 const int_t nb_som_faces = faces.dimension(1);
285 for (i = 0; i < n; i++)
286 {
287 char *sptr = s;
288 const int_t iface = liste_faces[i];
289 sptr += snprintf(sptr, 100, "%4ld ",(long) iface);
290 for (int j = 0; j < nb_som_faces; j++)
291 {
292 const int_t isom = faces(iface,j);
293 sptr += snprintf(sptr, 100, "%5ld(", (long)isom);
294 for (int k = 0; k < dim; k++)
295 if (isom!=-1)
296 sptr += snprintf(sptr, 100, "%10.6f", coord(isom, k));
297 sptr += snprintf(sptr, 100, ")");
298 }
299 sptr += snprintf(sptr, 100, "%4ld %4ld", (long)face_elem(iface,0),(long) face_elem(iface,1));
300 J << s << finl;
301 }
302 NettoieNoeuds_t::verifie_noeuds(ref_domaine_.valeur());
304 }
305}
306
307/*! @brief ajoute une face reelle dans faces_sommets et faces_voisins.
308 *
309 */
310template <typename _SIZE_>
311_SIZE_ Faces_builder_32_64<_SIZE_>::ajouter_une_face(const SmallArrOfTID_t& une_face,
312 const int_t elem0,
313 const int_t elem1,
314 IntTab_t& faces_sommets,
315 IntTab_t& faces_voisins)
316{
317 int i;
318 const int_t num_new_face = faces_sommets.dimension(0);
319 const int nb_sommets_par_face = (int)faces_sommets.dimension(1);
320 const int_t new_size = num_new_face + 1;
321
322 assert(une_face.size_array() == nb_sommets_par_face);
323 faces_sommets.resize(new_size, nb_sommets_par_face);
324 for (i = 0; i < nb_sommets_par_face; i++)
325 faces_sommets(num_new_face, i) = une_face[i];
326
327 faces_voisins.resize(new_size, 2);
328 faces_voisins(num_new_face, 0) = elem0;
329 faces_voisins(num_new_face, 1) = elem1;
330
331 return num_new_face;
332}
333
334template <typename _SIZE_>
336 const IntTab& faces_element_ref,
337 const SmallArrOfTID_t& une_face,
338 const int_t elem)
339{
340 const int nb_faces_element = (int)faces_element_ref.dimension(0);
341 const int nb_sommets_par_face = (int)faces_element_ref.dimension(1);
342
343 int i_face, i_som2, i_som;
344 for (i_face = 0; i_face < nb_faces_element; i_face++)
345 {
346 for (i_som = 0; i_som < nb_sommets_par_face; i_som++)
347 {
348 const int sommet_elem_ref = faces_element_ref(i_face, i_som);
349 int_t sommet_domaine ;
350 if (sommet_elem_ref==-1)
351 sommet_domaine=-1;
352 else
353 sommet_domaine = elem_som(elem, sommet_elem_ref);
354 for (i_som2 = 0; i_som2 < nb_sommets_par_face; i_som2++)
355 if (une_face[i_som2] == sommet_domaine) // si sommet trouve, stop
356 break;
357 if (i_som2 == nb_sommets_par_face) // si sommet non trouve, stop
358 break;
359 }
360 if (i_som == nb_sommets_par_face) // si tous les sommets ont ete trouves, stop
361 break;
362 }
363 if (i_face == nb_faces_element) // si face non trouvee
364 return -1;
365 else
366 return i_face;
367}
368
369template <typename _SIZE_>
370const IntTab& Faces_builder_32_64<_SIZE_>::faces_element_reference(int_t elem) const
371{
372 if (is_polyedre_==1)
373 {
374 const Poly_geom_base_t& poly =ref_cast(Poly_geom_base_t,ref_domaine_->type_elem().valeur());
375 IntTab& elem_ref_mod=ref_cast_non_const(IntTab,faces_element_reference_old_);
376 poly.get_tab_faces_sommets_locaux(elem_ref_mod,elem);
377
378 //abort();
379 //return faces_element_reference(0);
380 }
381 return faces_element_reference_old_;
382}
383
384
385/*! @brief Methode outil: on suppose que "une_face" contient les indices des sommets d'une face de l'element d'indice "elem" dans le domaine.
386 *
387 * On cherche quel est le numero de cette face sur l'element
388 * de reference. Si les sommets ne correspondent a aucune face de
389 * l'element, on renvoie -1.
390 *
391 */
392template <typename _SIZE_>
393int Faces_builder_32_64<_SIZE_>::chercher_face_element(const SmallArrOfTID_t& une_face,
394 const int_t elem) const
395{
396 const IntTab_t& elem_som = les_elements();
397 const IntTab& faces_element_ref = faces_element_reference(elem);
398 int i_face = chercher_face_element(elem_som, faces_element_ref, une_face, elem);
399 return i_face;
400}
401
402/*! @brief Insere les faces de la frontiere donnee dans les trois tableaux, a la suite des faces deja presentes dans faces_sommets.
403 *
404 * Remplissage de :
405 * frontiere.num_premiere_face
406 * Completion de :
407 * faces_sommets
408 * elem_faces
409 * faces_voisins
410 *
411 */
412template <typename _SIZE_>
413void Faces_builder_32_64<_SIZE_>::creer_faces_frontiere(const int_t nb_voisins_attendus,
414 Frontiere_t& frontiere,
415 IntTab_t& faces_sommets,
416 IntTab_t& faces_voisins,
417 IntTab_t& elem_faces) const
418{
419 assert(nb_voisins_attendus == 1 || nb_voisins_attendus == 2);
420
421 const Static_Int_Lists_t& som_elem = connectivite_som_elem();
422 const int nb_sommets_par_face = faces_element_reference(0).dimension(0) ? faces_element_reference(0).dimension(1) : 3;
423 const int_t num_premiere_face = faces_sommets.dimension(0);
424 const int_t nb_elem_reels = elem_faces.dimension(0);
425 frontiere.fixer_num_premiere_face(num_premiere_face);
426
427 const Faces_t& faces_frontiere = frontiere.faces();
428 const IntTab_t& sommets_faces_fr = faces_frontiere.les_sommets();
429 const int_t nb_faces = faces_frontiere.nb_faces();
430 SmallArrOfTID_t une_face(nb_sommets_par_face);
431 SmallArrOfTID_t voisins;
432
433 ArrOfInt_t liste_faces_erreur0;
434
435 ArrOfInt_t liste_faces_erreur1;
436
437 ArrOfInt_t liste_faces_erreur2;
438
439 ArrOfInt_t liste_faces_erreur3;
440
441 constexpr bool STOP_FIRST_ERR = false; // set this to true in Debug to stop gdb at the right place.
442
443 int i_face;
444 for (i_face = 0; i_face < nb_faces; i_face++)
445 {
446 {
447 int nb_sommets_par_face_fr= (int)sommets_faces_fr.dimension(1);
448 for (int i = 0; i < std::min(nb_sommets_par_face, nb_sommets_par_face_fr); i++)
449 une_face[i] = sommets_faces_fr(i_face, i);
450 for (int i = std::min(nb_sommets_par_face, nb_sommets_par_face_fr); i < nb_sommets_par_face; i++)
451 une_face[i] = -1;
452 }
453 // Quels sont les elements voisins de cette face ?
454 find_adjacent_elements(som_elem, une_face, voisins);
455 const int_t nb_voisins = voisins.size_array();
456 const int_t elem0 = (nb_voisins > 0) ? voisins[0] : -1;
457 const int_t elem1 = (nb_voisins > 1) ? voisins[1] : -1;
458 const int_t indice_face =
459 ajouter_une_face(une_face, elem0, elem1, faces_sommets, faces_voisins);
460
461 switch(nb_voisins)
462 {
463 case 0:
464 {
465 // Erreur: la face n'a pas de voisin
466 liste_faces_erreur0.append_array(indice_face);
467 if(STOP_FIRST_ERR) Process::exit("A least one face has no neighbor!");
468 break;
469 }
470 case 1:
471 case 2:
472 {
473 if (nb_voisins_attendus == nb_voisins)
474 {
475 int i_voisin;
476 for (i_voisin = 0; i_voisin < nb_voisins; i_voisin++)
477 {
478 const int_t elem = voisins[i_voisin];
479 // Quelle est la face de l'element ?
480 const int i_face_elem = chercher_face_element(une_face, elem);
481 if (i_face_elem >= 0)
482 {
483 // Si c'est un element reel, on associe la face
484 if (elem < nb_elem_reels)
485 {
486 if (elem_faces(elem, i_face_elem) < 0)
487 elem_faces(elem, i_face_elem) = indice_face;
488 else
489 {
490 // Erreur: cette face existe deja (dans cette frontiere ou une autre)
491 liste_faces_erreur3.append_array(indice_face);
492 if(STOP_FIRST_ERR) Process::exit("A face already exists! Was found twice!");
493 }
494 }
495 }
496 else
497 {
498 // Erreur: la face n'est pas une face de l'element.
499 liste_faces_erreur0.append_array(indice_face);
500 if(STOP_FIRST_ERR) Process::exit("A face does not belong to any element!");
501 }
502 }
503 }
504 else
505 {
506 // Erreur, on attendait pas ce nombre de voisins.
507 liste_faces_erreur1.append_array(indice_face);
508 if(STOP_FIRST_ERR) Process::exit("A face has an unexpected number of neighbors!");
509 }
510 break;
511 }
512 default:
513 // Erreur, plus de deux voisins, c'est n'importe quoi...
514 liste_faces_erreur2.append_array(indice_face);
515 if(STOP_FIRST_ERR) Process::exit("A face has more than 2 neighbors!");
516 }
517 }
518 Nom msg;
519 msg = "Boundary \"";
520 msg += frontiere.le_nom();
521 msg += "\" contains faces which do not belong to any element.";
522 check_erreur_faces(msg, liste_faces_erreur0);
523
524 msg = "Boundary \"";
525 msg += frontiere.le_nom();
526 msg += "\" contains faces that belong to ";
527 msg += Nom(3-nb_voisins_attendus);
528 msg += " elements.\n";
529 switch(nb_voisins_attendus)
530 {
531 case 1:
532 msg += "These faces should have only 1 neighbouring element.";
533 break;
534 case 2:
535 msg += "These faces should have 2 neighbouring elements.";
536 break;
537 default:
538 msg = "Internal error.";
539 }
540 if (sub_type(Joint, frontiere))
541 {
542 // Deux sources d'erreur possibles: les faces de joint sont fausses
543 // ou bien le domaine ne contient pas les elements virtuels (il faut
544 // au moins que le domaine contienne les elements virtuels voisins des
545 // faces de joint).
546 msg += "(Error in a Joint object: internal error in the mesh splitter or scatter ? )\n";
547 }
548 check_erreur_faces(msg, liste_faces_erreur1);
549
550 msg = "Boundary \"";
551 msg += frontiere.le_nom();
552 msg += "\" contains faces that belong to more than 2 elements.\n";
553 check_erreur_faces(msg, liste_faces_erreur2);
554
555 msg = "Boundary \"";
556 msg += frontiere.le_nom();
557 msg += "\" contains faces that already exist in another boundary or in this one.\n";
558 check_erreur_faces(msg, liste_faces_erreur3);
559}
560
561/*! @brief Construction des faces interieures au domaine (faces qui ont deux voisins et qui ne sont pas des "faces_bord_internes")
562 *
563 * Les faces de joint ont deja ete creees.
564 *
565 */
566template <typename _SIZE_>
567void Faces_builder_32_64<_SIZE_>::creer_faces_internes(IntTab_t& faces_sommets,
568 IntTab_t& elem_faces,
569 IntTab_t& faces_voisins) const
570{
571 const IntTab_t& elem_som = les_elements();
572 const Static_Int_Lists_t& som_elem = connectivite_som_elem();
573 // const IntTab_t & faces_elem_ref = faces_element_reference();
574 const int_t nb_elem = elem_som.dimension(0);
575 const int nb_faces_par_element = faces_element_reference(0).dimension(0);
576 const int nb_sommets_par_face = nb_faces_par_element ? faces_element_reference(0).dimension(1) : 3;
577
578 // Tableau temporaire dans lequel on stocke les indices des sommets
579 // de la face en cours de traitement
580 SmallArrOfTID_t une_face(nb_sommets_par_face);
581 // Tableau temporaire (liste des elements voisins d'une face)
582 SmallArrOfTID_t voisins;
583
584 // Liste des faces n'ayant qu'un seul voisin et qui ne figurent pas
585 // dans les faces de bord (ce sont des erreurs):
586 ArrOfInt_t liste_faces_frontiere_non_declarees;
587
588 ArrOfInt_t liste_faces_joint_non_declarees;
589
590 // Liste des faces presentant une erreur de connectivite (plus de
591 // deux elements voisins, ou connection a des sommets qui ne
592 // sont pas une face de l'element:
593 ArrOfInt_t liste_faces_erreurs_connectivite;
594
595 constexpr bool STOP_FIRST_ERR = false; // set this to true in Debug to stop gdb at the right place.
596
597 // Boucle sur les elements
598 int_t i_elem;
599 for (i_elem = 0; i_elem < nb_elem; i_elem++)
600 {
601 int i_face;
602 // Boucle sur les faces de l'element
603 for (i_face = 0; i_face < nb_faces_par_element; i_face++)
604 {
605
606 // L'indice de cette face dans le tableau faces_sommets.
607 // Il vaut -1 si la face n'a pas encore ete creee,
608 int_t indice_face = elem_faces(i_elem, i_face);
609
610 // Calcul des indices des sommets de la face dans le domaine:
611 int i;
612 // Attention il ne faut laisser l'appel ici...
613 const IntTab& faces_elem_ref = faces_element_reference(i_elem);
614
615 for (i = 0; i < nb_sommets_par_face; i++)
616 {
617 // indice du sommet sur l'element de reference
618 const int i_som_ref = faces_elem_ref(i_face, i);
619 // indice du sommet dans le domaine
620 if (i_som_ref==-1)
621 une_face[i] = -1;
622 else
623 {
624 const int_t i_som = elem_som(i_elem, i_som_ref);
625 une_face[i] = i_som;
626 }
627 }
628 if (une_face[0]==-1)
629 {
630 // on a une face bidon on ne fait rien
631 elem_faces(i_elem, i_face) = -1;
632 }
633 else
634 {
635 // Recherche des elements voisins de cette face.
636 // Le tableau "voisins" est classe dans l'ordre croissant.
637 find_adjacent_elements(som_elem, une_face, voisins);
638
639 const int_t nb_voisins = voisins.size_array();
640 assert (nb_voisins > 0); // Il devrait au moins y avoir i_elem !!! (ou alors on a une face constitues de -1);
641
642 if (nb_voisins == 1) // ***** La face a 1 voisin ********
643 {
644
645 assert(voisins[0] == i_elem); // L'element voisin est forcement i_elem
646 // Une face ayant un seul element voisin est une face de frontiere.
647 if (indice_face >= 0)
648 {
649 // Ok, c'est normal, les frontieres ont deja ete traitees
650 }
651 else
652 {
653 // Erreur: la face n'existe pas encore. Elle devrait avoir ete
654 // creee a partir des frontieres (creer_faces_frontiere)
655 indice_face = ajouter_une_face(une_face, i_elem, -1,
656 faces_sommets, faces_voisins);
657 liste_faces_frontiere_non_declarees.append_array(indice_face);
658 if(STOP_FIRST_ERR) Process::exit("Non declared face!");
659 }
660
661 }
662 else if (nb_voisins == 2) // ***** La face a 2 voisins ********
663 {
664
665 const int_t elem0 = voisins[0];
666 const int_t elem1 = voisins[1];
667 assert(elem0 < elem1);
668 if (indice_face >= 0)
669 {
670 // La face a deje ete creee.
671 }
672 else
673 {
674 // La face n'existe pas encore.
675 if (elem0 == i_elem)
676 {
677 // Les voisins sont classes: elem0 < elem1
678 // donc c'est la premiere fois qu'on parcourt cette face dans la boucle
679 // sur les elements.
680 indice_face = ajouter_une_face(une_face, elem0, elem1,
681 faces_sommets, faces_voisins);
682
683 // Ou est cette face sur l'element voisin ?
684 const int i_face_elem1 = chercher_face_element(une_face, elem1);
685 if (i_face_elem1 >= 0)
686 {
687 if (elem1 < nb_elem) // Element voisin reel ?
688 elem_faces(elem1, i_face_elem1) = indice_face;
689 }
690 else
691 {
692 // Erreur, les sommets de la face sont des sommets de l'element elem1
693 // mais ne sont pas sur une face de cet element. Erreur de
694 // connectivite du maillage.
695 liste_faces_erreurs_connectivite.append_array(indice_face);
696 if(STOP_FIRST_ERR) Process::exit("Connectivity issue with face!");
697 }
698 if (elem1 >= nb_elem)
699 {
700 // Erreur : le voisin est un element virtuel, cette face
701 // devrait etre dans les faces de joint, donc deja creee.
702 liste_faces_joint_non_declarees.append_array(indice_face);
703 if(STOP_FIRST_ERR) Process::exit("Pb with face: its neighbor is virtual! Should not happen here.");
704 }
705 }
706 else
707 {
708 assert(elem1 == i_elem);
709 indice_face = ajouter_une_face(une_face, elem0, elem1,
710 faces_sommets, faces_voisins);
711 // On aurait deja du creer cette face car elle est voisine de elem0
712 // qui est deja traite (indice plus petit). Si on arrive ici,
713 // c'est que les sommets de "une_face" appartiennent bien a l'elem0,
714 // mais qu'ils ne sont pas sur une face de cet element. C'est une
715 // erreur de connectivite.
716 liste_faces_erreurs_connectivite.append_array(indice_face);
717 if(STOP_FIRST_ERR) Process::exit("Pb with face: connectivity error.");
718 }
719 }
720
721 }
722 else // ***** La face a > 2 voisins ********
723 {
724 if (indice_face < 0)
725 {
726 const int_t elem0 = voisins[0];
727 const int_t elem1 = voisins[1];
728 indice_face = ajouter_une_face(une_face, elem0, elem1,
729 faces_sommets, faces_voisins);
730 }
731 liste_faces_erreurs_connectivite.append_array(indice_face);
732 if(STOP_FIRST_ERR) Process::exit("Pb with face: connectivity error 2.");
733 }
734
735 // Si la face n'existait pas, on l'a creee et on a mis son indice
736 // dans indice_face. Sinon on a trouve l'indice de la face existante.
737 assert(indice_face >= 0);
738 elem_faces(i_elem, i_face) = indice_face; /* WRITE elem_faces */
739 }
740 }
741 }
742
743 // Traitement des erreurs:
744 {
745 const char * const msg1 = "We found faces which belong to one element/cell only and are not declared in any boundary ! You forgot to define at least one boundary in your mesh. Fix your mesh.\n";
746 const char * const msg2 = "Joint faces are incomplete: internal error in the mesh splitter\n";
747 const char * const msg3 = "Connectivity error in the mesh elements. Possible errors:\n- one face of one element belongs to more than 2 elements\n- two element have at least 3 common nodes but these nodes are not faces of these elements\n";
748 check_erreur_faces(msg1, liste_faces_frontiere_non_declarees);
749 check_erreur_faces(msg2, liste_faces_joint_non_declarees);
750 check_erreur_faces(msg3, liste_faces_erreurs_connectivite);
751 }
752}
753
754/*! @brief Identification des groupes de faces specifiees dans le domaine
755 *
756 * Remplissage du tableau indices_faces d'un groupes de faces specifique
757 *
758 */
759template <typename _SIZE_>
760void Faces_builder_32_64<_SIZE_>::identification_groupe_faces(Groupe_Faces_t& groupe_faces,
761 const IntTab_t& elem_faces) const
762{
763 const Static_Int_Lists_t& som_elem = connectivite_som_elem();
764 const int nb_sommets_par_face = faces_element_reference(0).dimension(0) ? faces_element_reference(0).dimension(1) : 3;
765
766 const Faces_t& faces_specifiees = groupe_faces.faces();
767 const IntTab_t& sommets_faces_fr = faces_specifiees.les_sommets();
768 const int_t nb_faces = faces_specifiees.nb_faces();
769 ArrOfInt_t& indices_faces = groupe_faces.get_indices_faces();
770 indices_faces.resize_array(nb_faces);
771
772 SmallArrOfTID_t une_face(nb_sommets_par_face);
773 SmallArrOfTID_t voisins;
774
775 ArrOfInt_t liste_faces_erreur0;
776
777 ArrOfInt_t liste_faces_erreur1;
778
779
780 for (int i_face = 0; i_face < nb_faces; i_face++)
781 {
782 {
783 int nb_sommets_par_face_fr= (int)sommets_faces_fr.dimension(1);
784 for (int i = 0; i < std::min(nb_sommets_par_face, nb_sommets_par_face_fr); i++)
785 une_face[i] = sommets_faces_fr(i_face, i);
786 for (int i = std::min(nb_sommets_par_face, nb_sommets_par_face_fr); i < nb_sommets_par_face; i++)
787 une_face[i] = -1;
788 }
789 // Quels sont les elements voisins de cette face ?
790 find_adjacent_elements(som_elem, une_face, voisins);
791 const int_t nb_voisins = voisins.size_array();
792
793 switch(nb_voisins)
794 {
795 case 0:
796 {
797 // Erreur: la face n'a pas de voisin
798 liste_faces_erreur0.append_array(i_face);
799 break;
800 }
801 case 1:
802 case 2:
803 {
804 const int_t elem = voisins[0];
805 // Quelle est la face de l'element ?
806 const int i_face_elem = chercher_face_element(une_face, elem);
807
808 if (i_face_elem >= 0)
809 // Quel est le numero de la face
810 indices_faces[i_face] = elem_faces(elem,i_face_elem);
811 break;
812 }
813 default:
814 // Erreur, plus de deux voisins, c'est n'importe quoi...
815 liste_faces_erreur1.append_array(i_face);
816 }
817 }
818
819 Nom msg;
820 msg = "Group of Faces \"";
821 msg += groupe_faces.le_nom();
822 msg += "\" contains faces which do not belong to any element or not virtual element.";
823 check_erreur_faces(msg, liste_faces_erreur0);
824
825 msg = "Group of Faces \"";
826 msg += groupe_faces.le_nom();
827 msg += "\" contains faces that belong to more than 2 elements.\n";
828 check_erreur_faces(msg, liste_faces_erreur1);
829}
830
831template class Faces_builder_32_64<int>;
832//#if INT_is_64_ == 2
834//#endif
IntTab_t & voisins()
Renvoie le tableau des voisins (des faces).
Definition Faces.h:89
const IntTab_t & les_sommets() const
Renvoie le tableau des sommets de toutes les faces.
Definition Faces.h:74
classe outil pour construire les faces d'un domaine (utilisee uniquement pour creer les tableau des f...
Joints_32_64< _SIZE_ > Joints_t
IntTab_T< _SIZE_ > IntTab_t
Bords_32_64< _SIZE_ > Bords_t
Frontiere_32_64< _SIZE_ > Frontiere_t
SmallArrOfTID_T< _SIZE_ > SmallArrOfTID_t
Groupes_Faces_32_64< _SIZE_ > Groupes_Faces_t
static int chercher_face_element(const IntTab_t &elem_som, const IntTab &faces_element_ref, const SmallArrOfTID_t &une_face, const int_t elem)
Static_Int_Lists_32_64< _SIZE_ > Static_Int_Lists_t
Faces_32_64< _SIZE_ > Faces_t
Bords_Internes_32_64< _SIZE_ > Bords_Internes_t
ArrOfInt_T< _SIZE_ > ArrOfInt_t
Raccords_32_64< _SIZE_ > Raccords_t
Poly_geom_base_32_64< _SIZE_ > Poly_geom_base_t
Joint_32_64< _SIZE_ > Joint_t
Groupe_Faces_32_64< _SIZE_ > Groupe_Faces_t
void creer_faces_reeles(Domaine_t &domaine, const Static_Int_Lists_t &connect_som_elem, Faces_t &les_faces, IntTab_t &elem_faces)
A partir de la description des elements du domaine et des frontieres (bords, raccords,...
Domaine_32_64< _SIZE_ > Domaine_t
int_t num_premiere_face() const
Definition Frontiere.h:67
int_t nb_faces() const
Renvoie le nombre de faces de la frontiere.
Definition Frontiere.h:59
Joint_Items_t & set_joint_item(JOINT_ITEM type)
Renvoie les informations de joint pour un type d'item geometrique donne, pour remplissage des structu...
Definition Joint.cpp:103
ArrOfInt_t & set_items_communs()
Renvoie le tableau items_communs_ pour le remplir.
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const Nom & le_nom() const override
Renvoie *this;.
Definition Nom.cpp:563
static int dimension
Definition Objet_U.h:99
virtual int_t get_somme_nb_faces_elem() const =0
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
int_t get_nb_lists() const
renvoie le nombre de listes stockees
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133