Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SubMeshTools.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/* SubMeshTools.cc (C) 2000-2024 */
9/* */
10/* Algorithmes spécifiques aux sous-maillages. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/SubMeshTools.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/ScopedPtr.h"
18
19// Includes génériques non spécifiques à l'implémentation DynamicMesh
20#include "arcane/core/Variable.h"
21#include "arcane/core/SharedVariable.h"
22#include "arcane/core/IParallelMng.h"
23#include "arcane/core/MeshToMeshTransposer.h"
24#include "arcane/core/IVariableSynchronizer.h"
25#include "arcane/core/IParallelExchanger.h"
26#include "arcane/core/ISerializer.h"
27#include "arcane/core/ISerializeMessage.h"
28#include "arcane/core/ItemPrinter.h"
29#include "arcane/core/TemporaryVariableBuildInfo.h"
30#include "arcane/core/ParallelMngUtils.h"
31
32// Includes spécifiques à l'implémentation à base de DynamicMesh
33#include "arcane/mesh/DynamicMesh.h"
34#include "arcane/mesh/DynamicMeshIncrementalBuilder.h"
35#include "arcane/mesh/ItemFamily.h"
36#include "arcane/mesh/CellFamily.h"
37#include "arcane/mesh/FaceFamily.h"
38#include "arcane/mesh/EdgeFamily.h"
39#include "arcane/mesh/NodeFamily.h"
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44namespace Arcane::mesh
45{
46
47/*---------------------------------------------------------------------------*/
48/*---------------------------------------------------------------------------*/
49
50SubMeshTools::
51SubMeshTools(DynamicMesh * mesh, DynamicMeshIncrementalBuilder * mesh_builder)
52: TraceAccessor(mesh->traceMng())
53, m_mesh(mesh)
54, m_mesh_builder(mesh_builder)
55, m_parallel_mng(mesh->parallelMng())
56{
57 ;
58}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63SubMeshTools::
64~SubMeshTools()
65{
66 ;
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72void SubMeshTools::
73_updateGroups()
74{
75 // Réajuste les groupes en supprimant les entités qui ne sont plus dans le maillage
76 for( IItemFamilyCollection::Enumerator i_family(m_mesh->itemFamilies()); ++i_family; ){
77 IItemFamily* family = *i_family;
78 for( ItemGroupCollection::Enumerator i_group((*i_family)->groups()); ++i_group; ){
79 ItemGroup group = *i_group;
80 // GG: la méthode suivante est équivalente à ce qui est dans le define OLD.
81 family->partialEndUpdateGroup(group);
82#ifdef OLD
83 // GG: il ne faut pas modifier le groupe de toutes les entités car
84 // il sera modifié dans DynamicMeshKindInfos::finalizeMeshChanged()
85 // et donc si on le modifie ici, il le sera 2 fois.
86 if (group.isAllItems())
87 continue;
88 // Anciennement: if (group.isLocalToSubDomain() || group.isOwn())
89 if (group.internal()->hasComputeFunctor())
90 group.invalidate();
91 else
92 group.internal()->removeSuppressedItems();
93#endif
94 }
95 }
96}
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
101void SubMeshTools::
102_fillGhostItems(ItemFamily* family, Array<Int32>& items_local_id)
103{
104 items_local_id.clear();
105 ItemInternalMap& items_map = family->itemsMap();
106 Int32 rank = m_parallel_mng->commRank();
107
108 items_map.eachItem([&](Item item) {
109 if (item.owner() != rank) {
110 items_local_id.add(item.localId());
111 }
112 });
113}
114
115/*---------------------------------------------------------------------------*/
116/*---------------------------------------------------------------------------*/
117
118void SubMeshTools::
119_fillFloatingItems(ItemFamily* family, Array<Int32>& items_local_id)
120{
121 items_local_id.reserve(1000);
122 ItemInternalMap& items_map = family->itemsMap();
123 items_map.eachItem([&](impl::ItemBase item) {
124 if (!item.isSuppressed() && item.nbCell() == 0 && !item.isOwn()) {
125 items_local_id.add(item.localId());
126 }
127 });
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133void SubMeshTools::
134_removeCell(Cell cell)
135{
136 CellFamily& cell_family = m_mesh->trueCellFamily();
137 FaceFamily& face_family = m_mesh->trueFaceFamily();
138 EdgeFamily& edge_family = m_mesh->trueEdgeFamily();
139 NodeFamily& node_family = m_mesh->trueNodeFamily();
140
141 ItemLocalId cell_lid(cell);
142 for( Face face : cell.faces() )
143 face_family.removeCellFromFace(face,cell_lid);
144 for( Edge edge : cell.edges() )
145 edge_family.removeCellFromEdge(edge,cell_lid);
146 for( Node node : cell.nodes() )
147 node_family.removeCellFromNode(node,cell_lid);
148 cell_family.removeItem(cell);
149}
150
151/*---------------------------------------------------------------------------*/
152/*---------------------------------------------------------------------------*/
153
154void SubMeshTools::
155removeDeadGhostCells()
156{
157 // TODO
158 CellFamily& cell_family = m_mesh->trueCellFamily();
159 FaceFamily& face_family = m_mesh->trueFaceFamily();
160 EdgeFamily& edge_family = m_mesh->trueEdgeFamily();
161 NodeFamily& node_family = m_mesh->trueNodeFamily();
162
163 // On cherche les items fantômes dont les parents sont supprimés
164 UniqueArray<Int32> items_to_remove;
165 _fillGhostItems(&cell_family, items_to_remove);
166 ENUMERATE_ (Cell, icell, cell_family.view(items_to_remove)) {
167 impl::ItemBase item(icell->itemBase());
168 ARCANE_ASSERT((!item.parentBase(0).isSuppressed()),("SubMesh cell not synchronized with its support group"));
169
170 // on met no_destroy=true => ce sont les sous-items qui s'occuperont de la destruction
171 if (item.parentBase(0).isSuppressed())
172 _removeCell(item);
173 }
174
175 _fillGhostItems(&face_family, items_to_remove);
176 ENUMERATE_ (Face, iface, face_family.view(items_to_remove)) {
177 impl::ItemBase item(iface->itemBase());
178 if (item.parentBase(0).isSuppressed()) {
179 ARCANE_ASSERT((item.nbCell() == 0),("Cannot remove connected sub-item"));
180 face_family.removeFaceIfNotConnected(item);
181 }
182 }
183
184 _fillGhostItems(&edge_family, items_to_remove);
185 EdgeInfoListView edges(&edge_family);
186 ENUMERATE_ (Edge, iedge, edge_family.view(items_to_remove)) {
187 impl::ItemBase item(iedge->itemBase());
188 if (item.parentBase(0).isSuppressed()) {
189 ARCANE_ASSERT((item.nbCell() == 0 && item.nbFace() == 0),("Cannot remove connected sub-item"));
190 edge_family.removeEdgeIfNotConnected(item);
191 }
192 }
193
194 _fillGhostItems(&node_family, items_to_remove);
195 NodeInfoListView nodes(&node_family);
196 ENUMERATE_ (Node, inode, node_family.view(items_to_remove)) {
197 impl::ItemBase item(inode->itemBase());
198 if (item.parentBase(0).isSuppressed()) {
199 ARCANE_ASSERT((item.nbCell()==0 && item.nbFace()==0 && item.nbEdge()==0),("Cannot remove connected sub-item"));
200 node_family.removeItem(item);
201 }
202 }
203
204 _updateGroups();
205}
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
209
210void SubMeshTools::
211removeGhostMesh()
212{
213 CellFamily& cell_family = m_mesh->trueCellFamily();
214 FaceFamily& face_family = m_mesh->trueFaceFamily();
215 EdgeFamily& edge_family = m_mesh->trueEdgeFamily();
216 NodeFamily& node_family = m_mesh->trueNodeFamily();
217
218 // NOTE GG: normalement on devrait pouvoir remplacer tout le
219 // code de destruction par:
220 // for( ItemInternal* item : items_to_remove ){
221 // cell_family.removeCell(item);
222 // }
223 // A priori cela marche sur les tests comme je n'ai pas tous les tests IFPEN
224 // je préfère laisser comme cela.
225
226
227 // L'ordre est important pour correctement déconnecter les connectivités
228 // Les méthodes sont ici écrites directement avec les primitives des *Family
229 // car les méthodes toutes prêtes (dont CellFamily::removeCell)
230 // ne tiennent pas compte du mécanisme fantome particulier des sous-maillages
231 // où un sous-item peuvent vivre sans sur-item rattaché à celui-ic
232 // (ex: Face 'own' sans Cell autour)
233 UniqueArray<Int32> items_to_remove;
234
235 _fillGhostItems(&cell_family, items_to_remove);
236 ENUMERATE_ (Cell, icell, cell_family.view(items_to_remove)) {
237 _removeCell(*icell);
238 }
239
240 _fillGhostItems(&face_family, items_to_remove);
241 ENUMERATE_ (Face, iface, face_family.view(items_to_remove)) {
242 face_family.removeFaceIfNotConnected(*iface);
243 }
244
245 _fillGhostItems(&edge_family, items_to_remove);
246 ENUMERATE_ (Edge, iedge, edge_family.view(items_to_remove)) {
247 Edge edge(*iedge);
248 if (edge.nbCell() == 0 && edge.nbFace() == 0)
249 edge_family.removeEdgeIfNotConnected(edge);
250 }
251
252 _fillGhostItems(&node_family, items_to_remove);
253 ENUMERATE_ (Node, inode, node_family.view(items_to_remove)) {
254 Node node(*inode);
255 if (node.nbCell() == 0 && node.nbFace() == 0 && node.nbEdge() == 0)
256 node_family.removeItem(node);
257 }
258
259 _updateGroups();
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265void SubMeshTools::
266removeFloatingItems()
267{
268 FaceFamily& face_family = m_mesh->trueFaceFamily();
269 EdgeFamily& edge_family = m_mesh->trueEdgeFamily();
270 NodeFamily& node_family = m_mesh->trueNodeFamily();
271
272 // L'ordre est important pour correctement déconnecter les connectivités
273 // Les méthodes sont ici écrites directement avec les primitives des *Family
274 // car les méthodes toutes prêtes (dont CellFamily::removeCell)
275 // ne tiennent pas compte du mécanisme fantome particulier des sous-maillages
276 // où un sous-item peuvent vivre sans sur-item rattaché à celui-ic
277 // (ex: Face 'own' sans Cell autour)
278 SharedArray<Int32> items_to_remove;
279 _fillFloatingItems(&face_family, items_to_remove);
280 ENUMERATE_ (Face, iface, face_family.view(items_to_remove)) {
281 Face face(*iface);
282 if (face.nbCell() == 0)
283 face_family.removeFaceIfNotConnected(face);
284 }
285 items_to_remove.clear();
286 _fillFloatingItems(&edge_family, items_to_remove);
287 ENUMERATE_ (Edge, iedge, edge_family.view(items_to_remove)) {
288 Edge edge(*iedge);
289 if (edge.nbCell() == 0 && edge.nbFace() == 0)
290 edge_family.removeEdgeIfNotConnected(edge);
291 }
292 items_to_remove.clear();
293 _fillFloatingItems(&node_family, items_to_remove);
294 ENUMERATE_ (Node, inode, node_family.view(items_to_remove)) {
295 Node node(*inode);
296 if (node.nbCell() == 0 && node.nbFace() == 0 && node.nbEdge() == 0)
297 node_family.removeItem(node);
298 }
299
300 _updateGroups();
301}
302
303/*---------------------------------------------------------------------------*/
304/*---------------------------------------------------------------------------*/
305
306void SubMeshTools::
307updateGhostMesh()
308{
309 removeGhostMesh();
310
311 _checkValidItemOwner();
312
313 eItemKind kinds[] = { IK_Cell, IK_Face, IK_Edge, IK_Node };
314 Integer nb_kind = sizeof(kinds)/sizeof(eItemKind);
315 for(Integer i_kind=0;i_kind<nb_kind;++i_kind){
316 IItemFamily * family = m_mesh->itemFamily(kinds[i_kind]);
317 updateGhostFamily(family);
318 }
319
320 removeFloatingItems();
321 _checkFloatingItems();
322 _checkValidItemOwner();
323
324 // La finalisation des familles et la construction
325 // de leurs synchronizers est délégué à l'extérieur
326}
327
328/*---------------------------------------------------------------------------*/
329/*---------------------------------------------------------------------------*/
330
331void SubMeshTools::
332updateGhostFamily(IItemFamily * family)
333{
334 const eItemKind kind = family->itemKind();
335 // IMesh * parent_mesh = m_mesh->parentMesh();
336 IItemFamily * parent_family = family->parentFamily();
337
338 debug(Trace::High) << "Process ghost on submesh " << m_mesh->name() << " with kind=" << kind;
339
340 auto exchanger { ParallelMngUtils::createExchangerRef(m_parallel_mng) };
341 IVariableSynchronizer * synchronizer = parent_family->allItemsSynchronizer();
342 Int32ConstArrayView ranks = synchronizer->communicatingRanks();
343 std::map<Integer, SharedArray<Int64> > to_send_items;
344 for(Integer i=0;i<ranks.size();++i){
345 const Integer rank = ranks[i];
346 debug(Trace::High) << "Has " << kind << " comm with " << rank << " : " << i << " / " << ranks.size() << " ranks";
347
348 // Les shared sont forcément own => consistence des requêtes
349 ItemVectorView shared_items(parent_family->view(synchronizer->sharedItems(i)));
350 ItemVector shared_submesh_items = MeshToMeshTransposer::transpose(parent_family, family, shared_items);
351 SharedArray<Int64> current_to_send_items;
352
353 ENUMERATE_ITEM(iitem, shared_submesh_items){
354 if (iitem.localId() != NULL_ITEM_LOCAL_ID){
355 const Item & item = *iitem;
356 ARCANE_ASSERT((item.uniqueId() == item.parent().uniqueId()),("Inconsistent item/parent uid"));
357 debug(Trace::Highest) << "Send shared submesh item to " << rank << " " << ItemPrinter(item);
358 current_to_send_items.add(item.parent().uniqueId());
359 }
360 }
361
362 debug(Trace::High) << "SubMesh ghost comm " << kind << " with " << rank << " : "
363 << shared_items.size() << " / " << current_to_send_items.size();
364
365 // Pour les cas de sous-maillages localisés, on ne considère réellement que les
366 // destinataires où il y a quelque chose à envoyer
367 if (!current_to_send_items.empty()){
368 exchanger->addSender(rank);
369 to_send_items[rank] = current_to_send_items;
370 }
371 }
372
373 exchanger->initializeCommunicationsMessages();
374
375 for(Integer i=0, ns=exchanger->nbSender(); i<ns; ++i){
376 ISerializeMessage* sm = exchanger->messageToSend(i);
377 const Int32 rank = sm->destination().value();
378 ISerializer* s = sm->serializer();
379 const Int64Array & current_to_send_items = to_send_items[rank];
380 s->setMode(ISerializer::ModeReserve);
381
382 s->reserveArray(current_to_send_items);
383
384 s->allocateBuffer();
385 s->setMode(ISerializer::ModePut);
386
387 s->putArray(current_to_send_items);
388 }
389
390 to_send_items.clear(); // destruction des données temporaires avant envoie
391 exchanger->processExchange();
392
393 for( Integer i=0, ns=exchanger->nbReceiver(); i<ns; ++i ){
394 ISerializeMessage* sm = exchanger->messageToReceive(i);
395 const Int32 rank = sm->destination().value();
396 ISerializer* s = sm->serializer();
397 //Integer new_submesh_ghost_size = s->getInteger();
398 Int64UniqueArray uids;
399 s->getArray(uids);
400 Int32UniqueArray lids(uids.size());
401 parent_family->itemsUniqueIdToLocalId(lids, uids);
402 ItemVectorView new_submesh_ghosts = parent_family->view(lids);
403 ENUMERATE_ITEM(iitem, new_submesh_ghosts){
404 if (iitem->owner() != rank)
405 fatal() << "Bad ghost owner " << ItemPrinter(*iitem) << " : expected owner=" << rank;
406 debug(Trace::Highest) << "Add ghost submesh item from " << rank << " : " << FullItemPrinter(*iitem);
407 }
408 m_mesh_builder->addParentItems(new_submesh_ghosts, kind);
409 }
410}
411
412/*---------------------------------------------------------------------------*/
413/*---------------------------------------------------------------------------*/
414
415void SubMeshTools::
416display(IMesh* mesh, const String msg)
417{
418 ITraceMng * traceMng = mesh->traceMng();
419 traceMng->info() << "Display mesh " << mesh->name() << " : " << msg;
420 eItemKind kinds[] = { IK_Cell, IK_Face, IK_Edge, IK_Node };
421 Integer nb_kind = sizeof(kinds)/sizeof(eItemKind);
422 for(Integer i_kind=0;i_kind<nb_kind;++i_kind){
423 IItemFamily* family = mesh->itemFamily(kinds[i_kind]);
424 ItemInfoListView items(family);
425 Integer count = 0;
426 for( Integer z=0, zs=family->maxLocalId(); z<zs; ++z )
427 if (!items[z].itemBase().isSuppressed())
428 ++count;
429 traceMng->info() << "\t" << family->itemKind() << " " << count;
430
431 for( Integer z=0, zs=family->maxLocalId(); z<zs; ++z ){
432 Item item = items[z];
433 if (!item.itemBase().isSuppressed()){
434 traceMng->info() << ItemPrinter(item);
435 }
436 }
437 }
438}
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442
443void SubMeshTools::
444_checkValidItemOwner()
445{
446 if (!arcaneIsCheck())
447 return;
448
449 eItemKind kinds[] = { IK_Cell, IK_Face, IK_Edge, IK_Node };
450 Integer nb_kind = sizeof(kinds)/sizeof(eItemKind);
451 for(Integer i_kind=0;i_kind<nb_kind;++i_kind){
452 IItemFamily * family = m_mesh->itemFamily(kinds[i_kind]);
453 IItemFamily * parent_family = family->parentFamily();
454 ItemInfoListView items(family);
455 for( Integer z=0, zs=family->maxLocalId(); z<zs; ++z ){
456 Item item = items[z];
457 if (!item.itemBase().isSuppressed()){
458 if (item.uniqueId() != item.itemBase().parentBase(0).uniqueId()){
459 Int64UniqueArray uids; uids.add(item.uniqueId());
460 Int32UniqueArray lids(1);
461 parent_family->itemsUniqueIdToLocalId(lids,uids,false);
462 ARCANE_FATAL("Inconsistent parent uid '{0}' now located in '{1}'",
463 ItemPrinter(item),lids[0]);
464 }
465 }
466 }
467 }
468}
469
470/*---------------------------------------------------------------------------*/
471/*---------------------------------------------------------------------------*/
472
473void SubMeshTools::
474_checkFloatingItems()
475{
476 Integer nerror = 0;
477 eItemKind kinds[] = { IK_Face, IK_Edge, IK_Node };
478 Integer nb_kind = sizeof(kinds)/sizeof(eItemKind);
479 for(Integer i_kind=0;i_kind<nb_kind;++i_kind){
480 IItemFamily * family = m_mesh->itemFamily(kinds[i_kind]);
481 // Calcul des items orphelins de cellules
482 ItemInfoListView items(family);
483 for( Integer z=0, zs=family->maxLocalId(); z<zs; ++z ){
484 Item item = items[z];
485 if (!item.itemBase().isSuppressed() && item.itemBase().nbCell() == 0) {
486 error() << "Floating item detected : " << ItemPrinter(item);
487 ++nerror;
488 }
489 }
490 }
491 if (nerror)
492 fatal() << "ERROR " << String::plural(nerror,"floating item") << " detected; see above";
493}
494
495/*---------------------------------------------------------------------------*/
496/*---------------------------------------------------------------------------*/
497
498}
499
500/*---------------------------------------------------------------------------*/
501/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
Classe de base pour les entités du maillage.
Integer nbEdge() const
Nombre d'arêtes de l'entité ou nombre d'arêtes connectés à l'entités (pour les noeuds)
bool isSuppressed() const
Vrai si l'entité est supprimée.
Integer nbCell() const
Nombre de mailles connectées à l'entité (pour les noeuds, arêtes et faces)
Integer nbFace() const
Nombre de faces de l'entité ou nombre de faces connectés à l'entités (pour les noeuds et arêtes)
bool isOwn() const
Vrai si l'entité appartient au sous-domaine.
Classe de base d'un élément de maillage.
Definition Item.h:83
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:229
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
void clear()
Supprime les éléments du tableau.
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:325
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:151
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:513
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:640
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
eItemKind
Genre d'entité de maillage.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Face
Entité de maillage de genre face.
@ IK_Edge
Entité de maillage de genre arête.
Int32 Integer
Type représentant un entier.