Arcane  4.2.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
GhostLayerBuilder.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* GhostLayerBuilder.cc (C) 2000-2026 */
9/* */
10/* Construction des couches fantômes. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArgumentException.h"
15#include "arcane/utils/NotImplementedException.h"
16#include "arcane/utils/NotSupportedException.h"
17#include "arcane/utils/HashTableMap.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/ITraceMng.h"
21#include "arcane/utils/ValueConvert.h"
22#include "arcane/utils/OStringStream.h"
23#include "arcane/utils/CheckedConvert.h"
24
25#include "arcane/core/ItemTypeMng.h"
27#include "arcane/core/IParallelMng.h"
28#include "arcane/core/SerializeBuffer.h"
29#include "arcane/core/ItemPrinter.h"
30#include "arcane/core/IParallelExchanger.h"
31#include "arcane/core/ISerializeMessage.h"
32#include "arcane/core/IItemFamilyPolicyMng.h"
33#include "arcane/core/IItemFamilySerializer.h"
34#include "arcane/core/ParallelMngUtils.h"
35#include "arcane/core/IGhostLayerMng.h"
36#include "arcane/core/internal/IMeshInternal.h"
37
38#include "arcane/mesh/DynamicMesh.h"
39#include "arcane/mesh/GhostLayerBuilder.h"
40#include "arcane/mesh/OneMeshItemAdder.h"
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
45namespace Arcane::mesh
46{
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51extern "C++" void
52_buildGhostLayerNewVersion(IMesh* mesh, bool is_allocate, Int32 version);
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
57// #define ARCANE_DEBUG_DYNAMIC_MESH
58// #define ARCANE_DEBUG_DYNAMIC_MESH2
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
65
69, m_mesh(mesh)
70, m_mesh_internal(mesh->_internalApi())
71{
72}
73
74/*---------------------------------------------------------------------------*/
75/*---------------------------------------------------------------------------*/
76
77GhostLayerBuilder::
78~GhostLayerBuilder()
79{
80}
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88void GhostLayerBuilder::
89addGhostLayers(bool is_allocate)
90{
91 Real begin_time = platform::getRealTime();
92 Integer version = m_mesh->ghostLayerMng()->builderVersion();
93 if (version==1){
94 throw NotSupportedException(A_FUNCINFO,"Version 1 is no longer supported");
95 }
96 else if (version==2){
97 info() << "Use ghost layer builder version 2";
98 _addOneGhostLayerV2();
99 }
100 else if (version==3 || version==4){
101 info() << "Use GhostLayerBuilder with sort (version " << version << ")";
102 _buildGhostLayerNewVersion(m_mesh,is_allocate,version);
103 }
104 else
105 throw NotSupportedException(A_FUNCINFO,"Bad version number for addGhostLayer");
106
107 Real end_time = platform::getRealTime();
108 Real diff = (Real)(end_time - begin_time);
109 info() << "TIME to compute ghost layer=" << diff;
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115class NodeCellList
116{
117 public:
118 private:
119
120 public:
121 NodeCellList() : m_cell_last_index(5000,true) {}
122
123 public:
124
125 void add(Int64 node_uid,Int64 cell_uid,Int64 cell_owner)
126 {
127 Int32 current_index = m_cell_indexes.size();
128 m_cell_indexes.add(cell_uid);
129 m_cell_indexes.add(cell_owner);
130 bool is_add = false;
131 HashTableMapT<Int64,Int32>::Data* d = m_cell_last_index.lookupAdd(node_uid,-1,is_add);
132 m_cell_indexes.add(d->value());
133 d->value() = current_index;
134 }
135
136 public:
137 Int64UniqueArray m_cell_indexes;
138 HashTableMapT<Int64,Int32> m_cell_last_index;
139};
140
141/*---------------------------------------------------------------------------*/
142/*---------------------------------------------------------------------------*/
143
144void GhostLayerBuilder::
145_exchangeData(IParallelExchanger* exchanger,BoundaryInfosMap& boundary_infos_to_send)
146{
147 for( BoundaryInfosMapEnumerator i_map(boundary_infos_to_send); ++i_map; ){
148 Int32 sd = i_map.data()->key();
149 exchanger->addSender(sd);
150 }
152 {
153 for( Integer i=0, ns=exchanger->nbSender(); i<ns; ++i ){
154 ISerializeMessage* sm = exchanger->messageToSend(i);
155 Int32 rank = sm->destination().value();
156 ISerializer* s = sm->serializer();
157 Int64ConstArrayView infos = boundary_infos_to_send[rank];
158
159 s->setMode(ISerializer::ModeReserve);
160 s->reserveArray(infos); // Pour les elements
161
162 s->allocateBuffer();
164
165 s->putArray(infos);
166 }
167 }
168 exchanger->processExchange();
169 debug() << "END EXCHANGE";
170}
171
172/*---------------------------------------------------------------------------*/
173/*---------------------------------------------------------------------------*/
174
175void GhostLayerBuilder::
176_addOneGhostLayerV2()
177{
178 info() << "** NEW GHOST LAYER BUILDER V2";
179 if (m_mesh->ghostLayerMng()->nbGhostLayer()!=1)
180 ARCANE_THROW(NotImplementedException,"Only one layer of ghost cells is supported");
181
182 IParallelMng* pm = m_mesh->parallelMng();
183 Int32 my_rank = pm->commRank();
184 Int32 nb_rank = pm->commSize();
185 debug() << " RANK="<< pm->commRank() << " size=" << pm->commSize();
186 if (!pm->isParallel()){
187 debug() << "NOT PARALLEL";
188 return;
189 }
190#ifdef ARCANE_DEBUG_DYNAMIC_MESH
191 const bool is_verbose = true;
192#else
193 const bool is_verbose = false;
194#endif
195
196 OStringStream ostr;
197 if (is_verbose)
198 ostr() << "** FACES LIST\n";
199
200 Integer nb_sub_domain_boundary_face = 0;
201 // Marque les noeuds sur la frontière
202 ItemInternalMap& cells_map = m_mesh_internal->cellsMap(); // Supporte les transferts du maillage
203 ItemInternalMap& faces_map = m_mesh_internal->facesMap(); // Détermine les frontières avant transfert
204 // ItemInternalMap& edges_map = m_mesh_internal->edgesMap(); // N'est pas utilisé directement par l'algo
205 ItemInternalMap& nodes_map = m_mesh_internal->nodesMap(); // Localise les modifications
206
207 const int shared_and_boundary_flags = ItemFlags::II_Shared | ItemFlags::II_SubDomainBoundary;
208 // Parcours les faces et marque les nœuds, arêtes et faces frontières
209 faces_map.eachItem([&](Face face) {
210 impl::ItemBase face_base = face.itemBase();
211 if (is_verbose){
212 ostr() << ItemPrinter(face);
213 ostr() << '\n';
214 }
215 bool is_sub_domain_boundary_face = false;
216 if (face_base.hasFlags(ItemFlags::II_Boundary)) {
217 is_sub_domain_boundary_face = true;
218 }
219 else{
220 if (face.nbCell()==2 && (face.cell(0).owner()!=my_rank || face.cell(1).owner()!=my_rank))
221 is_sub_domain_boundary_face = true;
222 }
223 if (is_sub_domain_boundary_face){
224 face_base.toMutable().addFlags(shared_and_boundary_flags);
225 ++nb_sub_domain_boundary_face;
226 for( Item inode : face.nodes() )
227 inode.mutableItemBase().addFlags(shared_and_boundary_flags);
228 for( Item iedge : face.edges() )
229 iedge.mutableItemBase().addFlags(shared_and_boundary_flags);
230 }
231 });
232
233 Integer boundary_nodes_uid_count = 0;
234
235 // Parcours les nœuds et ajoute les nœuds frontières
236 Int64 my_max_node_uid = NULL_ITEM_UNIQUE_ID;
237 nodes_map.eachItem([&](Node node) {
238 Int32 f = node.itemBase().flags();
239 if (f & ItemFlags::II_Shared) {
240 Int64 node_uid = node.uniqueId();
241 if (node_uid > my_max_node_uid)
242 my_max_node_uid = node_uid;
243 ++boundary_nodes_uid_count;
244 }
245 });
246
247 Int64 global_max_node_uid = pm->reduce(Parallel::ReduceMax,my_max_node_uid);
248 debug() << "NB BOUNDARY NODE=" << boundary_nodes_uid_count
249 << " MY_MAX_UID=" << my_max_node_uid
250 << " GLOBAL=" << global_max_node_uid;
251
252 if (is_verbose){
253 ostr.reset();
254 ostr() << "List of shared cells:\n";
255 }
256
257
258 //TODO: choisir bonne valeur pour initialiser la table
259 BoundaryInfosMap boundary_infos_to_send(200,true);
260 NodeUidToSubDomain uid_to_subdomain_converter(global_max_node_uid,nb_rank);
261
262 cells_map.eachItem([&](Cell cell) {
263 if (is_verbose){
264 ostr() << "Send cell " << ItemPrinter(cell) << '\n';
265 }
266 //info() << " CHECK cell uid=" << cell->uniqueId() << " owner=" << cell->owner();
267 //bool add_cell = false;
268 for( Node node : cell.nodes() ){
269 //info() << "** CHECK NODE node=" << i_node->uniqueId() << " cell=" << cell->uniqueId();
270 if (node.hasFlags(ItemFlags::II_Shared)){
271 Int64 node_uid = node.uniqueId();
272 //info() << "** ADD BOUNDARY CELL node=" << node_uid << " cell=" << cell->uniqueId();
273 Int32 dest_rank = uid_to_subdomain_converter.uidToRank(node_uid);
274 SharedArray<Int64> v = boundary_infos_to_send.lookupAdd(dest_rank)->value();
275 v.add(node_uid);
276 v.add(cell.owner());
277 v.add(cell.uniqueId());
278 //TODO: supprimer les doublons ?
279 //add_cell = true;
280 //break;
281 }
282 }
283 });
284
285 if (is_verbose)
286 info() << ostr.str();
287
288 info() << "Number of shared faces: " << nb_sub_domain_boundary_face;
289
290 auto exchanger { ParallelMngUtils::createExchangerRef(pm) };
291
292 if (!platform::getEnvironmentVariable("ARCANE_COLLECTIVE_GHOST_LAYER").null())
294
295 _exchangeData(exchanger.get(),boundary_infos_to_send);
296
297 traceMng()->flush();
298 pm->barrier();
299 NodeCellList node_cell_list;
300 {
301 Integer nb_receiver = exchanger->nbReceiver();
302 debug() << "NB RECEIVER=" << nb_receiver;
303 Int64UniqueArray received_infos;
304 for( Integer i=0; i<nb_receiver; ++i ){
305 ISerializeMessage* sm = exchanger->messageToReceive(i);
306 //Int32 orig_rank = sm->destSubDomain();
307 ISerializer* s = sm->serializer();
309 s->getArray(received_infos);
310 Int64 nb_info = received_infos.largeSize();
311 //info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank;
312 if ((nb_info % 3)!=0)
313 ARCANE_FATAL("Inconsistent received data v={0}",nb_info);
314 Int64 nb_info_true = nb_info / 3;
315 for( Int64 z=0; z<nb_info_true; ++z ){
316 Int64 node_uid = received_infos[(z*3)+0];
317 Int64 cell_owner = received_infos[(z*3)+1];
318 Int64 cell_uid = received_infos[(z*3)+2];
319 node_cell_list.add(node_uid,cell_uid,cell_owner);
320 }
321 }
322 }
323
324 boundary_infos_to_send = BoundaryInfosMap(1000,true);
325
326 {
327 Int64ConstArrayView cell_indexes = node_cell_list.m_cell_indexes;
328 debug() << "NB_CELL_INDEXES = " << cell_indexes.size();
329 //for( Integer i=0, s=cell_indexes.size(); i<s; ++i )
330 //info() << "INDEX I=" << i << " V=" << cell_indexes[i];
331 Int32UniqueArray ranks;
332 Int64UniqueArray cells;
333 for( HashTableMapEnumeratorT<Int64,Int32> i_map(node_cell_list.m_cell_last_index); ++i_map; ){
334 HashTableMapT<Int64,Int32>::Data* d = i_map.data();
335 Int32 index = d->value();
336 Int64 node_uid = d->key();
337 //info() << "NODE UID=" << node_uid;
338 ranks.clear();
339 cells.clear();
340 // Comme on connait la liste des mailles connectées à ce noeud ainsi que leur
341 // propriétaire, en profite pour calculer le propriètaire du noeud en considérant
342 // qu'il s'agit du même propriétaire que celui de la maille de plus petit uniqueId()
343 // connecté à ce noeud.
344 Int32 node_new_owner = NULL_SUB_DOMAIN_ID;
345 Int64 smallest_cell_uid = NULL_ITEM_UNIQUE_ID;
346 //TODO ajouter securite en calculant le nombre max de valeurs
347 while(index!=(-1)){
348 Int64 cell_uid = cell_indexes[index];
349 Int32 cell_owner = CheckedConvert::toInt32(cell_indexes[index+1]);
350 index = CheckedConvert::toInteger(cell_indexes[index+2]);
351 //info() << " CELLS: uid=" << cell_uid << " owner=" << cell_owner;
352 ranks.add((Int32)cell_owner);
353 cells.add(cell_uid);
354 if (cell_uid<smallest_cell_uid || node_new_owner==NULL_SUB_DOMAIN_ID){
355 smallest_cell_uid = cell_uid;
356 node_new_owner = cell_owner;
357 }
358 }
359 // Tri les rangs puis supprime les doublons
360 std::sort(std::begin(ranks),std::end(ranks));
361 Integer new_size = CheckedConvert::toInteger(std::unique(std::begin(ranks),std::end(ranks)) - std::begin(ranks));
362 ranks.resize(new_size);
363 //info() << "NEW_SIZE=" << new_size;
364 //for( Integer z=0; z<new_size; ++z )
365 //info() << "NEW_RANK=" << ranks[z];
366
367 // Si le nombre de rang vaut 1, cela signifie que le noeud n'appartient qu'à un seul sous-domaine
368 // et donc il s'agit d'un vrai noeud frontière. Il n'y a pas besoin de transférer ses mailles.
369 if (new_size==1)
370 continue;
371 Integer nb_cell = cells.size();
372 for( Integer z=0; z<new_size; ++z ){
373 Int32 dest_rank = ranks[z];
374 //info() << "NEW_RANK=" << dest_rank;
375 Int64Array& v = boundary_infos_to_send.lookupAdd(dest_rank)->value();
376 v.add(node_uid);
377 v.add(node_new_owner);
378 v.add(new_size);
379 v.add(nb_cell);
380 for( Integer z2=0; z2<new_size; ++z2 )
381 v.add(ranks[z2]);
382 for( Integer z2=0; z2<nb_cell; ++z2 )
383 v.add(cells[z2]);
384 }
385 }
386 }
387
389 _exchangeData(exchanger.get(),boundary_infos_to_send);
390 debug() << "END OF EXCHANGE";
391
392 typedef HashTableMapT<Int32,SharedArray<Int32> > SubDomainItemMap;
393 SubDomainItemMap cells_to_send(50,true);
394 {
395 Integer nb_receiver = exchanger->nbReceiver();
396 debug() << "NB RECEIVER 2 =" << nb_receiver;
397 Int64UniqueArray received_infos;
398 //HashTableMapT<Int64,Int32> nodes_nb_cell(1000,true);
399 for( Integer i=0; i<nb_receiver; ++i ){
400 ISerializeMessage* sm = exchanger->messageToReceive(i);
401 //Int32 orig_rank = sm->destSubDomain();
402 ISerializer* s = sm->serializer();
404 //info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank;
405 s->getArray(received_infos);
406 Int64 nb_info = received_infos.largeSize();
407 Int64 z = 0;
408 Int32UniqueArray ranks;
409 Int32UniqueArray cells;
410 while (z<nb_info){
411 Int64 node_uid = received_infos[z];
412 Int32 node_new_owner = CheckedConvert::toInt32(received_infos[z+1]);
413 Int32 nb_rank = CheckedConvert::toInt32(received_infos[z+2]);
414 Int32 nb_cell = CheckedConvert::toInt32(received_infos[z+3]);
415 //info() << "RECEIVE NODE uid="<< node_uid << " nb_rank=" << nb_rank << " nb_cell=" << nb_cell;
416 nodes_map.findItem(node_uid).toMutable().setOwner(node_new_owner, my_rank);
417 ranks.clear();
418 cells.clear();
419 z += 4;
420 for( Integer z2=0; z2<nb_rank; ++z2 ){
421 Int32 nrank = (Int32)received_infos[z+z2];
422 if (nrank!=my_rank)
423 ranks.add(nrank);
424 }
425 z += nb_rank;
426 for( Integer z2=0; z2<nb_cell; ++z2 ){
427 Int64 cell_uid = received_infos[z+z2];
428 impl::ItemBase dcell = cells_map.tryFind(cell_uid);
429 if (!dcell.null())
430 cells.add(dcell.localId());
431 }
432 for( Integer z2=0,zs=ranks.size(); z2<zs; ++z2 ){
433 SubDomainItemMap::Data* d = cells_to_send.lookupAdd(ranks[z2]);
434 SharedArray<Int32> dv = d->value();
435 for( Integer z3=0, zs3=cells.size(); z3<zs3; ++z3 )
436 dv.add(cells[z3]);
437 }
438 z += nb_cell;
439 }
440 }
441 }
442
443 // Envoie et réceptionne les mailles fantômes
444 _exchangeCells(cells_to_send, false);
445 m_mesh_internal->printStats(TraceMessage::DEFAULT_LEVEL);
446}
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
451void GhostLayerBuilder::
452_exchangeCells(HashTableMapT<Int32,SharedArray<Int32>>& cells_to_send,bool with_flags)
453{
454 //TODO: fusionner avec GhostLayerBuilder2::_exchangeCells().
455 typedef HashTableMapT<Int32,SharedArray<Int32>> SubDomainItemMap;
456 IParallelMng* pm = m_mesh->parallelMng();
457 auto exchanger { ParallelMngUtils::createExchangerRef(pm) };
458 for( SubDomainItemMap::Enumerator i_map(cells_to_send); ++i_map; ){
459 Int32 sd = i_map.data()->key();
460 // TODO: items peut contenir des doublons et donc il faudrait les supprimer
461 // pour éviter d'envoyer inutilement plusieurs fois la même maille.
462 Int32ConstArrayView items = i_map.data()->value();
463 info(4) << "CELLS TO SEND SD=" << sd << " NB=" << items.size();
464 exchanger->addSender(sd);
465 }
467 for( Integer i=0, ns=exchanger->nbSender(); i<ns; ++i ){
468 ISerializeMessage* sm = exchanger->messageToSend(i);
469 Int32 rank = sm->destination().value();
470 ISerializer* s = sm->serializer();
471 Int32ConstArrayView items_to_send = cells_to_send[rank];
472 ScopedPtrT<IItemFamilySerializer> cell_serializer(m_mesh->cellFamily()->policyMng()->createSerializer(with_flags));
473 s->setMode(ISerializer::ModeReserve);
474 cell_serializer->serializeItems(s,items_to_send);
475 s->allocateBuffer();
476 s->setMode(ISerializer::ModePut);
477 cell_serializer->serializeItems(s,items_to_send);
478 }
479 exchanger->processExchange();
480 info(4) << "END EXCHANGE CELLS";
481 for( Integer i=0, ns=exchanger->nbReceiver(); i<ns; ++i ){
482 ISerializeMessage* sm = exchanger->messageToReceive(i);
483 ISerializer* s = sm->serializer();
485 ScopedPtrT<IItemFamilySerializer> cell_serializer(m_mesh->cellFamily()->policyMng()->createSerializer(with_flags));
486 cell_serializer->deserializeItems(s,nullptr);
487 }
488}
489
490/*---------------------------------------------------------------------------*/
491/*---------------------------------------------------------------------------*/
492
495{
496 info() << "** AMR GHOST CHILD FROM PARENT BUILDER V1";
497
498 IParallelMng* pm = m_mesh->parallelMng();
499 debug() << " RANK="<< pm->commRank() << " size=" << pm->commSize();
500 if (!pm->isParallel()){
501 debug() << "NOT PARALLEL";
502 return;
503 }
504 Integer sid = pm->commRank();
505
506 // Marque les noeuds sur la frontière
507 ItemInternalMap& cells_map = m_mesh_internal->cellsMap();
508
509 FaceFamily& true_face_family = m_mesh_internal->trueFaceFamily();
510
511 //TODO: choisir bonne valeur pour initialiser la table
512 BoundaryInfosMap boundary_infos_to_send(200,true);
513
514 cells_map.eachItem([&](Item cell) {
515 ARCANE_ASSERT((cell.owner() != -1), (""));
516 if (cell.itemBase().level() == 0 && cell.owner() != sid) {
517 ARCANE_ASSERT((cell.owner() != -1), (""));
518 Int64Array& v = boundary_infos_to_send.lookupAdd(cell.owner())->value();
519 v.add(sid);
520 v.add(cell.uniqueId());
521 }
522 });
523
524 // Positionne la liste des envois
525 auto exchanger { ParallelMngUtils::createExchangerRef(pm) };
526 _exchangeData(exchanger.get(),boundary_infos_to_send);
527
528 traceMng()->flush();
529 pm->barrier();
530
531 typedef HashTableMapT<Int32,SharedArray<Int32> > SubDomainItemMap;
532 SubDomainItemMap cells_to_send(50,true);
533 {
534 Integer nb_receiver = exchanger->nbReceiver();
535 debug() << "NB RECEIVER=" << nb_receiver;
536 Int64UniqueArray received_infos;
537 for( Integer i=0; i<nb_receiver; ++i ){
538 ISerializeMessage* sm = exchanger->messageToReceive(i);
539 ISerializer* s = sm->serializer();
541 s->getArray(received_infos);
542 Int64 nb_info = received_infos.size();
543 //Int32 orig_rank = sm->destSubDomain();
544 //info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank;
545 if ((nb_info % 2)!=0)
546 ARCANE_FATAL("info size can not be divided by 2 v={0}",nb_info);
547 Int64 nb_info_true = nb_info / 2;
548 Integer nb_recv_child=0;
549 for( Int64 z=0; z<nb_info_true; ++z ){
550 Int32 cell_owner = CheckedConvert::toInt32(received_infos[(z*2)+0]);
551 Int64 cell_uid = received_infos[(z*2)+1];
552
553 impl::ItemBase cell = cells_map.findItem(cell_uid);
554 ARCANE_ASSERT((cell.uniqueId() == cell_uid), (""));
555 if (!cell.hasHChildren())
556 continue;
557 UniqueArray<ItemInternal*> cell_family;
558 ARCANE_ASSERT((cell.level() == 0), (""));
559 ARCANE_ASSERT((cell.owner() != -1), ("CELL"));
560 ARCANE_ASSERT((cell_owner != -1),("CELL"));
561 true_face_family.familyTree(cell_family,cell);
562 SubDomainItemMap::Data* d = cells_to_send.lookupAdd(cell_owner);
563 Int32Array& dv = d->value();
564 const Integer cs=cell_family.size();
565 nb_recv_child +=cs;
566 for(Integer c=1;c<cs;c++){
567 ItemInternal* child= cell_family[c];
568 ARCANE_ASSERT((child->owner() != -1),("CHILD"));
569 //debug() << child->topHParent()->uniqueId() << " " << cell->uniqueId() << " " << child->topHParent()->owner() << " " << cell->owner();
570 //ARCANE_ASSERT((child->topHParent() == cell),("CHILD"));
571 dv.add(child->localId());
572 }
573 cell_family.clear();
574 }
575 debug() << "nb_recv_child= " << nb_recv_child;
576 }
577 }
578 // Envoie et réceptionne les mailles fantômes
579 _exchangeCells(cells_to_send, true);
580 m_mesh_internal->printStats(TraceMessage::DEFAULT_LEVEL);
581}
582
583/*---------------------------------------------------------------------------*/
584/*---------------------------------------------------------------------------*/
585/*---------------------------------------------------------------------------*/
586/*---------------------------------------------------------------------------*/
587void GhostLayerBuilder::
588addGhostChildFromParent2(Array<Int64>& ghost_cell_to_refine)
589{
590 info() << "** AMR GHOST CHILD FROM PARENT BUILDER V2";
591
592 IParallelMng* pm = m_mesh->parallelMng();
593 debug() << " RANK="<< pm->commRank() << " size=" << pm->commSize();
594 if (!pm->isParallel()){
595 debug() << "NOT PARALLEL";
596 return;
597 }
598 Integer sid = pm->commRank();
599
600 // Marque les noeuds sur la frontière
601 ItemInternalMap& cells_map = m_mesh_internal->cellsMap();
602
603 //TODO: choisir bonne valeur pour initialiser la table
604 BoundaryInfosMap boundary_infos_to_send(200,true);
605 // mailles de niveau 0 ne sont pas concernée
606 // que les mailles actives de niveau supérieur a 0 sont concernees
607 // que les mailles qui viennent d'être raffinées ou dé-raffinées sont concernées
608 cells_map.eachItem([&](Item cell) {
609 ARCANE_ASSERT((cell.owner() != -1), (""));
610 if (cell.owner() == sid)
611 return;
612 // cela suppose que les flags sont deja synchronises
614 // cell to add
615 ghost_cell_to_refine.add(cell.uniqueId());
616 Int64Array& v = boundary_infos_to_send.lookupAdd(cell.owner())->value();
617 v.add(sid);
618 v.add(cell.uniqueId());
619 }
620 });
621
622 // Positionne la liste des envois
623 auto exchanger{ ParallelMngUtils::createExchangerRef(pm) };
624 _exchangeData(exchanger.get(), boundary_infos_to_send);
625
626 traceMng()->flush();
627 pm->barrier();
628
629 typedef HashTableMapT<Int32,SharedArray<Int32> > SubDomainItemMap;
630 SubDomainItemMap cells_to_send(50,true);
631 {
632 Integer nb_receiver = exchanger->nbReceiver();
633 debug() << "NB RECEIVER=" << nb_receiver;
634 Int64UniqueArray received_infos;
635 for( Integer i=0; i<nb_receiver; ++i ){
636 ISerializeMessage* sm = exchanger->messageToReceive(i);
637 //Int32 orig_rank = sm->destSubDomain();
638 ISerializer* s = sm->serializer();
640 //info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank;
641 s->getArray(received_infos);
642 Int64 nb_info = received_infos.size();
643 if ((nb_info % 2)!=0)
644 ARCANE_FATAL("info size can not be divided by 2 v={0}",nb_info);
645 Int64 nb_info_true = nb_info / 2;
646 Integer nb_recv_child = 0;
647 for( Int64 z=0; z<nb_info_true; ++z ){
648 Int32 cell_owner = CheckedConvert::toInt32(received_infos[(z*2)+0]);
649 Int64 cell_uid = received_infos[(z*2)+1];
650
651 Cell cell = cells_map.findItem(cell_uid);
652 ARCANE_ASSERT((cell.uniqueId() == cell_uid),(""));
653 ARCANE_ASSERT((cell.owner() != -1),("CELL"));
654 ARCANE_ASSERT((cell_owner != -1),("CELL"));
655
656 SubDomainItemMap::Data* d = cells_to_send.lookupAdd(cell_owner);
657 Int32Array& dv = d->value();
658
659 nb_recv_child +=cell.nbHChildren();
660 for(Integer c=0,cs=cell.nbHChildren();c<cs;c++){
661 Cell child= cell.hChild(c);
662 ARCANE_ASSERT((child.owner() != -1),("CHILD"));
663 //debug() << child->topHParent()->uniqueId() << " " << cell->uniqueId() << " " << child->topHParent()->owner() << " " << cell->owner();
664 //ARCANE_ASSERT((child->topHParent() == cell),("CHILD"));
665 dv.add(child.localId());
666 }
667 }
668 debug() << "nb_recv_child= " << nb_recv_child;
669 }
670 }
671
672 // Envoie et réceptionne les mailles fantômes
673 _exchangeCells(cells_to_send, true);
674 m_mesh_internal->printStats(TraceMessage::DEFAULT_LEVEL);
675}
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
679/*---------------------------------------------------------------------------*/
680
681NodeUidToSubDomain::
682NodeUidToSubDomain(Int64 max_uid,Int32 nb_rank)
683: m_nb_rank(nb_rank)
684, m_modulo(1)
685, m_nb_by_rank(max_uid)
686{
687 m_nb_by_rank = max_uid / nb_rank;
688 if (m_nb_by_rank==0)
689 m_nb_by_rank = max_uid;
690 m_modulo = nb_rank;
691 Integer div_value = 1;
692 if (m_nb_rank>4)
693 div_value = 2;
694 String s = platform::getEnvironmentVariable("ARCANE_INIT_RANK_GROUP_SIZE");
695 if (!s.null()){
696 bool is_ok = builtInGetValue(div_value,s);
697 if (is_ok){
698 if (div_value<0)
699 div_value = 1;
700 if (div_value>m_nb_rank)
701 div_value = m_nb_rank;
702 }
703 }
704 m_modulo = m_nb_rank / div_value;
705}
706
707/*---------------------------------------------------------------------------*/
708/*---------------------------------------------------------------------------*/
709
710} // End namespace Arcane::mesh
711
712/*---------------------------------------------------------------------------*/
713/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur le maillage.
Integer size() const
Nombre d'éléments du vecteur.
Tableau d'items de types quelconques.
void clear()
Supprime les éléments du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
Table de hachage pour tableaux associatifs.
Data * lookupAdd(KeyTypeConstRef id, const ValueType &value, bool &is_add)
Recherche ou ajoute la valeur correspondant à la clé id.
virtual Integer builderVersion() const =0
Version du constructeur de mailles fantômes.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IGhostLayerMng * ghostLayerMng() const =0
Gestionnare de couche fantômes associé
Échange d'informations entre processeurs.
virtual void addSender(Int32 rank)=0
Ajoute un processeur à envoyer.
@ EM_Collective
Utilise les opération collectives (allToAll).
virtual Integer nbSender() const =0
Nombre de processeurs auquel on envoie.
virtual void setExchangeMode(eExchangeMode mode)=0
Positionne le mode d'échange.
virtual Integer nbReceiver() const =0
Nombre de processeurs dont on va réceptionner les messages.
virtual bool initializeCommunicationsMessages()=0
Calcule les communications.
virtual ISerializeMessage * messageToSend(Integer i)=0
Message destiné au ième processeur.
virtual void processExchange()=0
Effectue l'échange avec les options par défaut de ParallelExchangerOptions.
virtual ISerializeMessage * messageToReceive(Integer i)=0
Message reçu du ième processeur.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual void barrier()=0
Effectue une barière.
virtual void putArray(Span< const Real > values)=0
Sauve le nombre d'éléments et les values éléments.
virtual void reserveArray(Span< const Real > values)=0
Réserve pour sauver le nombre d'éléments et les values éléments.
virtual void getArray(Array< Real > &values)=0
Redimensionne et remplit values.
@ ModePut
Le sérialiseur attend des reserve().
virtual void allocateBuffer()=0
Alloue la mémoire du sérialiseur.
virtual void setMode(eMode new_mode)=0
Positionne le fonctionnement actuel.
virtual void flush()=0
Flush tous les flots.
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Int32 level() const
Int32 localId() const
Numéro local (au sous-domaine) de l'entité
@ II_Shared
L'entité est partagée par un autre sous-domaine.
Definition ItemFlags.h:58
@ II_SubDomainBoundary
L'entité est à la frontière de deux sous-domaines.
Definition ItemFlags.h:59
@ II_JustRefined
L'entité vient d'être raffinée.
Definition ItemFlags.h:78
@ II_Boundary
L'entité est sur la frontière.
Definition ItemFlags.h:50
Structure interne d'une entité de maillage.
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:238
constexpr bool hasFlags(Int32 flags) const
Retourne si les flags flags sont positionnées pour l'entité
Definition Item.h:338
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:369
Interface d'un message de sérialisation entre IMessagePassingMng.
virtual MessageRank destination() const =0
Rang du destinataire (si isSend() est vrai) ou de l'envoyeur.
virtual ISerializer * serializer()=0
Sérialiseur.
Int32 value() const
Valeur du rang.
Definition MessageRank.h:72
Exception lorsqu'une opération n'est pas supportée.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Famille de faces.
Definition FaceFamily.h:53
GhostLayerBuilder(IMesh *mesh)
Construit une instance pour le maillage mesh.
impl::ItemBase findItem(Int64 uid) const
Retourne l'entité de numéro unique uid.
void eachItem(const Lambda &lambda)
Fonction template pour itérer sur les entités de l'instance.
@ ReduceMax
Maximum des valeurs.
Ref< IParallelExchanger > createExchangerRef(IParallelMng *pm)
Retourne une interface pour transférer des messages entre rangs.
Real getRealTime()
Temps Real utilisé en secondes.
String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:119
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:337
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:480
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:478
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:339
double Real
Type représentant un réel.
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:121
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52
std::int32_t Int32
Type entier signé sur 32 bits.