Arcane  v3.14.10.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-2024 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-2024 */
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/NotSupportedException.h"
17#include "arcane/utils/ArgumentException.h"
18
19#include "arcane/core/IMesh.h"
21#include "arcane/core/IMeshModifier.h"
23#include "arcane/core/ItemPrinter.h"
24#include "arcane/core/Connectivity.h"
25
26#include "arcane/mesh/MeshNodeMerger.h"
27#include "arcane/mesh/FaceReorienter.h"
28
29#include "arcane/mesh/ItemTools.h"
30#include "arcane/mesh/NodeFamily.h"
31#include "arcane/mesh/EdgeFamily.h"
32#include "arcane/mesh/FaceFamily.h"
33#include "arcane/mesh/CellFamily.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane::mesh
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44MeshNodeMerger::
45MeshNodeMerger(IMesh* mesh)
46: TraceAccessor(mesh->traceMng())
47, m_mesh(mesh)
48{
49 if (m_mesh->hasTiedInterface())
50 throw NotImplementedException(A_FUNCINFO,"mesh with tied interfaces");
51 if (m_mesh->dimension()==3){
52 Int32 c = m_mesh->connectivity()();
53 if (Connectivity::hasConnectivity(c,Connectivity::CT_HasEdge))
54 throw NotImplementedException(A_FUNCINFO,"3D mesh with edges");
55 }
56 if (m_mesh->childMeshes().count()!=0)
57 throw NotSupportedException(A_FUNCINFO,"mesh with child meshes");
58 if (m_mesh->isAmrActivated())
59 throw NotSupportedException(A_FUNCINFO,"mesh with AMR cells");
60
61 m_node_family = ARCANE_CHECK_POINTER(dynamic_cast<NodeFamily*>(m_mesh->nodeFamily()));
62 m_edge_family = ARCANE_CHECK_POINTER(dynamic_cast<EdgeFamily*>(m_mesh->edgeFamily()));
63 m_face_family = ARCANE_CHECK_POINTER(dynamic_cast<FaceFamily*>(m_mesh->faceFamily()));
64 m_cell_family = ARCANE_CHECK_POINTER(dynamic_cast<CellFamily*>(m_mesh->cellFamily()));
65
66}
67
68/*---------------------------------------------------------------------------*/
69/*---------------------------------------------------------------------------*/
84void MeshNodeMerger::
87{
88 ItemInternalList nodes_internal(m_node_family->itemsInternal());
89 Integer nb_node = nodes_local_id.size();
91 throw ArgumentException(A_FUNCINFO,String::format("Arrays of different size"));
92 for( Integer i=0; i<nb_node; ++i ){
95 if (node.localId()==node_to_merge.localId())
96 ARCANE_FATAL("Can not merge a node with itself");
97 info(4) << "ADD CORRESPONDANCE node=" << node.uniqueId() << " node_to_merge=" << node_to_merge.uniqueId();
98 m_nodes_correspondance.insert(std::make_pair(node_to_merge,node));
99 }
100
101 // Marque toutes les faces qui contiennent au moins un noeud fusionné
102 // et détermine celles qui doivent être fusionnées: ce sont celles pour
103 // lesquelles chaque noeud est fusionné.
104 std::set<Face> marked_faces;
107 ENUMERATE_FACE(iface,m_face_family->allItems()){
108 Face face = *iface;
109 Integer nb_node = face.nbNode();
110 Integer nb_merged_node = 0;
111 for( NodeEnumerator inode(face.nodes()); inode(); ++inode ){
112 Node node = *inode;
113 if (m_nodes_correspondance.find(node)!=m_nodes_correspondance.end()){
115 marked_faces.insert(face);
116 }
117 }
119 // Tous les noeuds de la face sont fusionnés. Cela veut dire que les
120 // mailles associées à cette face vont faire référence à une nouvelle face.
121 // Il faut maintenant trouver cette nouvelle face.
122 info(4) << "FACE TO MERGE uid=" << face.uniqueId();
126 for( NodeEnumerator inode(face.nodes()); inode(); ++inode ){
127 Node new_node = m_nodes_correspondance.find(*inode)->second;
128 if (inode.index()==0)
130 face_new_nodes_uid[inode.index()] = new_node.uniqueId();
131 info(4) << " OLD_node=" << (*inode).uniqueId() << " new=" << new_node.uniqueId();
132 }
133 mesh_utils::reorderNodesOfFace(face_new_nodes_uid,face_new_nodes_sorted_uid);
134 Face new_face = ItemTools::findFaceInNode2(new_face_first_node,face.type(),face_new_nodes_sorted_uid);
135 if (new_face.null())
136 ARCANE_FATAL("Can not find corresponding face nodes_uid={0}",face_new_nodes_sorted_uid);
137 info(4) << "NEW FACE=" << new_face.uniqueId() << " nb_cell=" << new_face.nbCell();
138 m_faces_correspondance.insert(std::make_pair(face,new_face));
139 // Comme cette face est fusionnée, on la retire de la liste des faces
140 // marquées.
141 marked_faces.erase(marked_faces.find(face));
142 }
143 }
144 // TODO: traiter les arêtes
145
146 // Marque toutes les mailles qui contiennent au moins un noeud fusionné.
147 std::set<Cell> marked_cells;
148 ENUMERATE_CELL(icell,m_cell_family->allItems()){
149 Cell cell = *icell;
150 for( NodeEnumerator inode(cell.nodes()); inode(); ++inode ){
151 if (m_nodes_correspondance.find(*inode)!=m_nodes_correspondance.end())
152 marked_cells.insert(cell);
153 }
154 }
155
156 for( Cell cell : marked_cells ){
157 ItemLocalId cell_local_id(cell.localId());
158 info(4) << "MARKED CELL2=" << cell.localId();
159 for( NodeEnumerator inode(cell.nodes()); inode(); ++inode ){
160 Node node = *inode;
161 auto x = m_nodes_correspondance.find(node);
162 if (x!=m_nodes_correspondance.end()){
163 Node new_node = x->second;
164 info(4) << "REMOVE node=" << ItemPrinter(node) << " from cell=" << ItemPrinter(cell);
165 m_node_family->removeCellFromNode(node,cell_local_id);
166 m_node_family->addCellToNode(new_node,cell);
167 m_cell_family->replaceNode(cell,inode.index(),new_node);
168 }
169 }
170 for( FaceEnumerator iface(cell.faces()); iface(); ++iface ){
171 Face face = *iface;
172 auto x = m_faces_correspondance.find(face);
173 if (x!=m_faces_correspondance.end()){
174 Face new_face = x->second;
175 m_face_family->removeCellFromFace(face,cell_local_id);
176 if (new_face.backCell().null())
177 m_face_family->addBackCellToFace(new_face,cell);
178 else
179 m_face_family->addFrontCellToFace(new_face,cell);
180 m_cell_family->replaceFace(cell,iface.index(),new_face);
181 }
182 }
183 // TODO: ajouter gestion des aretes.
184 }
185
186 for( Face face : marked_faces ){
187 info(4) << "MARKED FACE=" << face.localId();
188 for( NodeEnumerator inode(face.nodes()); inode(); ++inode ){
189 Node node = *inode;
190 auto x = m_nodes_correspondance.find(node);
191 if (x!=m_nodes_correspondance.end()){
192 Node new_node = x->second;
193 m_node_family->removeFaceFromNode(node,face);
194 m_node_family->addFaceToNode(new_node,face);
195 m_face_family->replaceNode(face,inode.index(),new_node);
196 }
197 }
198 }
199 // TODO: ajouter gestion des arêtes.
200
201 // S'assure que les nouvelles faces sont bien orientées
202 {
203 FaceReorienter fr(m_mesh);
204 for( Face face : marked_faces ){
205 fr.checkAndChangeOrientation(face);
206 }
207 }
208
209 // Supprime toutes les faces qui doivent être fusionnées.
210 for( const auto& x : m_faces_correspondance ){
211 Face face = x.first;
212 m_face_family->removeFaceIfNotConnected(face);
213 }
214
215 // Supprime tous les noeuds qui doivent être fusionnées.
216 for( const auto& x : m_nodes_correspondance ){
217 Node node = x.first;
218 m_node_family->removeNodeIfNotConnected(node);
219 }
220
221 m_mesh->modifier()->endUpdate();
222}
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
227} // End namespace Arcane::mesh
228
229/*---------------------------------------------------------------------------*/
230/*---------------------------------------------------------------------------*/
231
#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_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
Fonctions utilitaires sur le maillage.
Maille d'un maillage.
Definition Item.h:1178
Cette fonction/classe réoriente les faces.
Face d'une maille.
Definition Item.h:932
Enumérateur sur une liste typée d'entités de type ItemType.
Index d'un Item dans une variable.
Definition ItemLocalId.h:40
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:771
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:765
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
Int16 type() const
Type de l'entité
Definition Item.h:232
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Noeud d'un maillage.
Definition Dom.h:204
Exception lorsqu'un argument est invalide.
Vue constante d'un tableau de type T.
Vecteur 1D de données avec sémantique par valeur (style STL).