14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/ScopedPtr.h"
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/OStringStream.h"
19#include "arcane/mesh/DynamicMesh.h"
20#include "arcane/mesh/EdgeUniqueIdBuilder.h"
21#include "arcane/mesh/GhostLayerBuilder.h"
22#include "arcane/mesh/OneMeshItemAdder.h"
24#include "arcane/core/IParallelExchanger.h"
25#include "arcane/core/IParallelMng.h"
26#include "arcane/core/ISerializeMessage.h"
27#include "arcane/core/ISerializer.h"
28#include "arcane/core/ParallelMngUtils.h"
29#include "arcane/core/IMeshUniqueIdMng.h"
56void EdgeUniqueIdBuilder::
57computeEdgesUniqueIds()
64 <<
" mesh=" << m_mesh->
name();
67 _computeEdgesUniqueIdsParallel3();
69 _computeEdgesUniqueIdsParallelV2();
71 _computeEdgesUniqueIdsParallel64bit();
73 info() <<
"No renumbering for edges";
75 ARCANE_FATAL(
"Invalid valid version '{0}'. Valid values are 0, 1, 2 or 3");
77 double end_time = platform::getRealTime();
79 info() <<
"TIME to compute edge unique ids=" <<
diff;
87 if (m_mesh_builder->isVerbose()) {
88 info() <<
"NEW EDGES_MAP after re-indexing";
117 : m_unique_id(NULL_ITEM_ID)
119 , m_nb_true_boundary_edge(0)
127 return m_unique_id <
ci.m_unique_id;
133 Int64 m_nb_back_edge;
134 Int64 m_nb_true_boundary_edge;
137template <
typename DataType>
147 MyInfo(
const DataType& d, Integer n)
161 : m_last_index(5000,
true)
166 void add(Int64 node_uid,
const DataType& data)
173 m_values.add(MyInfo(data, d->value()));
189 using BoundaryInfosMap = std::unordered_map<Int32, SharedArray<Int64>>;
205 const Int32 m_my_rank = A_NULL_RANK;
206 const Int32 m_nb_rank = A_NULL_RANK;
207 BoundaryInfosMap m_boundary_infos_to_send;
209 std::unordered_map<Int64, SharedArray<Int64>> m_nodes_info;
211 bool m_is_verbose =
false;
216 void _addEdgeBoundaryInfo(
Edge edge);
217 void _computeEdgesUniqueId();
218 void _sendInfosToOtherRanks();
224Parallel3EdgeUniqueIdBuilder::
229, m_parallel_mng(m_mesh->parallelMng())
230, m_my_rank(m_parallel_mng->commRank())
231, m_nb_rank(m_parallel_mng->commSize())
232, m_uid_to_subdomain_converter(max_node_uid, m_nb_rank)
233, m_is_verbose(m_mesh_builder->isVerbose())
246 for (
const auto& [key, value] : m_boundary_infos_to_send) {
251 for (Integer i = 0, ns = exchanger->
nbSender(); i < ns; ++i) {
253 Int32 rank =
sm->destination().value();
256 Integer
nb_info = infos.size();
257 s->
setMode(ISerializer::ModeReserve);
268 debug() <<
"END EXCHANGE";
274void Parallel3EdgeUniqueIdBuilder::
275_addEdgeBoundaryInfo(
Edge edge)
281 if (!m_is_boundary_nodes[
first_node.localId()]) {
288 v.add(first_node_uid);
292 v.add(NULL_ITEM_UNIQUE_ID);
293 v.add(NULL_ITEM_UNIQUE_ID);
296 <<
" n0=" << ItemPrinter(edge.
node(0)) <<
" n1=" << ItemPrinter(edge.
node(1)) <<
" dest_rank=" << dest_rank;
297 for (Node edge_node : edge.nodes())
298 v.add(edge_node.uniqueId());
322 Integer
nb_local_edge = m_mesh_builder->oneMeshItemAdder()->nbEdge();
368 m_is_boundary_nodes[
ilid] =
true;
383 info() <<
"Edge: ItemInternalMap is using new implementation";
389 _addEdgeBoundaryInfo(edge);
394 _addEdgeBoundaryInfo(edge);
398 _computeEdgesUniqueId();
399 _sendInfosToOtherRanks();
403 info() <<
"END OF TEST NEW EDGE COMPUTE";
409void Parallel3EdgeUniqueIdBuilder::
410_computeEdgesUniqueId()
454 for (
const auto& [key, value] : m_nodes_info) {
461 while (z < nb_info) {
469 ItemTypeInfo* itt = itm->
typeFromId(edge_type);
470 Integer edge_nb_node = itt->nbLocalNode();
478 my_max_edge_node =
math::max(node_nb_edge, my_max_edge_node);
480 Integer global_max_edge_node = pm->
reduce(Parallel::ReduceMax, my_max_edge_node);
481 debug() <<
"GLOBAL MAX EDGE NODE=" << global_max_edge_node;
484 m_boundary_infos_to_send.clear();
486 for (
const auto& [key, value] : m_nodes_info) {
492 while (z < nb_info) {
493 Int64 node_uid = a[z + 0];
495 Int64 edge_uid = a[z + 2];
499 ItemTypeInfo* itt = itm->
typeFromId(edge_type);
500 Integer edge_nb_node = itt->nbLocalNode();
503 Integer edge_index = node_nb_edge;
504 Int32 edge_new_owner = sender_rank;
505 for (Integer y = 0; y < node_nb_edge; ++y) {
506 if (memcmp(&a[indexes[y] + 6], &a[z + 6],
sizeof(
Int64) * edge_nb_node) == 0) {
508 edge_new_owner = (
Int32)a[indexes[y] + 1];
511 Int64 edge_new_uid = (node_uid * global_max_edge_node) + edge_index;
512 Int64Array& v = m_boundary_infos_to_send[sender_rank];
516 v.add(edge_new_owner);
526 my_max_edge_node =
math::max(node_nb_edge, my_max_edge_node);
533void Parallel3EdgeUniqueIdBuilder::
534_sendInfosToOtherRanks()
536 const bool is_verbose = m_mesh_builder->isVerbose();
537 IParallelMng* pm = m_parallel_mng;
542 ItemInternalMap& edges_map = m_mesh->edgesMap();
543 Integer nb_receiver = exchanger->nbReceiver();
544 debug() <<
"NB RECEIVER=" << nb_receiver;
546 for (Integer i = 0; i < nb_receiver; ++i) {
547 ISerializeMessage* sm = exchanger->messageToReceive(i);
549 ISerializer* s = sm->serializer();
551 Int64 nb_info = s->getInt64();
553 info() <<
"RECEIVE NB_INFO=" << nb_info <<
" from=" << orig_rank;
554 received_infos.resize(nb_info);
555 s->getSpan(received_infos);
556 if ((nb_info % 3) != 0)
557 ARCANE_FATAL(
"info size can not be divided by 3 x={0}", nb_info);
558 Int64 nb_item = nb_info / 3;
559 for (
Int64 z = 0; z < nb_item; ++z) {
560 Int64 old_uid = received_infos[(z * 3)];
561 Int64 new_uid = received_infos[(z * 3) + 1];
562 Int32 new_owner =
static_cast<Int32>(received_infos[(z * 3) + 2]);
564 impl::MutableItemBase iedge(edges_map.tryFind(old_uid));
567 iedge.setUniqueId(new_uid);
568 iedge.setOwner(new_owner, m_my_rank);
571 info() <<
"SetEdgeOwner uid=" << new_uid <<
" owner=" << new_owner
573 <<
" n0=" << ItemPrinter(edge.
node(0)) <<
" n1=" << ItemPrinter(edge.
node(1));
588 bool is_verbose = m_mesh_builder->isVerbose();
589 Integer
nb_cell = m_mesh_builder->oneMeshItemAdder()->nbCell();
597 Int32 cell_uid = cell.
uniqueId().asInt32();
607 Int32 cell_uid = cell.
uniqueId().asInt32();
610 for(
Edge edge : cell.edges()){
613 else if (edge.
nbCell()==1){
622 for( Integer i=0; i<
nb_cell; ++i ){
628 for( Integer i=0; i<
nb_cell; ++i ){
629 info() <<
"Recv: Cell EdgeInfo celluid=" << i
637 Int32 cell_uid = cell.
uniqueId().asInt32();
640 for(
Edge edge : cell.edges() ){
647 else if (edge.
nbCell()==1){
662 Int32 cell_uid = cell.
uniqueId().asInt32();
670 else if (edge.
nbCell()==1){
677 ostr() <<
"NEW LOCAL ID FOR CELLEDGE " << cell_uid <<
' '
678 << index <<
' ' << edge.
uniqueId() <<
" (";
680 ostr() <<
' ' << node.uniqueId();
684 ostr() <<
" internal-other";
686 ostr() <<
" true-boundary";
700void EdgeUniqueIdBuilder::
701_computeEdgesUniqueIdsParallelV2()
727 Node node1{edge.
node(1)};
728 Int64 new_uid = (node0.uniqueId().asInt64() * total_max_uid) + node1.uniqueId().asInt64();
736void EdgeUniqueIdBuilder::
737_computeEdgesUniqueIdsParallel3()
740 ItemInternalMap& nodes_map = m_mesh->nodesMap();
743 Int64 my_max_node_uid = NULL_ITEM_UNIQUE_ID;
744 nodes_map.eachItem([&](Item item) {
745 Int64 node_uid = item.uniqueId();
746 if (node_uid > my_max_node_uid)
747 my_max_node_uid = node_uid;
749 Int64 global_max_node_uid = pm->
reduce(Parallel::ReduceMax, my_max_node_uid);
750 debug() <<
"NODE_UID_INFO: MY_MAX_UID=" << my_max_node_uid
751 <<
" GLOBAL=" << global_max_node_uid;
753 Parallel3EdgeUniqueIdBuilder builder(
traceMng(), m_mesh_builder, global_max_node_uid);
760void EdgeUniqueIdBuilder::
761_computeEdgesUniqueIdsParallel64bit()
765 ItemInternalMap& edges_map = m_mesh->edgesMap();
767 std::hash<Int64> hasher;
770 Node node0{edge.node(0)};
771 Node node1{edge.node(1)};
772 size_t hash0 = hasher(node0.uniqueId().asInt64());
773 size_t hash1 = hasher(node1.uniqueId().asInt64());
774 hash0 ^= hash1 + 0x9e3779b9 + (hash0 << 6) + (hash0 >> 2);
775 Int64 new_uid = hash0 & 0x7fffffff;
776 edge.mutableItemBase().setUniqueId(new_uid);
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Tableau d'items de types quelconques.
EdgeConnectedListViewType edges() const
Liste des arêtes de la maille.
Int32 nbCell() const
Nombre de mailles connectées à l'arête.
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
Data * lookupAdd(KeyTypeConstRef id, const ValueType &value, bool &is_add)
Recherche ou ajoute la valeur correspondant à la clé id.
Interface d'une famille d'entités.
virtual Integer edgeBuilderVersion() const =0
Version de la numérotation des arêtes.
Echange d'informations entre processeurs.
virtual void addSender(Int32 rank)=0
Ajoute un processeur à envoyer.
virtual Integer nbSender() const =0
Nombre de processeurs auquel on envoie.
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.
Interface du gestionnaire de parallélisme pour un sous-domaine.
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.
ItemUniqueId uniqueId() const
Numéro unique de l'entité
ItemBase backCell() const
Maille derrière l'entité (nullItem() si aucune)
Infos sur un type d'entité du maillage.
Gestionnaire des types d'entités de maillage.
ItemTypeInfo * typeFromId(Integer id) const
Type correspondant au numéro id.
Node node(Int32 i) const
i-ème noeud de l'entité
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
NodeLocalIdView nodeIds() const
Liste des noeuds de l'entité
Classe de base d'un élément de maillage.
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
impl::ItemBase itemBase() const
Partie interne de l'entité.
Int16 type() const
Type de l'entité
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Flot de sortie lié à une String.
Construction d'un maillage de manière incrémentale.
Implémentation d'un maillage.
IItemFamily * nodeFamily() override
Retourne la famille des noeuds.
IParallelMng * parallelMng() override
Gestionnaire de parallèlisme.
String name() const override
Nom du maillage.
ItemTypeMng * itemTypeMng() const override
Gestionnaire de types d'entités associé
IMeshUniqueIdMng * meshUniqueIdMng() const override
Gestionnare de la numérotation des identifiants uniques.
EdgeUniqueIdBuilder(DynamicMeshIncrementalBuilder *mesh_builder)
Construit une instance pour le maillage mesh.
void _computeEdgesUniqueIdsSequential()
Calcul les numéros uniques de chaque edge en séquentiel.
Tableau associatif de ItemInternal.
void eachItem(const Lambda &lambda)
Fonction template pour itérer sur les entités de l'instance.
void _exchangeData(IParallelExchanger *exchanger)
void compute()
Calcule les numéros uniques de chaque edge en parallèle.
Classe d'aide pour la détermination en parallèle des unique_id des edges.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
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 reserveSpan(eDataType dt, Int64 n)=0
Réserve de la mémoire pour n valeurs de dt.
virtual void putSpan(Span< const Real > values)
Ajoute le tableau values.
virtual void getSpan(Span< Real > values)
Récupère le tableau values.
virtual Int64 getInt64()=0
Récupère une taille.
virtual void reserve(eDataType dt, Int64 n)=0
Réserve de la mémoire pour n objets de type dt.
virtual void setMode(eMode new_mode)=0
Positionne le fonctionnement actuel.
virtual void putInt64(Int64 value)=0
Ajoute l'entier value.
Interface du gestionnaire de traces.
virtual void flush()=0
Flush tous les flots.
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.
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).
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
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.
@ DT_Int64
Donnée de type entier 64 bits.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Int32 Integer
Type représentant un entier.