Arcane  v3.16.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CellMerger.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CellMerger.cc (C) 2000-2025 */
9/* */
10/* Fusionne deux mailles. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/CellMerger.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/TraceInfo.h"
19#include "arcane/utils/CheckedConvert.h"
20#include "arcane/utils/TraceAccessor.h"
21
22#include "arcane/core/Item.h"
24#include "arcane/core/IItemFamily.h"
25#include "arcane/core/IItemFamilyTopologyModifier.h"
26#include "arcane/core/IMesh.h"
27#include "arcane/core/internal/IItemFamilyInternal.h"
28
29#include "arcane/mesh/FaceReorienter.h"
30
31#include <map>
32#include <set>
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37namespace Arcane::mesh
38{
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
44class ItemSwapperUtils
45: public TraceAccessor
46{
47 public:
48
49 explicit ItemSwapperUtils(IMesh* mesh)
50 : TraceAccessor(mesh->traceMng()),
51 m_face_reorienter(mesh),
52 m_cell_tm(mesh->cellFamily()->_internalApi()->topologyModifier()),
53 m_face_tm(mesh->faceFamily()->_internalApi()->topologyModifier()),
54 m_node_tm(mesh->nodeFamily()->_internalApi()->topologyModifier())
55 {
56 }
57 public:
58
65 void swapFaceNodes(Face face_1,Face face_2,
66 Integer face1_node_idx,Integer face2_node_idx)
67 {
68 NodeLocalId face1_node = face_1.node(face1_node_idx);
69 NodeLocalId face2_node = face_2.node(face2_node_idx);
70
71 m_face_tm->replaceNode(face_1,face1_node_idx,face2_node);
72 m_face_tm->replaceNode(face_2,face2_node_idx,face1_node);
73
74 m_node_tm->findAndReplaceFace(face1_node,face_1,face_2);
75 m_node_tm->findAndReplaceFace(face2_node,face_2,face_1);
76 }
77
84 void swapCellNodes(Cell cell1,Cell cell2,
85 Integer cell1_node_idx,Integer cell2_node_idx)
86 {
87 NodeLocalId cell1_node = cell1.node(cell1_node_idx);
88 NodeLocalId cell2_node = cell2.node(cell2_node_idx);
89
90 m_cell_tm->replaceNode(cell1,cell1_node_idx,cell2_node);
91 m_cell_tm->replaceNode(cell2,cell2_node_idx,cell1_node);
92
93 m_node_tm->findAndReplaceCell(cell1_node,cell1,cell2);
94 m_node_tm->findAndReplaceCell(cell2_node,cell2,cell1);
95 }
96
103 void swapCellFaces(Cell cell1,Cell cell2,
104 Integer cell1_face_idx,Integer cell2_face_idx)
105 {
106 FaceLocalId cell1_face = cell1.face(cell1_face_idx);
107 FaceLocalId cell2_face = cell2.face(cell2_face_idx);
108
109 m_cell_tm->replaceFace(cell1,cell1_face_idx,cell2_face);
110 m_cell_tm->replaceFace(cell2,cell2_face_idx,cell1_face);
111
112 m_face_tm->findAndReplaceCell(cell1_face,cell1,cell2);
113 m_face_tm->findAndReplaceCell(cell2_face,cell2,cell1);
114 }
115
116 void checkAndChangeFaceOrientation(Cell cell)
117 {
118 // Ceci pourrait sans doutes etre optimise
119 for( Integer i=0, n=cell.nbFace(); i<n; ++i) {
120 m_face_reorienter.checkAndChangeOrientation(cell.face(i));
121 }
122 }
123
124 private:
125 FaceReorienter m_face_reorienter;
126 IItemFamilyTopologyModifier* m_cell_tm;
127 IItemFamilyTopologyModifier* m_face_tm;
128 IItemFamilyTopologyModifier* m_node_tm;
129};
130
131/*---------------------------------------------------------------------------*/
132/*---------------------------------------------------------------------------*/
141{
142 public:
143 typedef std::set<Integer> NodesLIDSet;
144
145 private:
148
149 NodesLIDSet m_nodes_lid_set;
150
151 public:
157 const NodesLIDSet& nodesLID() const
158 {
159 return m_nodes_lid_set;
160 }
161
169 {
171 }
172
180 {
182 }
183
191 CommonFaceFinder(Cell i_cell_1,Cell i_cell_2);
193};
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
197
199CommonFaceFinder(Cell i_cell_1,Cell i_cell_2)
202{
203 typedef std::map<Integer, Integer> LIDCellMapping;
204 LIDCellMapping faces1; // numero des faces de la maille 1
205 LIDCellMapping faces2; // numero des faces de la maille 2
206
207 { // création des correspondances localId numero dans la maille pour la maille 1
208 Integer n = 0;
209 for( ItemEnumerator i_face(i_cell_1.faces()); i_face(); ++i_face ) {
210 faces1[i_face->localId()] = n;
211 n++;
212 }
213 }
214 { // création des correspondances localId numero dans la maille pour la maille 2
215 Integer n = 0;
216 for( ItemEnumerator i_face(i_cell_2.faces()); i_face(); ++i_face ) {
217 faces2[i_face->localId()] = n;
218 n++;
219 }
220 }
221
222 // On parcours maintenant les deux tables créé précédemment, comme
223 // elles sont triées par localId croissant, on en déduit
224 // simplement la face commune.
225 LIDCellMapping::const_iterator i_face1 = faces1.begin();
226 LIDCellMapping::const_iterator i_face2 = faces2.begin();
227
228 do {
229 const Integer& lid1 = i_face1->first; // localId de la face dans la liste 1
230 const Integer& lid2 = i_face2->first; // localId de la face dans la liste 2
231
232 if (lid1 == lid2) { // on a trouvé la face commune
233 m_cell_1_local_number = i_face1->second;
234 m_cell_2_local_number = i_face2->second;
235
236 // Enregistrement des localId des noeuds de la face commune
237 Face common_face = i_cell_1.face(m_cell_1_local_number);
238
239 for( NodeEnumerator i_node(common_face.nodes()); i_node(); ++i_node) {
240 m_nodes_lid_set.insert(i_node->localId());
241 }
242 return;
243 }
244 else {
245 if (lid1<lid2) {
246 ++i_face1;
247 } else {
248 ++i_face2;
249 }
250 }
251 } while (i_face1 != faces1.end() && i_face2 != faces2.end());
252
253 ARCANE_FATAL("Face commune non trouvée !");
254}
255
256/*---------------------------------------------------------------------------*/
257/*---------------------------------------------------------------------------*/
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
292
294_setFacesNodeNumbers(Face i_face_1,Face i_face_2)
295{
296 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
297 LocalIDToLocalNumber face1_node_localId;
298 LocalIDToLocalNumber face2_node_localId;
299
300 {
301 Integer n = 0;
302 for (ItemEnumerator i_node(i_face_1.nodes()); i_node(); ++i_node) {
303 face1_node_localId[i_node->localId()]=n++;
304 }
305 }
306 {
307 Integer n = 0;
308 for (ItemEnumerator i_node(i_face_2.nodes()); i_node(); ++i_node) {
309 face2_node_localId[i_node->localId()]=n++;
310 }
311 }
312
313 //Integer face2_common_edge_node_number = std::numeric_limits<Integer>::max();
314
315 for (LocalIDToLocalNumber::const_iterator
316 i = face1_node_localId.begin(),
317 j = face2_node_localId.begin();
318 i != face1_node_localId.end() && j != face2_node_localId.end();) {
319 Int32 node1_localId = i->first;
320 Int32 node2_localId = j->first;
321 if (node1_localId == node2_localId) {
324 break;
325 } else {
326 if (node1_localId < node2_localId) {
327 ++i;
328 } else {
329 ++j;
330 }
331 }
332 }
333
335}
336
337/*---------------------------------------------------------------------------*/
338/*---------------------------------------------------------------------------*/
339
341Faces2DMerger(ItemSwapperUtils* swap_utils,Face face1,Face face2)
342: m_face_1_common_node_numbers(std::numeric_limits<Integer>::max())
343, m_face_2_common_node_numbers(std::numeric_limits<Integer>::max())
344, m_face_2_exchanged_node_numbers(std::numeric_limits<Integer>::max())
345{
346 ARCANE_ASSERT(face2.type()==IT_Line2,("The cell is not a line"));
347
348 _setFacesNodeNumbers(face1,face2);
349
350 swap_utils->swapFaceNodes(face1,face2,m_face_1_common_node_numbers,
352}
353
354/*---------------------------------------------------------------------------*/
355/*---------------------------------------------------------------------------*/
361{
362 private:
363
365
372 IntegerUniqueArray m_cell2_edge_face_list;
374
386 IntegerArray& edge_face_list,
387 Integer common_face_number,
388 const CommonFaceFinder::NodesLIDSet& common_face_nodes)
389 {
390 typedef Integer _EdgeDescriptor;
391 typedef std::map<_EdgeDescriptor, Integer> _EdgeFaceList;
392
393 _EdgeFaceList temp_edge_face_list;
394 Integer face_number = 0;
395 // Pour chaque face de la maille
396 for ( FaceEnumerator i_face(i_cell.faces()); i_face(); ++i_face, ++face_number) {
397 if (face_number == common_face_number) {
398 continue; // si la face est la face commune, on ne fait rien
399 }
400
401 // On crée la liste des noeuds de cette face qui sont communs
402 std::multiset<Integer> node_list;
403 for( NodeEnumerator i_node(i_face->nodes()); i_node(); ++i_node) {
404 const Integer& node_lid = i_node->localId();
405 if (common_face_nodes.find(node_lid) != common_face_nodes.end()) {
406 node_list.insert(node_lid);
407 }
408 }
409
410 switch (node_list.size()) {
411 case 0: // la face n'est pas à retailler [déjà traitée]
412 case 2:continue;
413 case 1: { // Si la liste ne contient qu'un élément, c'est que la face est à fusionner
414 std::multiset<Integer>::const_iterator i = node_list.begin();
415 const Integer node_lid = *i;
416 temp_edge_face_list[node_lid] = face_number;
417 break;
418 }
419 default: {
420 ARCANE_FATAL("Unexpected number of nodes on the common face !");
421 }
422 }
423 }
424
425 // On recopie les donnée : on n'a plus besoin des arêtes
426 edge_face_list.reserve((Integer)temp_edge_face_list.size());
427 for (_EdgeFaceList::const_iterator i = temp_edge_face_list.begin();
428 i != temp_edge_face_list.end(); ++i) {
429 edge_face_list.add(i->second); // on stocke les numéros des faces à fusionner
430 }
431 }
432
433 public:
440 {
441 return m_cell1_edge_face_list.size();
442 }
443
452 {
453 return m_cell1_edge_face_list[i];
454 }
455
464 {
465 return m_cell2_edge_face_list[i];
466 }
467
476 const CommonFaceFinder& common_face)
477 {
478 this->_setEdgeFaceList(cell1,
480 common_face.cell1LocalNumber(),
481 common_face.nodesLID());
482 this->_setEdgeFaceList(cell2,
483 m_cell2_edge_face_list,
484 common_face.cell2LocalNumber(),
485 common_face.nodesLID());
486
487 ARCANE_ASSERT(m_cell1_edge_face_list.size() == m_cell2_edge_face_list.size(),
488 ("Incompatible number of 2D faces to merge !"));
489 }
490};
491
492/*---------------------------------------------------------------------------*/
493/*---------------------------------------------------------------------------*/
494
495/*---------------------------------------------------------------------------*/
496/*---------------------------------------------------------------------------*/
502{
503 public:
504
511 {
512 return m_cell1_edge_face_list.size();
513 }
514
523 {
524 return m_cell1_edge_face_list[i];
525 }
526
535 {
536 return m_cell2_edge_face_list[i];
537 }
538
547 const CommonFaceFinder& common_face)
548 {
550 common_face.cell1LocalNumber(),common_face.nodesLID());
551 _setEdgeFaceList(cell2,m_cell2_edge_face_list,
552 common_face.cell2LocalNumber(),common_face.nodesLID());
553
554 ARCANE_ASSERT(m_cell1_edge_face_list.size() == m_cell2_edge_face_list.size(),
555 ("Incompatible number of faces to merge !"));
556 }
557
558 private:
559
561
568 IntegerUniqueArray m_cell2_edge_face_list;
570 void _setEdgeFaceList(Cell i_cell,
571 IntegerArray& edge_face_list,
572 Integer common_face_number,
573 const CommonFaceFinder::NodesLIDSet& common_face_nodes);
574};
575
576/*---------------------------------------------------------------------------*/
577/*---------------------------------------------------------------------------*/
578
591 IntegerArray& edge_face_list,
592 Integer common_face_number,
593 const CommonFaceFinder::NodesLIDSet& common_face_nodes)
594{
595 typedef std::pair<Integer,Integer> _EdgeDescriptor;
596 typedef std::map<_EdgeDescriptor, Integer> _EdgeFaceList;
597
598 _EdgeFaceList temp_edge_face_list; // liste tries des numéros de faces par arêtes
599 Integer face_number = 0;
600 for (FaceEnumerator i_face(i_cell.faces()); i_face(); ++i_face, ++face_number) {
601 if (face_number == common_face_number) { // si la face est la face commune elle n'est pas traitée
602 continue;
603 }
604
605 std::multiset<Integer> node_list; // liste des localIds des noeuds de la face qui sont communs
606 for (NodeEnumerator i_node(i_face->nodes()); i_node(); ++i_node) {
607 Int32 node_lid = i_node->localId();
608 // si le noeud est commun on l'ajoute à la liste des noeuds communs
609 if (common_face_nodes.find(node_lid) != common_face_nodes.end()) {
610 node_list.insert(node_lid);
611 }
612 }
613
614 switch (node_list.size()) {
615 case 0: // la face n'est pas à retailler [déjà traitée]
616 case 4:continue;
617 case 2: {
618 std::multiset<Integer>::const_iterator i = node_list.begin();
619 const Integer first_node_lid = *i;
620 ++i;
621 const Integer second_node_lid = *i;
622 // On crée la correspondance arête/face (les noeuds de l'arête étant triés)
623 temp_edge_face_list[std::make_pair(first_node_lid, second_node_lid)] = face_number;
624 break;
625 }
626 default:
627 ARCANE_FATAL("Unexpected number of nodes on the common face !");
628 }
629 }
630
631 // On recopie les donnée : on n'a plus besoin des arêtes. Les
632 // faces numéros des faces sont orientés comme on le souhaite.
633 edge_face_list.reserve(CheckedConvert::toInteger(temp_edge_face_list.size()));
634 for (_EdgeFaceList::const_iterator i = temp_edge_face_list.begin();
635 i != temp_edge_face_list.end(); ++i) {
636 edge_face_list.add(i->second);
637 }
638}
639
640/*---------------------------------------------------------------------------*/
641/*---------------------------------------------------------------------------*/
673
674/*---------------------------------------------------------------------------*/
675/*---------------------------------------------------------------------------*/
676
678_setFacesNodeNumbers(Face i_face_1,Face i_face_2)
679{
680 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
681 LocalIDToLocalNumber face1_node_localId;
682 LocalIDToLocalNumber face2_node_localId;
683
684 {
685 Integer n = 0;
686 for (NodeEnumerator i_node(i_face_1.nodes()); i_node(); ++i_node) {
687 face1_node_localId[i_node->localId()]=n++;
688 }
689 }
690 {
691 Integer n = 0;
692 for (NodeEnumerator i_node(i_face_2.nodes()); i_node(); ++i_node) {
693 face2_node_localId[i_node->localId()]=n++;
694 }
695 }
696
699
700 std::set<Integer> face2_common_edge_node_number;
701
702 for (LocalIDToLocalNumber::const_iterator
703 i = face1_node_localId.begin(),
704 j = face2_node_localId.begin();
705 i != face1_node_localId.end() && j != face2_node_localId.end();) {
706 const Integer& node1_localId = i->first;
707 const Integer& node2_localId = j->first;
708 if (node1_localId == node2_localId) {
709 m_face_1_common_node_numbers.add(i->second);
710 m_face_2_common_node_numbers.add(j->second);
711 face2_common_edge_node_number.insert(j->second);
712 ++i;++j;
713 } else {
714 if (node1_localId < node2_localId) {
715 ++i;
716 } else {
717 ++j;
718 }
719 }
720 }
721
722 if (m_face_1_common_node_numbers.size() == 0) return false;
723
724 ARCANE_ASSERT((m_face_2_common_node_numbers.size() == 2)
725 && (m_face_1_common_node_numbers.size() == 2),
726 ("Incorrect number of shared vertices"));
727
729 for (Integer i = 0; i<m_face_2_common_node_numbers.size(); ++i) {
730 const Integer& node_number = m_face_2_common_node_numbers[i];
731 for (Integer j=0; j<2; ++j) {
732 const Integer& edge_node = m_quad_node_neighbors[node_number][j];
733 if (face2_common_edge_node_number.find(edge_node) == face2_common_edge_node_number.end()) {
734 m_face_2_exchanged_node_numbers.add(edge_node);
735 break;
736 }
737 }
738 }
739 return true;
740}
741
742
743/*---------------------------------------------------------------------------*/
744/*---------------------------------------------------------------------------*/
745
748{
749 ARCANE_ASSERT(face2.type()==IT_Quad4,("The cell is not a quadrangle"));
750
751 if (_setFacesNodeNumbers(face1,face2)) {
752 ARCANE_ASSERT(m_face_2_exchanged_node_numbers.size() == 2,
753 ("Incorrect number of exchange vertices"));
754
755 // Echange des sommets des faces
756 for (Integer i = 0; i<2; ++i) {
757 swap_utils->swapFaceNodes(face1,face2,m_face_1_common_node_numbers[i],
759 }
760 }
761}
762
763/*---------------------------------------------------------------------------*/
764/*---------------------------------------------------------------------------*/
765
766const Integer
768m_quad_node_neighbors[4][2] = { {1,3},{0,2},{1,3},{0,2} };
769
770/*---------------------------------------------------------------------------*/
771/*---------------------------------------------------------------------------*/
772
773/*---------------------------------------------------------------------------*/
774/*---------------------------------------------------------------------------*/
775
808
809/*---------------------------------------------------------------------------*/
810/*---------------------------------------------------------------------------*/
811
813_setCellsNodeNumbers(Cell i_cell_1,Cell i_cell_2)
814{
815 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
816 LocalIDToLocalNumber cell1_node_localId;
817 LocalIDToLocalNumber cell2_node_localId;
818
819 {
820 Integer n = 0;
821 for (NodeEnumerator i_node(i_cell_1.nodes()); i_node(); ++i_node) {
822 cell1_node_localId[i_node->localId()] = n++;
823 }
824 }
825 {
826 Integer n = 0;
827 for (NodeEnumerator i_node(i_cell_2.nodes()); i_node(); ++i_node) {
828 cell2_node_localId[i_node->localId()] = n++;
829 }
830 }
831
832 std::set<Integer> cell2_common_edge_node_number;
833 for (LocalIDToLocalNumber::const_iterator
834 i = cell1_node_localId.begin(),
835 j = cell2_node_localId.begin();
836 i != cell1_node_localId.end() && j != cell2_node_localId.end();) {
837 const Integer& node1_localId = i->first;
838 const Integer& node2_localId = j->first;
839 if (node1_localId == node2_localId) {
840 m_cell_1_common_node_numbers.add(i->second);
841 m_cell_2_common_node_numbers.add(j->second);
842 cell2_common_edge_node_number.insert(j->second);
843 ++i;++j;
844 }
845 else {
846 if (node1_localId < node2_localId) {
847 ++i;
848 }
849 else {
850 ++j;
851 }
852 }
853 }
854
855 ARCANE_ASSERT(m_cell_1_common_node_numbers.size() == 2,
856 ("Bad number of shared vertices"));
857
859 for (Integer i = 0; i<m_cell_2_common_node_numbers.size(); ++i) {
860 const Integer& node_number = m_cell_2_common_node_numbers[i];
861 for (Integer j=0; j<2; ++j) {
862 const Integer& edge_node = m_quad_node_neighbors[node_number][j];
863 if (cell2_common_edge_node_number.find(edge_node) == cell2_common_edge_node_number.end()) {
864 m_cell_2_exchanged_node_numbers.add(edge_node);
865 break;
866 }
867 }
868 }
869}
870
871/*---------------------------------------------------------------------------*/
872/*---------------------------------------------------------------------------*/
873
876{
877 ARCANE_ASSERT(cell2.type()==IT_Quad4,("Cell2 is not a IT_Quad4"));
878
879 CommonFaceFinder common_face(cell1,cell2);
880
881 this->_setCellsNodeNumbers(cell1,cell2);
882
883 // Fusion des mailles de côté
884 Faces2DToMergeFinder faces_to_merge(cell1,cell2,common_face);
885 for (Integer i = 0; i<faces_to_merge.getNumber(); ++i) {
886 Faces2DMerger(swap_utils,
887 cell1.face(faces_to_merge.cell1FaceNumber(i)),
888 cell2.face(faces_to_merge.cell2FaceNumber(i)));
889 }
890
891 // Echange des faces.
892 swap_utils->swapCellFaces(cell1,cell2,
893 common_face.cell1LocalNumber(),
894 (common_face.cell2LocalNumber()+2)%4); // face opposée
895
896 // Echange des sommets des mailles
897 for (Integer i=0, n=m_cell_1_common_node_numbers.size(); i<n; ++i) {
898 swap_utils->swapCellNodes(cell1,cell2,
901 }
902
903 swap_utils->checkAndChangeFaceOrientation(cell1);
904}
905
906/*---------------------------------------------------------------------------*/
907/*---------------------------------------------------------------------------*/
908
910= { {1,3},{0,2},{1,3},{0,2} };
911
912/*---------------------------------------------------------------------------*/
913/*---------------------------------------------------------------------------*/
945
946/*---------------------------------------------------------------------------*/
947/*---------------------------------------------------------------------------*/
948
950_setCellsNodeNumbers(Cell cell1,Cell cell2)
951{
952 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
953 LocalIDToLocalNumber cell1_node_localId;
954 LocalIDToLocalNumber cell2_node_localId;
955
956 // On associe les numéros (dans la maille) des noeuds à leur
957 // localId. Ces listes sont triées par localId !
958 {
959 // d'abord pour la maille 1
960 Integer n = 0;
961 for (NodeEnumerator i_node(cell1.nodes()); i_node(); ++i_node) {
962 cell1_node_localId[i_node->localId()] = n++;
963 }
964 }
965 {
966 // puis pour la maille 2
967 Integer n = 0;
968 for (NodeEnumerator i_node(cell2.nodes()); i_node(); ++i_node) {
969 cell2_node_localId[i_node->localId()] = n++;
970 }
971 }
972
973 // On determine ensuite l'ensemble des noeuds communs aux deux
974 // mailles
975 std::set<Integer> cell2_common_edge_node_number;
976 for (LocalIDToLocalNumber::const_iterator
977 i = cell1_node_localId.begin(),
978 j = cell2_node_localId.begin();
979 i != cell1_node_localId.end() && j != cell2_node_localId.end();) {
980 Integer node1_localId = i->first;
981 Integer node2_localId = j->first;
982 if (node1_localId == node2_localId) { // si les noeuds sont les mêmes
983 // on stockes les numéros dans la mailles de ces sommets
984 m_cell_1_common_node_numbers.add(i->second); // pour la maille 1
985 m_cell_2_common_node_numbers.add(j->second); // pour la maille 2
986
987 // et on crée l'ensemble ordonné des noeuds communs dans la
988 // seconde maille
989 cell2_common_edge_node_number.insert(j->second);
990 ++i;++j;
991 } else {
992 if (node1_localId < node2_localId) {
993 ++i;
994 } else {
995 ++j;
996 }
997 }
998 }
999
1000 ARCANE_ASSERT(m_cell_1_common_node_numbers.size() == 4,
1001 ("Bad number of shared vertices"));
1002
1003 // On cherche maintenant les sommets voisins des noeuds commun
1004 // appartenant à la seconde maille et qui ne sont pas des sommets
1005 // échangés. Ce sont les sommets qui formeront la nouvelle maille
1006 // par substitution avec les sommets communs de la première maille.
1008 for (Integer i = 0; i<m_cell_2_common_node_numbers.size(); ++i) {
1009 const Integer& node_number = m_cell_2_common_node_numbers[i];
1010 for (Integer j=0; j<3; ++j) {
1011 const Integer& edge_node = m_hexa_node_neighbors[node_number][j];
1012 if (cell2_common_edge_node_number.find(edge_node) == cell2_common_edge_node_number.end()) {
1013 m_cell_2_exchanged_node_numbers.add(edge_node);
1014 break;
1015 }
1016 }
1017 }
1018}
1019
1020/*---------------------------------------------------------------------------*/
1021/*---------------------------------------------------------------------------*/
1022
1024CellToHexahedronMerger(ItemSwapperUtils* swap_utils,Cell cell1,Cell cell2)
1025{
1026 // TODO: fusionner ce code avec CellToQuadrilateralMerger.
1027
1028 ARCANE_ASSERT(cell2.type() == IT_Hexaedron8,("Cell2 is not a IT_Hexaedron8"));
1029
1030 CommonFaceFinder common_face(cell1,cell2);
1031
1032 this->_setCellsNodeNumbers(cell1,cell2);
1033
1034 // Fusion des mailles de côté
1035 FacesToMergeFinder faces_to_merge(cell1,cell2,common_face);
1036 for (Integer i = 0; i<faces_to_merge.getNumber(); ++i) {
1037 FaceToQuadrilateralMerger(swap_utils,
1038 cell1.face(faces_to_merge.cell1FaceNumber(i)),
1039 cell2.face(faces_to_merge.cell2FaceNumber(i)));
1040 }
1041
1042 // Echange des faces.
1043 swap_utils->swapCellFaces(cell1,cell2,
1044 common_face.cell1LocalNumber(),
1045 (common_face.cell2LocalNumber()+3)%6); // face opposée
1046
1047 // Echange des sommets des mailles
1048 for (Integer i=0, n=m_cell_1_common_node_numbers.size(); i<n; ++i) {
1049 swap_utils->swapCellNodes(cell1,cell2,
1052 }
1053
1054 swap_utils->checkAndChangeFaceOrientation(cell1);
1055}
1056
1057/*---------------------------------------------------------------------------*/
1058/*---------------------------------------------------------------------------*/
1059
1060const Integer
1062m_hexa_node_neighbors[8][3] = { {1,3,4},{0,2,5},{1,3,6},{0,2,7},{0,5,7},{1,4,6},{2,5,7},{3,4,6} };
1063
1064/*---------------------------------------------------------------------------*/
1065/*---------------------------------------------------------------------------*/
1066
1068_typeName(const CellMerger::_Type& t) const
1069{
1070 switch (t) {
1071 case Hexahedron: return "hexahèdre";
1072 case Pyramid: return "pyramide";
1073 case Pentahedron: return "pentahèdre";
1074 case Quadrilateral: return "quadrangle";
1075 case Triangle: return "triangle";
1076 default: return "inconnu";
1077 }
1078}
1079
1080/*---------------------------------------------------------------------------*/
1081/*---------------------------------------------------------------------------*/
1082
1084_getCellType(const Integer& internal_cell_type) const
1085{
1086 switch(internal_cell_type) {
1087 case IT_Hexaedron8: {
1088 return Hexahedron;
1089 }
1090 case IT_Pyramid5: {
1091 return Pyramid;
1092 }
1093 case IT_Pentaedron6: {
1094 return Pentahedron;
1095 }
1096 case IT_Quad4: {
1097 return Quadrilateral;
1098 }
1099 case IT_Triangle3: {
1100 return Triangle;
1101 }
1102 default: {
1103 return NotMergeable;
1104 }
1105 }
1106}
1107
1108/*---------------------------------------------------------------------------*/
1109/*---------------------------------------------------------------------------*/
1110
1112_promoteType(const _Type& t1,const _Type& t2) const
1113{
1114 switch(t1*t2) {
1115 case 1: return Hexahedron;
1116 case 2: return Pyramid;
1117 case 3: return Pentahedron;
1118 case 100: return Quadrilateral;
1119 case 110: return Triangle;
1120 default:
1121 ARCANE_FATAL("Can not merge cells of type {0} and {1}",_typeName(t1),_typeName(t2));
1122 }
1123}
1124
1125/*---------------------------------------------------------------------------*/
1126/*---------------------------------------------------------------------------*/
1127
1129merge(Cell i_cell_1,Cell i_cell_2)
1130{
1131 _Type cell_1_type = _getCellType(i_cell_1.type());
1132 IMesh* mesh = i_cell_1.itemFamily()->mesh();
1133 ItemSwapperUtils swap_utils(mesh);
1134
1135 switch (cell_1_type) {
1136 case Hexahedron:
1137 case Pyramid:
1138 case Pentahedron:
1139 {
1140 CellToHexahedronMerger(&swap_utils,i_cell_1, i_cell_2);
1141 return;
1142 }
1143 case Quadrilateral:
1144 case Triangle:{
1145 {
1146 CellToQuadrilateralMerger(&swap_utils,i_cell_1,i_cell_2);
1147 return;
1148 }
1149 }
1150 case NotMergeable: {
1151 ARCANE_FATAL("Impossible to merge the entities !\n");
1152 }
1153 }
1154 ARCANE_FATAL("Merge for this kind of cell not implemented\n");
1155}
1156
1157/*---------------------------------------------------------------------------*/
1158/*---------------------------------------------------------------------------*/
1159
1161getCell(Cell i_cell_1,Cell i_cell_2)
1162{
1163 _Type cell_1_type = _getCellType(i_cell_1.type());
1164 _Type cell_2_type = _getCellType(i_cell_2.type());
1165
1166 _Type merged_cell_type = _promoteType(cell_1_type, cell_2_type);
1167
1168 switch (merged_cell_type) {
1169 case Hexahedron: {
1170 return i_cell_1;
1171 }
1172 case Pyramid:
1173 case Pentahedron: {
1174 if (cell_2_type == Hexahedron) {
1175 return i_cell_1;
1176 } else {
1177 return i_cell_2;
1178 }
1179 }
1180 case Quadrilateral: {
1181 return i_cell_1;
1182 }
1183 case Triangle: {
1184 if (cell_2_type == Quadrilateral) {
1185 return i_cell_1;
1186 } else {
1187 return i_cell_2;
1188 }
1189 }
1190 case NotMergeable: {
1191 ARCANE_FATAL("Impossible to merge the entities !\n");
1192 }
1193 default:
1194 ARCANE_FATAL("Merge for this kind of cell not implemented\n");
1195 }
1196 return 0;
1197}
1198
1199/*---------------------------------------------------------------------------*/
1200/*---------------------------------------------------------------------------*/
1201
1203getItemInternal(ItemInternal* i_cell_1, ItemInternal* i_cell_2)
1204{
1205 return ItemCompatibility::_itemInternal(getCell(i_cell_1,i_cell_2));
1206}
1207
1208/*---------------------------------------------------------------------------*/
1209/*---------------------------------------------------------------------------*/
1210
1211} // End namespace Arcane::mesh
1212
1213/*---------------------------------------------------------------------------*/
1214/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Maille d'un maillage.
Definition Item.h:1191
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1272
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1269
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1266
ARCANE_DEPRECATED_260 void checkAndChangeOrientation(ItemInternal *face)
Face d'une maille.
Definition Item.h:944
virtual IMesh * mesh() const =0
Maillage associé
Enumérateur sur une liste d'entités.
Structure interne d'une entité de maillage.
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:779
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:782
IItemFamily * itemFamily() const
Famille dont est issue l'entité
Definition Item.h:247
Int16 type() const
Type de l'entité
Definition Item.h:241
Chaîne de caractères unicode.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
_Type _getCellType(const Integer &internal_cell_type) const
Détermine le _Type de la maille en fonction de son type "ItemInternal".
String _typeName(const _Type &t) const
Retourne le nom associé à type de maille.
void merge(Cell i_cell_1, Cell i_cell_2)
Effectue la fusion des deux mailles i_cell_1 et i_cell_2.
ItemInternal * getItemInternal(ItemInternal *i_cell_1, ItemInternal *i_cell_2)
Retourne l'ItemInteral utilisé par la maille après fusion.
_Type _promoteType(const _Type &t1, const _Type &t2) const
Cell getCell(Cell i_cell_1, Cell i_cell_2)
Retourne la maille utilisé par la maille après fusion.
Cette fonction-classe a pour but de fusionner deux mailles dont la deuxième est forcément un hexahèdr...
void _setCellsNodeNumbers(Cell cell1, Cell cell2)
static const Integer m_hexa_node_neighbors[8][3]
IntegerUniqueArray m_cell_2_exchanged_node_numbers
IntegerUniqueArray m_cell_1_common_node_numbers
IntegerUniqueArray m_cell_2_common_node_numbers
CellToHexahedronMerger(ItemSwapperUtils *swap_utils, Cell cell1, Cell cell2)
static const Integer m_quad_node_neighbors[4][2]
Liste des noeuds voisins par arête dans un quadrangle.
void _setCellsNodeNumbers(Cell i_cell_1, Cell i_cell_2)
IntegerUniqueArray m_cell_2_exchanged_node_numbers
Numéros dans la maille 2 des sommets qui définiront la maille fusionnée.
IntegerUniqueArray m_cell_2_common_node_numbers
Numéros dans la maille 2 des sommets communs avec la maille 1.
CellToQuadrilateralMerger(ItemSwapperUtils *swap_utils, Cell cell1, Cell cell2)
IntegerUniqueArray m_cell_1_common_node_numbers
Numéros dans la maille 1 des sommets communs avec la maille 2.
Recherche la face commune à deux mailles.
Integer m_cell_2_local_number
Numéro de la face commune dans la maille 2.
Integer m_cell_1_local_number
Numéro de la face commune dans la maille 1.
CommonFaceFinder(Cell i_cell_1, Cell i_cell_2)
const NodesLIDSet & nodesLID() const
Ensemble des localId des sommets en communs.
Cett fonction-classe a pour but de fusionner deux faces dont la deuxième est forcément un quadrangle.
IntegerUniqueArray m_face_2_exchanged_node_numbers
IntegerUniqueArray m_face_2_common_node_numbers
bool _setFacesNodeNumbers(Face i_face_1, Face i_face_2)
static const Integer m_quad_node_neighbors[4][2]
IntegerUniqueArray m_face_1_common_node_numbers
FaceToQuadrilateralMerger(ItemSwapperUtils *swap_utils, Face face1, Face face2)
Fusionne deux faces en 2D (en fait deux arêtes).
void _setFacesNodeNumbers(Face i_face_1, Face i_face_2)
Faces2DMerger(ItemSwapperUtils *swap_utils, Face i_face_1, Face i_face_2)
En dimension 2, recherche des faces communes à deux mailles (Les faces sont en fait des arêtes).
Integer cell1FaceNumber(Integer i) const
Integer cell2FaceNumber(Integer i) const
IntegerUniqueArray m_cell1_edge_face_list
void _setEdgeFaceList(Cell i_cell, IntegerArray &edge_face_list, Integer common_face_number, const CommonFaceFinder::NodesLIDSet &common_face_nodes)
Faces2DToMergeFinder(Cell cell1, Cell cell2, const CommonFaceFinder &common_face)
Cette fonction-classe recherche les faces à fusionner lors de la fusion de deux mailles.
Integer cell1FaceNumber(Integer i) const
Integer cell2FaceNumber(Integer i) const
IntegerUniqueArray m_cell1_edge_face_list
void _setEdgeFaceList(Cell i_cell, IntegerArray &edge_face_list, Integer common_face_number, const CommonFaceFinder::NodesLIDSet &common_face_nodes)
FacesToMergeFinder(Cell cell1, Cell cell2, const CommonFaceFinder &common_face)
Classe utilitaire pour échanger des entités entre deux entités.
Definition CellMerger.cc:46
void swapFaceNodes(Face face_1, Face face_2, Integer face1_node_idx, Integer face2_node_idx)
Échange deux noeuds entre deux faces.
Definition CellMerger.cc:65
void swapCellFaces(Cell cell1, Cell cell2, Integer cell1_face_idx, Integer cell2_face_idx)
Échange deux faces entre deux mailles.
void swapCellNodes(Cell cell1, Cell cell2, Integer cell1_node_idx, Integer cell2_node_idx)
Échange deux noeuds entre deux mailles.
Definition CellMerger.cc:84
ItemEnumeratorT< Node > NodeEnumerator
Enumérateurs sur des noeuds.
Definition ItemTypes.h:254
ItemEnumeratorT< Face > FaceEnumerator
Enumérateurs sur des faces.
Definition ItemTypes.h:265
Integer toInteger(Real r)
Converti un Int64 en un Integer.
Int32 Integer
Type représentant un entier.
Array< Integer > IntegerArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:220
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:434
std::int32_t Int32
Type entier signé sur 32 bits.