14#include "arcane/mesh/CellMerger.h"
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"
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"
29#include "arcane/mesh/FaceReorienter.h"
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())
69 NodeLocalId face1_node = face_1.
node(face1_node_idx);
70 NodeLocalId face2_node = face_2.
node(face2_node_idx);
72 m_face_tm->replaceNode(face_1, face1_node_idx, face2_node);
73 m_face_tm->replaceNode(face_2, face2_node_idx, face1_node);
75 m_node_tm->findAndReplaceFace(face1_node, face_1, face_2);
76 m_node_tm->findAndReplaceFace(face2_node, face_2, face_1);
88 NodeLocalId cell1_node = cell1.
node(cell1_node_idx);
89 NodeLocalId cell2_node = cell2.
node(cell2_node_idx);
91 m_cell_tm->replaceNode(cell1, cell1_node_idx, cell2_node);
92 m_cell_tm->replaceNode(cell2, cell2_node_idx, cell1_node);
94 m_node_tm->findAndReplaceCell(cell1_node, cell1, cell2);
95 m_node_tm->findAndReplaceCell(cell2_node, cell2, cell1);
107 FaceLocalId cell1_face = cell1.
face(cell1_face_idx);
108 FaceLocalId cell2_face = cell2.
face(cell2_face_idx);
110 m_cell_tm->replaceFace(cell1, cell1_face_idx, cell2_face);
111 m_cell_tm->replaceFace(cell2, cell2_face_idx, cell1_face);
113 m_face_tm->findAndReplaceCell(cell1_face, cell1, cell2);
114 m_face_tm->findAndReplaceCell(cell2_face, cell2, cell1);
117 void checkAndChangeFaceOrientation(
Cell cell)
127 FaceReorienter m_face_reorienter;
128 IItemFamilyTopologyModifier* m_cell_tm;
129 IItemFamilyTopologyModifier* m_face_tm;
130 IItemFamilyTopologyModifier* m_node_tm;
146 typedef std::set<Integer> NodesLIDSet;
153 NodesLIDSet m_nodes_lid_set;
164 return m_nodes_lid_set;
207 typedef std::map<Integer, Integer> LIDCellMapping;
208 LIDCellMapping faces1;
209 LIDCellMapping faces2;
214 faces1[i_face->localId()] = n;
221 faces2[i_face->localId()] = n;
229 LIDCellMapping::const_iterator i_face1 = faces1.begin();
230 LIDCellMapping::const_iterator i_face2 = faces2.begin();
233 const Integer& lid1 = i_face1->first;
234 const Integer& lid2 = i_face2->first;
244 m_nodes_lid_set.insert(i_node->localId());
256 }
while (i_face1 != faces1.end() && i_face2 != faces2.end());
303 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
304 LocalIDToLocalNumber face1_node_localId;
305 LocalIDToLocalNumber face2_node_localId;
310 face1_node_localId[i_node->localId()] = n++;
316 face2_node_localId[i_node->localId()] = n++;
322 for (LocalIDToLocalNumber::const_iterator
323 i = face1_node_localId.begin(),
324 j = face2_node_localId.begin();
325 i != face1_node_localId.end() && j != face2_node_localId.end();) {
326 Int32 node1_localId = i->first;
327 Int32 node2_localId = j->first;
328 if (node1_localId == node2_localId) {
334 if (node1_localId < node2_localId) {
355 ARCANE_ASSERT(face2.
type() == IT_Line2, (
"The cell is not a line"));
397 const CommonFaceFinder::NodesLIDSet& common_face_nodes)
399 typedef Integer _EdgeDescriptor;
400 typedef std::map<_EdgeDescriptor, Integer> _EdgeFaceList;
402 _EdgeFaceList temp_edge_face_list;
406 if (face_number == common_face_number) {
411 std::multiset<Integer> node_list;
412 for (
NodeEnumerator i_node(i_face->nodes()); i_node(); ++i_node) {
413 const Integer& node_lid = i_node->localId();
414 if (common_face_nodes.find(node_lid) != common_face_nodes.end()) {
415 node_list.insert(node_lid);
419 switch (node_list.size()) {
424 std::multiset<Integer>::const_iterator i = node_list.begin();
426 temp_edge_face_list[node_lid] = face_number;
430 ARCANE_FATAL(
"Unexpected number of nodes on the common face !");
437 for (_EdgeFaceList::const_iterator i = temp_edge_face_list.begin();
438 i != temp_edge_face_list.end(); ++i) {
439 edge_face_list.
add(i->second);
476 return m_cell2_edge_face_list[i];
494 m_cell2_edge_face_list,
499 (
"Incompatible number of 2D faces to merge !"));
548 return m_cell2_edge_face_list[i];
567 (
"Incompatible number of faces to merge !"));
585 const CommonFaceFinder::NodesLIDSet& common_face_nodes);
605 const CommonFaceFinder::NodesLIDSet& common_face_nodes)
607 typedef std::pair<Integer, Integer> _EdgeDescriptor;
608 typedef std::map<_EdgeDescriptor, Integer> _EdgeFaceList;
610 _EdgeFaceList temp_edge_face_list;
613 if (face_number == common_face_number) {
617 std::multiset<Integer> node_list;
618 for (
NodeEnumerator i_node(i_face->nodes()); i_node(); ++i_node) {
619 Int32 node_lid = i_node->localId();
621 if (common_face_nodes.find(node_lid) != common_face_nodes.end()) {
622 node_list.insert(node_lid);
626 switch (node_list.size()) {
631 std::multiset<Integer>::const_iterator i = node_list.begin();
632 const Integer first_node_lid = *i;
634 const Integer second_node_lid = *i;
636 temp_edge_face_list[std::make_pair(first_node_lid, second_node_lid)] = face_number;
640 ARCANE_FATAL(
"Unexpected number of nodes on the common face !");
646 edge_face_list.
reserve(CheckedConvert::toInteger(temp_edge_face_list.size()));
647 for (_EdgeFaceList::const_iterator i = temp_edge_face_list.begin();
648 i != temp_edge_face_list.end(); ++i) {
649 edge_face_list.
add(i->second);
695 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
696 LocalIDToLocalNumber face1_node_localId;
697 LocalIDToLocalNumber face2_node_localId;
702 face1_node_localId[i_node->localId()] = n++;
708 face2_node_localId[i_node->localId()] = n++;
715 std::set<Integer> face2_common_edge_node_number;
717 for (LocalIDToLocalNumber::const_iterator
718 i = face1_node_localId.begin(),
719 j = face2_node_localId.begin();
720 i != face1_node_localId.end() && j != face2_node_localId.end();) {
721 const Integer& node1_localId = i->first;
722 const Integer& node2_localId = j->first;
723 if (node1_localId == node2_localId) {
726 face2_common_edge_node_number.insert(j->second);
731 if (node1_localId < node2_localId) {
744 (
"Incorrect number of shared vertices"));
749 for (
Integer j = 0; j < 2; ++j) {
751 if (face2_common_edge_node_number.find(edge_node) == face2_common_edge_node_number.end()) {
766 ARCANE_ASSERT(face2.
type() == IT_Quad4, (
"The cell is not a quadrangle"));
770 (
"Incorrect number of exchange vertices"));
773 for (
Integer i = 0; i < 2; ++i) {
833 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
834 LocalIDToLocalNumber cell1_node_localId;
835 LocalIDToLocalNumber cell2_node_localId;
840 cell1_node_localId[i_node->localId()] = n++;
846 cell2_node_localId[i_node->localId()] = n++;
850 std::set<Integer> cell2_common_edge_node_number;
851 for (LocalIDToLocalNumber::const_iterator
852 i = cell1_node_localId.begin(),
853 j = cell2_node_localId.begin();
854 i != cell1_node_localId.end() && j != cell2_node_localId.end();) {
855 const Integer& node1_localId = i->first;
856 const Integer& node2_localId = j->first;
857 if (node1_localId == node2_localId) {
860 cell2_common_edge_node_number.insert(j->second);
865 if (node1_localId < node2_localId) {
875 (
"Bad number of shared vertices"));
880 for (
Integer j = 0; j < 2; ++j) {
882 if (cell2_common_edge_node_number.find(edge_node) == cell2_common_edge_node_number.end()) {
896 ARCANE_ASSERT(cell2.
type() == IT_Quad4, (
"Cell2 is not a IT_Quad4"));
922 swap_utils->checkAndChangeFaceOrientation(cell1);
973 typedef std::map<Integer, Integer> LocalIDToLocalNumber;
974 LocalIDToLocalNumber cell1_node_localId;
975 LocalIDToLocalNumber cell2_node_localId;
983 cell1_node_localId[i_node->localId()] = n++;
990 cell2_node_localId[i_node->localId()] = n++;
996 std::set<Integer> cell2_common_edge_node_number;
997 for (LocalIDToLocalNumber::const_iterator
998 i = cell1_node_localId.begin(),
999 j = cell2_node_localId.begin();
1000 i != cell1_node_localId.end() && j != cell2_node_localId.end();) {
1001 Integer node1_localId = i->first;
1002 Integer node2_localId = j->first;
1003 if (node1_localId == node2_localId) {
1010 cell2_common_edge_node_number.insert(j->second);
1015 if (node1_localId < node2_localId) {
1025 (
"Bad number of shared vertices"));
1034 for (
Integer j = 0; j < 3; ++j) {
1036 if (cell2_common_edge_node_number.find(edge_node) == cell2_common_edge_node_number.end()) {
1052 ARCANE_ASSERT(cell2.
type() == IT_Hexaedron8, (
"Cell2 is not a IT_Hexaedron8"));
1078 swap_utils->checkAndChangeFaceOrientation(cell1);
1086m_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 } };
1096 return "hexahedron";
1100 return "pentahedron";
1102 return "quadrangle";
1116 switch (internal_cell_type) {
1117 case IT_Hexaedron8: {
1123 case IT_Pentaedron6: {
1127 return Quadrilateral;
1129 case IT_Triangle3: {
1133 return NotMergeable;
1152 return Quadrilateral;
1170 switch (cell_1_type) {
1184 case NotMergeable: {
1188 ARCANE_FATAL(
"Merge for this kind of cell not implemented\n");
1202 switch (merged_cell_type) {
1208 if (cell_2_type == Hexahedron) {
1215 case Quadrilateral: {
1219 if (cell_2_type == Quadrilateral) {
1226 case NotMergeable: {
1230 ARCANE_FATAL(
"Merge for this kind of cell not implemented\n");
1241 return ItemCompatibility::_itemInternal(
getCell(i_cell_1, i_cell_2));
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
void add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
FaceConnectedListViewType faces() const
List of faces of the cell.
Face face(Int32 i) const
i-th face of the cell
Int32 nbFace() const
Number of faces of the cell.
ARCANE_DEPRECATED_260 void checkAndChangeOrientation(ItemInternal *face)
virtual IMesh * mesh() const =0
Associated mesh.
Internal structure of a mesh entity.
Node node(Int32 i) const
i-th node of the entity
NodeConnectedListViewType nodes() const
List of nodes of the entity.
IItemFamily * itemFamily() const
Family from which the entity originates.
Int16 type() const
Entity type.
Unicode character string.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
_Type _getCellType(const Integer &internal_cell_type) const
Determines the cell _Type based on its "ItemInternal" type.
String _typeName(const _Type &t) const
Returns the name associated with the cell type.
void merge(Cell i_cell_1, Cell i_cell_2)
Merges the two cells i_cell_1 and i_cell_2.
ItemInternal * getItemInternal(ItemInternal *i_cell_1, ItemInternal *i_cell_2)
Returns the ItemInternal used by the cell after merging.
_Type _promoteType(const _Type &t1, const _Type &t2) const
Determines the cell type resulting from the merging of two given types.
Cell getCell(Cell i_cell_1, Cell i_cell_2)
Returns the cell used by the cell after merging.
This function-class aims to merge two cells where the second one is necessarily a hexahedron.
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]
List of neighboring nodes by edge in a quadrangle.
void _setCellsNodeNumbers(Cell i_cell_1, Cell i_cell_2)
IntegerUniqueArray m_cell_2_exchanged_node_numbers
Numbers in cell 2 of the vertices that will define the merged cell.
IntegerUniqueArray m_cell_2_common_node_numbers
Numbers in cell 2 of the common vertices with cell 1.
CellToQuadrilateralMerger(ItemSwapperUtils *swap_utils, Cell cell1, Cell cell2)
IntegerUniqueArray m_cell_1_common_node_numbers
Numbers in cell 1 of the common vertices with cell 2.
Finds the common face between two cells.
Integer m_cell_2_local_number
Number of the common face in cell 2.
Integer cell2LocalNumber() const
Integer m_cell_1_local_number
Number of the common face in cell 1.
CommonFaceFinder(Cell i_cell_1, Cell i_cell_2)
const NodesLIDSet & nodesLID() const
Set of localIds of common nodes.
Integer cell1LocalNumber() const
This function-class aims to merge two faces, where the second is necessarily a 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)
Merges two faces in 2D (in fact, two edges).
Integer m_face_2_exchanged_node_numbers
Integer m_face_2_common_node_numbers
Integer m_face_1_common_node_numbers
void _setFacesNodeNumbers(Face i_face_1, Face i_face_2)
Faces2DMerger(ItemSwapperUtils *swap_utils, Face i_face_1, Face i_face_2)
In dimension 2, finds common faces between two cells (The faces are actually edges).
Integer cell1FaceNumber(Integer i) const
Integer cell2FaceNumber(Integer i) const
Integer getNumber() 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)
This function-class searches for faces to merge when merging two cells.
Integer cell1FaceNumber(Integer i) const
Integer cell2FaceNumber(Integer i) const
Integer getNumber() 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)
Utility class for swapping entities between two entities.
void swapFaceNodes(Face face_1, Face face_2, Integer face1_node_idx, Integer face2_node_idx)
Swaps two nodes between two faces.
void swapCellFaces(Cell cell1, Cell cell2, Integer cell1_face_idx, Integer cell2_face_idx)
Swaps two faces between two cells.
void swapCellNodes(Cell cell1, Cell cell2, Integer cell1_node_idx, Integer cell2_node_idx)
Swaps two nodes between two cells.
ItemEnumeratorT< Node > NodeEnumerator
Enumerators over nodes.
ItemEnumeratorT< Face > FaceEnumerator
Enumerators over faces.
Int32 Integer
Type representing an integer.
Array< Integer > IntegerArray
Dynamic one-dimensional array of integers.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
std::int32_t Int32
Signed integer type of 32 bits.