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"
68, m_mesh(mesh_builder->
mesh())
69, m_mesh_builder(mesh_builder)
87void GhostLayerBuilder::
88addGhostLayers(
bool is_allocate)
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");
107 Real diff = (
Real)(end_time - begin_time);
108 info() <<
"TIME to compute ghost layer=" << diff;
120 NodeCellList() : m_cell_last_index(5000,
true) {}
126 Int32 current_index = m_cell_indexes.size();
127 m_cell_indexes.add(cell_uid);
128 m_cell_indexes.add(cell_owner);
131 m_cell_indexes.add(d->value());
132 d->value() = current_index;
143void GhostLayerBuilder::
146 for( BoundaryInfosMapEnumerator i_map(boundary_infos_to_send); ++i_map; ){
147 Int32 sd = i_map.data()->key();
158 s->
setMode(ISerializer::ModeReserve);
168 debug() <<
"END EXCHANGE";
174void GhostLayerBuilder::
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");
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";
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();
208 faces_map.eachItem([&](Face face) {
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;
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;
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 ){
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;
455 IParallelMng* pm = m_mesh->parallelMng();
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();
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";
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";
508 ItemInternalMap& cells_map = m_mesh->cellsMap();
510 FaceFamily& true_face_family = m_mesh->trueFaceFamily();
513 BoundaryInfosMap boundary_infos_to_send(200,
true);
516 ARCANE_ASSERT((cell.
owner() != -1), (
""));
518 ARCANE_ASSERT((cell.
owner() != -1), (
""));
527 _exchangeData(exchanger.get(),boundary_infos_to_send);
533 SubDomainItemMap cells_to_send(50,
true);
536 debug() <<
"NB RECEIVER=" << nb_receiver;
538 for(
Integer i=0; i<nb_receiver; ++i ){
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;
550 for(
Int64 z=0; z<nb_info_true; ++z ){
552 Int64 cell_uid = received_infos[(z*2)+1];
554 impl::ItemBase cell = cells_map.
findItem(cell_uid);
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"));
562 true_face_family.familyTree(cell_family,cell);
563 SubDomainItemMap::Data* d = cells_to_send.lookupAdd(cell_owner);
569 ARCANE_ASSERT((child->
owner() != -1),(
"CHILD"));
576 debug() <<
"nb_recv_child= " << nb_recv_child;
580 _exchangeCells(cells_to_send,
true);
581 m_mesh_builder->printStats();
588void GhostLayerBuilder::
589addGhostChildFromParent2(
Array<Int64>& ghost_cell_to_refine)
591 info() <<
"** AMR GHOST CHILD FROM PARENT BUILDER V2";
596 debug() <<
"NOT PARALLEL";
602 ItemInternalMap& cells_map = m_mesh->cellsMap();
605 BoundaryInfosMap boundary_infos_to_send(200,
true);
609 cells_map.eachItem([&](
Item cell) {
610 ARCANE_ASSERT((cell.
owner() != -1), (
""));
611 if (cell.
owner() == sid)
617 Int64Array& v = boundary_infos_to_send.lookupAdd(cell.
owner())->value();
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 ){
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;
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.
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.
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 void barrier()=0
Effectue une barière.
Interface d'un sérialiseur.
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()
@ ModeGet
Le sérialiseur attend des get()
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 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é.
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.
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).
Construction d'un maillage de manière incrémentale.
Implémentation d'un maillage.
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.
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.
Integer toInteger(Real r)
Converti un Int64 en un Integer.
Int32 toInt32(Int64 v)
Converti un Int64 en un Int32.
@ ReduceMax
Maximum des valeurs.
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.
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.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
double Real
Type représentant un réel.
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
std::int32_t Int32
Type entier signé sur 32 bits.