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"
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"
37#include "arcane/mesh/DynamicMesh.h"
38#include "arcane/mesh/GhostLayerBuilder.h"
39#include "arcane/mesh/OneMeshItemAdder.h"
51_buildGhostLayerNewVersion(DynamicMesh* mesh,
bool is_allocate,
Int32 version);
87void GhostLayerBuilder::
96 info() <<
"Use ghost layer builder version 2";
97 _addOneGhostLayerV2();
99 else if (version==3 || version==4){
100 info() <<
"Use GhostLayerBuilder with sort (version " << version <<
")";
101 _buildGhostLayerNewVersion(m_mesh,is_allocate,version);
104 throw NotSupportedException(A_FUNCINFO,
"Bad version number for addGhostLayer");
106 Real end_time = platform::getRealTime();
107 Real diff = (
Real)(end_time - begin_time);
108 info() <<
"TIME to compute ghost layer=" << diff;
124 void add(Int64 node_uid,Int64 cell_uid,Int64 cell_owner)
127 m_cell_indexes.
add(cell_uid);
128 m_cell_indexes.
add(cell_owner);
131 m_cell_indexes.
add(d->value());
143void GhostLayerBuilder::
147 Int32
sd =
i_map.data()->key();
152 for( Integer i=0, ns=exchanger->
nbSender(); i<ns; ++i ){
154 Int32 rank =
sm->destination().value();
158 s->
setMode(ISerializer::ModeReserve);
168 debug() <<
"END EXCHANGE";
174void GhostLayerBuilder::
177 info() <<
"** NEW GHOST LAYER BUILDER V2";
179 ARCANE_THROW(NotImplementedException,
"Only one layer of ghost cells is supported");
186 debug() <<
"NOT PARALLEL";
189#ifdef ARCANE_DEBUG_DYNAMIC_MESH
190 const bool is_verbose =
true;
192 const bool is_verbose =
false;
197 ostr() <<
"** FACES LIST\n";
199 Integer nb_sub_domain_boundary_face = 0;
201 ItemInternalMap& cells_map = m_mesh->cellsMap();
202 ItemInternalMap& faces_map = m_mesh->facesMap();
204 ItemInternalMap& nodes_map = m_mesh->nodesMap();
209 impl::ItemBase face_base = face.itemBase();
211 ostr() << ItemPrinter(face);
214 bool is_sub_domain_boundary_face =
false;
216 is_sub_domain_boundary_face =
true;
219 if (face.nbCell()==2 && (face.cell(0).owner()!=my_rank || face.cell(1).owner()!=my_rank))
220 is_sub_domain_boundary_face =
true;
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);
232 Integer boundary_nodes_uid_count = 0;
235 Int64 my_max_node_uid = NULL_ITEM_UNIQUE_ID;
236 nodes_map.eachItem([&](Node node) {
237 Int32 f = node.itemBase().flags();
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;
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;
253 ostr() <<
"List of shared cells:\n";
258 BoundaryInfosMap boundary_infos_to_send(200,
true);
259 NodeUidToSubDomain uid_to_subdomain_converter(global_max_node_uid,nb_rank);
261 cells_map.eachItem([&](Cell cell) {
263 ostr() <<
"Send cell " << ItemPrinter(cell) <<
'\n';
267 for( Node inode : cell.nodes() ){
270 Int64 node_uid = inode.uniqueId();
272 Int32 dest_rank = uid_to_subdomain_converter.uidToRank(node_uid);
273 SharedArray<Int64> v = boundary_infos_to_send.lookupAdd(dest_rank)->value();
276 v.add(cell.uniqueId());
285 info() << ostr.str();
287 info() <<
"Number of shared faces: " << nb_sub_domain_boundary_face;
291 if (!platform::getEnvironmentVariable(
"ARCANE_COLLECTIVE_GHOST_LAYER").null())
294 _exchangeData(exchanger.get(),boundary_infos_to_send);
298 NodeCellList node_cell_list;
301 debug() <<
"NB RECEIVER=" << nb_receiver;
303 for( Integer i=0; i<nb_receiver; ++i ){
306 ISerializer* s = sm->serializer();
308 s->getArray(received_infos);
309 Int64 nb_info = received_infos.largeSize();
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);
323 boundary_infos_to_send = BoundaryInfosMap(1000,
true);
327 debug() <<
"NB_CELL_INDEXES = " << cell_indexes.size();
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();
343 Int32 node_new_owner = NULL_SUB_DOMAIN_ID;
344 Int64 smallest_cell_uid = NULL_ITEM_UNIQUE_ID;
347 Int64 cell_uid = cell_indexes[index];
351 ranks.add((
Int32)cell_owner);
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;
359 std::sort(std::begin(ranks),std::end(ranks));
361 ranks.resize(new_size);
370 Integer nb_cell = cells.size();
371 for( Integer z=0; z<new_size; ++z ){
372 Int32 dest_rank = ranks[z];
374 Int64Array& v = boundary_infos_to_send.lookupAdd(dest_rank)->value();
376 v.add(node_new_owner);
379 for( Integer z2=0; z2<new_size; ++z2 )
381 for( Integer z2=0; z2<nb_cell; ++z2 )
388 _exchangeData(exchanger.get(),boundary_infos_to_send);
389 debug() <<
"END OF EXCHANGE";
391 typedef HashTableMapT<Int32,SharedArray<Int32> > SubDomainItemMap;
392 SubDomainItemMap cells_to_send(50,
true);
395 debug() <<
"NB RECEIVER 2 =" << nb_receiver;
398 for( Integer i=0; i<nb_receiver; ++i ){
401 ISerializer* s = sm->serializer();
404 s->getArray(received_infos);
405 Int64 nb_info = received_infos.largeSize();
410 Int64 node_uid = received_infos[z];
415 nodes_map.findItem(node_uid).toMutable().setOwner(node_new_owner, my_rank);
419 for( Integer z2=0; z2<nb_rank; ++z2 ){
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);
429 cells.add(dcell.localId());
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 )
443 _exchangeCells(cells_to_send,
false);
444 m_mesh_builder->printStats();
450void GhostLayerBuilder::
451_exchangeCells(HashTableMapT<
Int32,SharedArray<Int32>>& cells_to_send,
bool with_flags)
454 typedef HashTableMapT<Int32,SharedArray<Int32>> SubDomainItemMap;
457 for( SubDomainItemMap::Enumerator i_map(cells_to_send); ++i_map; ){
458 Int32 sd = i_map.data()->key();
462 info(4) <<
"CELLS TO SEND SD=" << sd <<
" NB=" << items.size();
466 for( Integer i=0, ns=exchanger->
nbSender(); i<ns; ++i ){
468 Int32 rank = sm->destination().value();
469 ISerializer* s = sm->serializer();
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);
477 cell_serializer->serializeItems(s,items_to_send);
480 info(4) <<
"END EXCHANGE CELLS";
481 for( Integer i=0, ns=exchanger->
nbReceiver(); i<ns; ++i ){
483 ISerializer* s = sm->serializer();
486 ScopedPtrT<IItemFamilySerializer> cell_serializer(m_mesh->
cellFamily()->
policyMng()->createSerializer(with_flags));
487 cell_serializer->deserializeItems(s,
nullptr);
497 info() <<
"** AMR GHOST CHILD FROM PARENT BUILDER V1";
502 debug() <<
"NOT PARALLEL";
516 ARCANE_ASSERT((cell.
owner() != -1), (
""));
518 ARCANE_ASSERT((cell.
owner() != -1), (
""));
555 ARCANE_ASSERT((cell.uniqueId() == cell_uid), (
""));
556 if (!cell.hasHChildren())
559 ARCANE_ASSERT((cell.level() == 0), (
""));
560 ARCANE_ASSERT((cell.owner() != -1), (
"CELL"));
561 ARCANE_ASSERT((cell_owner != -1),(
"CELL"));
563 SubDomainItemMap::Data* d =
cells_to_send.lookupAdd(cell_owner);
567 for(Integer
c=1;
c<
cs;
c++){
569 ARCANE_ASSERT((child->
owner() != -1),(
"CHILD"));
581 m_mesh_builder->printStats();
588void GhostLayerBuilder::
591 info() <<
"** AMR GHOST CHILD FROM PARENT BUILDER V2";
596 debug() <<
"NOT PARALLEL";
602 ItemInternalMap&
cells_map = m_mesh->cellsMap();
610 ARCANE_ASSERT((cell.
owner() != -1), (
""));
625 _exchangeData(exchanger.get(), boundary_infos_to_send);
630 typedef HashTableMapT<Int32,SharedArray<Int32> > SubDomainItemMap;
631 SubDomainItemMap cells_to_send(50,
true);
634 debug() <<
"NB RECEIVER=" << nb_receiver;
636 for( Integer i=0; i<nb_receiver; ++i ){
639 ISerializer* s = sm->serializer();
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;
648 for(
Int64 z=0; z<nb_info_true; ++z ){
650 Int64 cell_uid = received_infos[(z*2)+1];
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"));
657 SubDomainItemMap::Data* d = cells_to_send.lookupAdd(cell_owner);
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"));
666 dv.add(child.localId());
669 debug() <<
"nb_recv_child= " << nb_recv_child;
674 _exchangeCells(cells_to_send,
true);
675 m_mesh_builder->printStats();
683NodeUidToSubDomain(
Int64 max_uid,
Int32 nb_rank)
686, m_nb_by_rank(max_uid)
688 m_nb_by_rank = max_uid / nb_rank;
690 m_nb_by_rank = max_uid;
695 String s = platform::getEnvironmentVariable(
"ARCANE_INIT_RANK_GROUP_SIZE");
697 bool is_ok = builtInGetValue(div_value,s);
701 if (div_value>m_nb_rank)
702 div_value = m_nb_rank;
705 m_modulo = m_nb_rank / div_value;
#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 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.
@ II_SubDomainBoundary
L'entité est à la frontière de deux sous-domaines.
@ II_JustRefined
L'entité vient d'être raffinée.
@ II_Boundary
L'entité est sur la frontière.
Structure interne d'une entité de maillage.
Classe de base d'un élément de maillage.
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
impl::ItemBase itemBase() const
Partie interne de l'entité.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
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é
void addGhostChildFromParent()
AMR.
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.
Interface d'un sérialiseur.
virtual void allocateBuffer()=0
Alloue la mémoire du sérialiseur.
@ ModePut
Le sérialiseur attend des reserve()
@ ModeGet
Le sérialiseur attend des get()
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.
Interface d'un message de sérialisation entre IMessagePassingMng.
Exception lorsqu'une opération n'est pas supportée.
Classe d'accès aux traces.
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.
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Int32 Integer
Type représentant un entier.