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