Arcane  v3.16.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshNodeMerger.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/* MeshNodeMerger.cc (C) 2000-2025 */
9/* */
10/* Fusions de noeuds d'un maillage. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/FatalErrorException.h"
15#include "arcane/utils/NotImplementedException.h"
16#include "arcane/utils/ArgumentException.h"
17
18#include "arcane/core/IMesh.h"
20#include "arcane/core/IMeshModifier.h"
22#include "arcane/core/ItemPrinter.h"
23#include "arcane/core/Connectivity.h"
24
25#include "arcane/mesh/MeshNodeMerger.h"
26#include "arcane/mesh/FaceReorienter.h"
27#include "arcane/mesh/ItemTools.h"
28#include "arcane/mesh/NodeFamily.h"
29#include "arcane/mesh/EdgeFamily.h"
30#include "arcane/mesh/FaceFamily.h"
31#include "arcane/mesh/CellFamily.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane::mesh
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42MeshNodeMerger::
43MeshNodeMerger(IMesh* mesh)
44: TraceAccessor(mesh->traceMng())
45, m_mesh(mesh)
46{
47 if (m_mesh->hasTiedInterface())
48 throw NotImplementedException(A_FUNCINFO,"mesh with tied interfaces");
49 if (m_mesh->dimension()==3){
50 Int32 c = m_mesh->connectivity()();
51 if (Connectivity::hasConnectivity(c,Connectivity::CT_HasEdge))
52 throw NotImplementedException(A_FUNCINFO,"3D mesh with edges");
53 }
54 if (m_mesh->childMeshes().count()!=0)
55 throw NotSupportedException(A_FUNCINFO,"mesh with child meshes");
56 if (m_mesh->isAmrActivated())
57 throw NotSupportedException(A_FUNCINFO,"mesh with AMR cells");
58
59 m_node_family = ARCANE_CHECK_POINTER(dynamic_cast<NodeFamily*>(m_mesh->nodeFamily()));
60 m_edge_family = ARCANE_CHECK_POINTER(dynamic_cast<EdgeFamily*>(m_mesh->edgeFamily()));
61 m_face_family = ARCANE_CHECK_POINTER(dynamic_cast<FaceFamily*>(m_mesh->faceFamily()));
62 m_cell_family = ARCANE_CHECK_POINTER(dynamic_cast<CellFamily*>(m_mesh->cellFamily()));
63
64}
65
66/*---------------------------------------------------------------------------*/
67/*---------------------------------------------------------------------------*/
82void MeshNodeMerger::
83mergeNodes(Int32ConstArrayView nodes_local_id,
84 Int32ConstArrayView nodes_to_merge_local_id,
85 bool allow_non_corresponding_face)
86{
87 ItemInternalList nodes_internal(m_node_family->itemsInternal());
88 Integer nb_node = nodes_local_id.size();
89 if (nb_node != nodes_to_merge_local_id.size())
90 throw ArgumentException(A_FUNCINFO,String::format("Arrays of different size"));
91 for (Integer i = 0; i < nb_node; ++i) {
92 Node node(nodes_internal[nodes_local_id[i]]);
93 Node node_to_merge(nodes_internal[nodes_to_merge_local_id[i]]);
94 if (node.localId()==node_to_merge.localId())
95 ARCANE_FATAL("Can not merge a node with itself");
96 info(4) << "ADD CORRESPONDANCE node=" << node.uniqueId() << " node_to_merge=" << node_to_merge.uniqueId();
97 m_nodes_correspondance.insert(std::make_pair(node_to_merge,node));
98 }
99
100 // Marque toutes les faces qui contiennent au moins un nœud fusionné
101 // et détermine celles qui doivent être fusionnées : ce sont celles pour
102 // lesquelles chaque nœud est fusionné.
103 std::set<Face> marked_faces;
104 Int64UniqueArray face_new_nodes_uid;
105 Int64UniqueArray face_new_nodes_sorted_uid;
106 ENUMERATE_ (Face, iface, m_face_family->allItems()) {
107 Face face = *iface;
108 Integer face_nb_node = face.nbNode();
109 Integer nb_merged_node = 0;
110 for( NodeEnumerator inode(face.nodes()); inode(); ++inode ){
111 Node node = *inode;
112 if (m_nodes_correspondance.find(node)!=m_nodes_correspondance.end()){
113 ++nb_merged_node;
114 marked_faces.insert(face);
115 }
116 }
117 if (nb_merged_node == face_nb_node) {
118 // Tous les nœuds de la face sont fusionnés. Cela veut dire que les
119 // mailles associées à cette face vont faire référence à une nouvelle face.
120 // Il faut maintenant trouver cette nouvelle face.
121 info(4) << "FACE TO MERGE uid=" << face.uniqueId();
122 face_new_nodes_uid.resize(face_nb_node);
123 face_new_nodes_sorted_uid.resize(face_nb_node);
124 Node new_face_first_node;
125 for( NodeEnumerator inode(face.nodes()); inode(); ++inode ){
126 Node new_node = m_nodes_correspondance.find(*inode)->second;
127 if (inode.index()==0)
128 new_face_first_node = new_node;
129 face_new_nodes_uid[inode.index()] = new_node.uniqueId();
130 info(4) << " OLD_node=" << (*inode).uniqueId() << " new=" << new_node.uniqueId();
131 }
132 mesh_utils::reorderNodesOfFace(face_new_nodes_uid, face_new_nodes_sorted_uid);
133 Face new_face = ItemTools::findFaceInNode2(new_face_first_node, face.type(), face_new_nodes_sorted_uid);
134 if (new_face.null()) {
135 // La face n'a pas de correspondante. Ne fais rien si cela est autorisé.
136 if (allow_non_corresponding_face)
137 continue;
138 ARCANE_FATAL("Can not find corresponding face nodes_uid={0}", face_new_nodes_sorted_uid);
139 }
140 info(4) << "NEW FACE=" << new_face.uniqueId() << " nb_cell=" << new_face.nbCell();
141 m_faces_correspondance.insert(std::make_pair(face,new_face));
142 // Comme cette face est fusionnée, on la retire de la liste des faces
143 // marquées.
144 marked_faces.erase(marked_faces.find(face));
145 }
146 }
147 // TODO: traiter les arêtes
148
149 // Marque toutes les mailles qui contiennent au moins un noeud fusionné.
150 std::set<Cell> marked_cells;
151 ENUMERATE_CELL(icell,m_cell_family->allItems()){
152 Cell cell = *icell;
153 for( NodeEnumerator inode(cell.nodes()); inode(); ++inode ){
154 if (m_nodes_correspondance.find(*inode)!=m_nodes_correspondance.end())
155 marked_cells.insert(cell);
156 }
157 }
158
159 for( Cell cell : marked_cells ){
160 ItemLocalId cell_local_id(cell.localId());
161 info(4) << "MARKED CELL2=" << cell.localId();
162 for( NodeEnumerator inode(cell.nodes()); inode(); ++inode ){
163 Node node = *inode;
164 auto x = m_nodes_correspondance.find(node);
165 if (x!=m_nodes_correspondance.end()){
166 Node new_node = x->second;
167 info(4) << "REMOVE node=" << ItemPrinter(node) << " from cell=" << ItemPrinter(cell);
168 m_node_family->removeCellFromNode(node,cell_local_id);
169 m_node_family->addCellToNode(new_node,cell);
170 m_cell_family->replaceNode(cell,inode.index(),new_node);
171 }
172 }
173 for( FaceEnumerator iface(cell.faces()); iface(); ++iface ){
174 Face face = *iface;
175 auto x = m_faces_correspondance.find(face);
176 if (x!=m_faces_correspondance.end()){
177 Face new_face = x->second;
178 m_face_family->removeCellFromFace(face,cell_local_id);
179 if (new_face.backCell().null())
180 m_face_family->addBackCellToFace(new_face,cell);
181 else
182 m_face_family->addFrontCellToFace(new_face,cell);
183 m_cell_family->replaceFace(cell,iface.index(),new_face);
184 }
185 }
186 // TODO: ajouter gestion des aretes.
187 }
188
189 for( Face face : marked_faces ){
190 info(4) << "MARKED FACE=" << face.localId();
191 for( NodeEnumerator inode(face.nodes()); inode(); ++inode ){
192 Node node = *inode;
193 auto x = m_nodes_correspondance.find(node);
194 if (x!=m_nodes_correspondance.end()){
195 Node new_node = x->second;
196 m_node_family->removeFaceFromNode(node,face);
197 m_node_family->addFaceToNode(new_node,face);
198 m_face_family->replaceNode(face,inode.index(),new_node);
199 }
200 }
201 }
202 // TODO: ajouter gestion des arêtes.
203
204 // S'assure que les nouvelles faces sont bien orientées
205 {
206 FaceReorienter fr(m_mesh);
207 for( Face face : marked_faces ){
209 }
210 }
211
212 // Supprime toutes les faces qui doivent être fusionnées.
213 for( const auto& x : m_faces_correspondance ){
214 Face face = x.first;
215 m_face_family->removeFaceIfNotConnected(face);
216 }
217
218 // Supprime tous les noeuds qui doivent être fusionnées.
219 for( const auto& x : m_nodes_correspondance ){
220 Node node = x.first;
221 m_node_family->removeNodeIfNotConnected(node);
222 }
223
224 m_mesh->modifier()->endUpdate();
225}
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
230} // End namespace Arcane::mesh
231
232/*---------------------------------------------------------------------------*/
233/*---------------------------------------------------------------------------*/
234
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
Fonctions utilitaires sur le maillage.
bool reorderNodesOfFace(Int64ConstArrayView before_ids, Int64ArrayView after_ids)
Réordonne les noeuds d'une face.
Exception lorsqu'un argument est invalide.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
Maille d'un maillage.
Definition Item.h:1199
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Cette fonction/classe réoriente les faces.
ARCANE_DEPRECATED_260 void checkAndChangeOrientation(ItemInternal *face)
Face d'une maille.
Definition Item.h:952
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
Definition Item.h:1027
Cell backCell() const
Maille derrière la face (maille nulle si aucune)
Definition Item.h:1622
Index d'un Item dans une variable.
Definition ItemLocalId.h:41
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:35
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:785
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:779
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
Int16 type() const
Type de l'entité
Definition Item.h:241
Noeud d'un maillage.
Definition Item.h:576
TraceMessage info() const
Flot pour un message d'information.
static Face findFaceInNode2(Node node, Integer face_type_id, Int64ConstArrayView face_nodes_uid)
Definition ItemTools.cc:44
ItemEnumeratorT< Node > NodeEnumerator
Enumérateurs sur des noeuds.
Definition ItemTypes.h:254
ItemEnumeratorT< Face > FaceEnumerator
Enumérateurs sur des faces.
Definition ItemTypes.h:265
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:426
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:569
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466