Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
EdgeUniqueIdBuilder.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/* EdgeUniqueIdBuilder.cc (C) 2000-2024 */
9/* */
10/* Construction des identifiants uniques des arêtes. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/ScopedPtr.h"
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/OStringStream.h"
18
19#include "arcane/mesh/DynamicMesh.h"
20#include "arcane/mesh/EdgeUniqueIdBuilder.h"
21#include "arcane/mesh/GhostLayerBuilder.h"
22#include "arcane/mesh/OneMeshItemAdder.h"
23
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"
30
31#include <functional>
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane::mesh
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53/*---------------------------------------------------------------------------*/
54/*---------------------------------------------------------------------------*/
55
56void EdgeUniqueIdBuilder::
57computeEdgesUniqueIds()
58{
59 double begin_time = platform::getRealTime();
60
62
63 info() << "Using version=" << edge_version << " to compute edges unique ids"
64 << " mesh=" << m_mesh->name();
65
66 if (edge_version == 1)
67 _computeEdgesUniqueIdsParallel3();
68 else if (edge_version == 2)
69 _computeEdgesUniqueIdsParallelV2();
70 else if (edge_version == 3)
71 _computeEdgesUniqueIdsParallel64bit();
72 else if (edge_version == 0)
73 info() << "No renumbering for edges";
74 else
75 ARCANE_FATAL("Invalid valid version '{0}'. Valid values are 0, 1, 2 or 3");
76
77 double end_time = platform::getRealTime();
78 Real diff = (Real)(end_time - begin_time);
79 info() << "TIME to compute edge unique ids=" << diff;
80
81 ItemInternalMap& edges_map = m_mesh->edgesMap();
82
83 // Il faut ranger à nouveau #m_edges_map car les uniqueId() des
84 // edges ont été modifiés
85 edges_map.notifyUniqueIdsChanged();
86
87 if (m_mesh_builder->isVerbose()) {
88 info() << "NEW EDGES_MAP after re-indexing";
89 edges_map.eachItem([&](Item edge) {
90 info() << "Edge uid=" << edge.uniqueId() << " lid=" << edge.localId();
91 });
92 }
93}
94
95/*---------------------------------------------------------------------------*/
96/*---------------------------------------------------------------------------*/
106{
107 public:
108
109 T_CellEdgeInfo(Int64 uid, Integer nb_back_edge, Integer nb_true_boundary_edge)
110 : m_unique_id(uid)
111 , m_nb_back_edge(nb_back_edge)
112 , m_nb_true_boundary_edge(nb_true_boundary_edge)
113 {
114 }
115
117 : m_unique_id(NULL_ITEM_ID)
118 , m_nb_back_edge(0)
119 , m_nb_true_boundary_edge(0)
120 {
121 }
122
123 public:
124
125 bool operator<(const T_CellEdgeInfo& ci) const
126 {
127 return m_unique_id < ci.m_unique_id;
128 }
129
130 public:
131
132 Int64 m_unique_id;
133 Int64 m_nb_back_edge;
134 Int64 m_nb_true_boundary_edge;
135};
136
137template <typename DataType>
139{
140 public:
141 private:
142
143 class MyInfo
144 {
145 public:
146
147 MyInfo(const DataType& d, Integer n)
148 : data(d)
149 , next_index(n)
150 {}
151
152 public:
153
154 DataType data;
155 Integer next_index;
156 };
157
158 public:
159
161 : m_last_index(5000, true)
162 {}
163
164 public:
165
166 void add(Int64 node_uid, const DataType& data)
167 {
168 Integer current_index = m_values.size();
169
170 bool is_add = false;
171 HashTableMapT<Int64, Int32>::Data* d = m_last_index.lookupAdd(node_uid, -1, is_add);
172
173 m_values.add(MyInfo(data, d->value()));
174 d->value() = current_index;
175 }
176
177 public:
178
179 UniqueArray<MyInfo> m_values;
180 HashTableMapT<Int64, Int32> m_last_index;
181};
182
183/*---------------------------------------------------------------------------*/
184/*---------------------------------------------------------------------------*/
185
187: public TraceAccessor
188{
189 using BoundaryInfosMap = std::unordered_map<Int32, SharedArray<Int64>>;
190
191 public:
192
194 Int64 max_node_uid);
195
196 public:
197
198 void compute();
199
200 private:
201
202 DynamicMesh* m_mesh = nullptr;
203 DynamicMeshIncrementalBuilder* m_mesh_builder = nullptr;
204 IParallelMng* m_parallel_mng = nullptr;
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;
208 NodeUidToSubDomain m_uid_to_subdomain_converter;
209 std::unordered_map<Int64, SharedArray<Int64>> m_nodes_info;
210 UniqueArray<bool> m_is_boundary_nodes;
211 bool m_is_verbose = false;
212
213 private:
214
215 void _exchangeData(IParallelExchanger* exchanger);
216 void _addEdgeBoundaryInfo(Edge edge);
217 void _computeEdgesUniqueId();
218 void _sendInfosToOtherRanks();
219};
220
221/*---------------------------------------------------------------------------*/
222/*---------------------------------------------------------------------------*/
223
224Parallel3EdgeUniqueIdBuilder::
225Parallel3EdgeUniqueIdBuilder(ITraceMng* tm, DynamicMeshIncrementalBuilder* mesh_builder, Int64 max_node_uid)
227, m_mesh(mesh_builder->mesh())
228, m_mesh_builder(mesh_builder)
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())
234{
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
245{
246 for (const auto& [key, value] : m_boundary_infos_to_send) {
247 exchanger->addSender(key);
248 }
250 {
251 for (Integer i = 0, ns = exchanger->nbSender(); i < ns; ++i) {
252 ISerializeMessage* sm = exchanger->messageToSend(i);
253 Int32 rank = sm->destination().value();
254 ISerializer* s = sm->serializer();
255 ConstArrayView<Int64> infos = m_boundary_infos_to_send[rank];
256 Integer nb_info = infos.size();
257 s->setMode(ISerializer::ModeReserve);
258 s->reserve(DT_Int64, 1); // Pour le nombre d'éléments
259 s->reserveSpan(DT_Int64, nb_info); // Pour les elements
260 s->allocateBuffer();
262 //info() << " SEND1 rank=" << rank << " nb_info=" << nb_info;
263 s->putInt64(nb_info);
264 s->putSpan(infos);
265 }
266 }
267 exchanger->processExchange();
268 debug() << "END EXCHANGE";
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
274void Parallel3EdgeUniqueIdBuilder::
275_addEdgeBoundaryInfo(Edge edge)
276{
277 Node first_node = edge.node(0);
278 Int64 first_node_uid = first_node.uniqueId();
280 Int32 dest_rank = -1;
281 if (!m_is_boundary_nodes[first_node.localId()]) {
282 v = m_nodes_info[first_node_uid];
283 }
284 else {
285 dest_rank = m_uid_to_subdomain_converter.uidToRank(first_node_uid);
286 v = m_boundary_infos_to_send[dest_rank];
287 }
288 v.add(first_node_uid); // 0
289 v.add(m_my_rank); // 1
290 v.add(edge.uniqueId()); // 2
291 v.add(edge.type()); // 3
292 v.add(NULL_ITEM_UNIQUE_ID); // 4 : only used for debug
293 v.add(NULL_ITEM_UNIQUE_ID); // 5 : only used for debug
294 if (m_is_verbose)
295 info() << "Edge uid=" << edge.uniqueId() << " n0,n1=" << edge.node(0).uniqueId() << "," << edge.node(1).uniqueId()
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());
299}
300
301/*---------------------------------------------------------------------------*/
302/*---------------------------------------------------------------------------*/
318compute()
319{
320 IParallelMng* pm = m_mesh->parallelMng();
321
322 Integer nb_local_edge = m_mesh_builder->oneMeshItemAdder()->nbEdge();
323 info() << "ComputeEdgesUniqueIdsParallel3 nb_edge=" << nb_local_edge;
324
326 edges_opposite_cell_uid.fill(NULL_ITEM_ID);
329
330 // Pour vérification, s'assure que tous les éléments de ce tableau
331 // sont valides, ce qui signifie que toutes les edges ont bien été
332 // renumérotés.
334 edges_new_uid.fill(NULL_ITEM_UNIQUE_ID);
335
337 edges_infos.reserve(10000);
338 ItemInternalMap& edges_map = m_mesh->edgesMap();
339 ItemInternalMap& faces_map = m_mesh->facesMap(); // utilisé pour détecter le bord
340
341 // NOTE : ce tableau n'est pas utile sur toutes les mailles. Il
342 // suffit qu'il contienne les mailles dont on a besoin, c'est-à-dire
343 // les nôtres + celles connectées à une de nos edges.
344 HashTableMapT<Int32, Int32> cell_first_edge_uid(m_mesh_builder->oneMeshItemAdder()->nbCell() * 2, true);
345
346 // Rassemble les données des autres processeurs dans recv_cells;
347 // Pour éviter que les tableaux ne soient trop gros, on procède en plusieurs
348 // étapes.
349 // Chaque sous-domaine construit sa liste des arêtes frontières, avec pour
350 // chaque arête :
351 // - son type,
352 // - la liste de ses noeuds,
353 // - le numéro unique de sa maille,
354 // - le propriétaire de sa maille,
355 // - son indice dans sa maille,
356 // Cette liste sera ensuite envoyée à tous les sous-domaines.
357
359 m_is_boundary_nodes.resize(node_family->maxLocalId(), false);
360
361 // Marque tous les noeuds frontières, car ce sont ceux qu'il faudra envoyer
362 // Un noeud est considéré comme frontière s'il appartient à une face qui n'a qu'une
363 // maille connectée.
364 faces_map.eachItem([&](Face face) {
365 Integer face_nb_cell = face.nbCell();
366 if (face_nb_cell == 1) {
367 for (Int32 ilid : face.nodeIds())
368 m_is_boundary_nodes[ilid] = true;
369 }
370 });
371
372 // Détermine la liste des arêtes frontières.
373 // L'ordre de cette liste dépend de l'implémentation de la table de hashage.
374 // Afin d'avoir la même numérotation que la version historique (qui utilise HashTableMapT),
375 // on utilise une instance temporaire de cette classe pour ce calcul si
376 // l'implémentation utilisée est différente. C'est le cas à partir d'octobre 2024.
377 // A terme, il faudrait utiliser une autre version du calcul des uniqueId() des
378 // arêtes.
379 // TODO: Ce mécanisme est en test. A vérifier que cela donne ensuite
380 // la même numérotation.
381 const bool is_new_item_map_impl = ItemInternalMap::UseNewImpl;
383 info() << "Edge: ItemInternalMap is using new implementation";
385 edges_map.eachItem([&](Edge edge) {
386 old_edges_map.add(edge.uniqueId(), edge);
387 });
388 old_edges_map.eachValue([&](Edge edge) {
389 _addEdgeBoundaryInfo(edge);
390 });
391 }
392 else {
393 edges_map.eachItem([&](Edge edge) {
394 _addEdgeBoundaryInfo(edge);
395 });
396 }
397
398 _computeEdgesUniqueId();
399 _sendInfosToOtherRanks();
400
401 traceMng()->flush();
402 pm->barrier();
403 info() << "END OF TEST NEW EDGE COMPUTE";
404}
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
409void Parallel3EdgeUniqueIdBuilder::
410_computeEdgesUniqueId()
411{
412 ItemTypeMng* itm = m_mesh->itemTypeMng();
413 IParallelMng* pm = m_parallel_mng;
415 _exchangeData(exchanger.get());
416
417 Integer nb_receiver = exchanger->nbReceiver();
418 debug() << "NB RECEIVER=" << nb_receiver;
420 for (Integer i = 0; i < nb_receiver; ++i) {
421 ISerializeMessage* sm = exchanger->messageToReceive(i);
422 //Int32 orig_rank = sm->destSubDomain();
423 ISerializer* s = sm->serializer();
425 Int64 nb_info = s->getInt64();
426 //info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank;
427 received_infos.resize(nb_info);
429 //if ((nb_info % 3)!=0)
430 //fatal() << "info size can not be divided by 3";
431 Integer z = 0;
432 while (z < nb_info) {
433 Int64 node_uid = received_infos[z + 0];
434 //Int64 sender_rank = received_infos[z+1];
435 //Int64 edge_uid = received_infos[z+2];
436 Int32 edge_type = (Int32)received_infos[z + 3];
437 // received_infos[z+4];
438 // received_infos[z+5];
439 ItemTypeInfo* itt = itm->typeFromId(edge_type);
440 Integer edge_nb_node = itt->nbLocalNode();
441 Int64Array& a = m_nodes_info[node_uid];
442 a.addRange(Int64ConstArrayView(6 + edge_nb_node, &received_infos[z]));
443 z += 6;
444 z += edge_nb_node;
445 //info() << "NODE UID=" << node_uid << " sender=" << sender_rank
446 // << " edge_uid=" << edge_uid;
447 //node_cell_list.add(node_uid,cell_uid,cell_owner);
448 //HashTableMapT<Int64,Int32>::Data* v = nodes_nb_cell.lookupAdd(node_uid);
449 //++v->value();
450 }
451 }
452
453 Integer my_max_edge_node = 0;
454 for (const auto& [key, value] : m_nodes_info) {
455 //Int64 key = inode.data()->key();
456 Int64ConstArrayView a = value;
457 //info() << "A key=" << key << " size=" << a.size();
458 Integer nb_info = a.size();
459 Integer z = 0;
460 Integer node_nb_edge = 0;
461 while (z < nb_info) {
462 ++node_nb_edge;
463 //Int64 node_uid = a[z+0];
464 //Int64 sender_rank = a[z+1];
465 //Int64 edge_uid = a[z+2];
466 Int32 edge_type = (Int32)a[z + 3];
467 // a[z+4];
468 // a[z+5];
469 ItemTypeInfo* itt = itm->typeFromId(edge_type);
470 Integer edge_nb_node = itt->nbLocalNode();
471 /*info() << "NODE2 UID=" << node_uid << " sender=" << sender_rank
472 << " edge_uid=" << edge_uid */
473 //for( Integer y=0; y<edge_nb_node; ++y )
474 //info() << "Nodes = i="<< y << " " << a[z+6+y];
475 z += 6;
476 z += edge_nb_node;
477 }
478 my_max_edge_node = math::max(node_nb_edge, my_max_edge_node);
479 }
480 Integer global_max_edge_node = pm->reduce(Parallel::ReduceMax, my_max_edge_node);
481 debug() << "GLOBAL MAX EDGE NODE=" << global_max_edge_node;
482 // OK, maintenant donne comme uid de la edge (node_uid * global_max_edge_node + index)
483 IntegerUniqueArray indexes;
484 m_boundary_infos_to_send.clear();
485
486 for (const auto& [key, value] : m_nodes_info) {
487 Int64ConstArrayView a = value;
488 Integer nb_info = a.size();
489 Integer z = 0;
490 Integer node_nb_edge = 0;
491 indexes.clear();
492 while (z < nb_info) {
493 Int64 node_uid = a[z + 0];
494 Int32 sender_rank = (Int32)a[z + 1];
495 Int64 edge_uid = a[z + 2];
496 Int32 edge_type = (Int32)a[z + 3];
497 // a[z+4];
498 // a[z+5];
499 ItemTypeInfo* itt = itm->typeFromId(edge_type);
500 Integer edge_nb_node = itt->nbLocalNode();
501
502 // Regarde si la edge est déjà dans la liste:
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) {
507 edge_index = y;
508 edge_new_owner = (Int32)a[indexes[y] + 1];
509 }
510 }
511 Int64 edge_new_uid = (node_uid * global_max_edge_node) + edge_index;
512 Int64Array& v = m_boundary_infos_to_send[sender_rank];
513 // Indique au propriétaire de cette arête son nouvel uid
514 v.add(edge_uid);
515 v.add(edge_new_uid);
516 v.add(edge_new_owner);
517 indexes.add(z);
518 z += 6;
519 z += edge_nb_node;
520 /* info() << "NODE3 UID=" << node_uid << " sender=" << sender_rank
521 << " edge_uid=" << edge_uid
522 << " edge_index=" << edge_index
523 << " edge_new_uid=" << edge_new_uid; */
524 ++node_nb_edge;
525 }
526 my_max_edge_node = math::max(node_nb_edge, my_max_edge_node);
527 }
528}
529
530/*---------------------------------------------------------------------------*/
531/*---------------------------------------------------------------------------*/
532
533void Parallel3EdgeUniqueIdBuilder::
534_sendInfosToOtherRanks()
535{
536 const bool is_verbose = m_mesh_builder->isVerbose();
537 IParallelMng* pm = m_parallel_mng;
538 Ref<IParallelExchanger> exchanger = ParallelMngUtils::createExchangerRef(pm);
539
540 _exchangeData(exchanger.get());
541
542 ItemInternalMap& edges_map = m_mesh->edgesMap();
543 Integer nb_receiver = exchanger->nbReceiver();
544 debug() << "NB RECEIVER=" << nb_receiver;
545 Int64UniqueArray received_infos;
546 for (Integer i = 0; i < nb_receiver; ++i) {
547 ISerializeMessage* sm = exchanger->messageToReceive(i);
548 auto orig_rank = sm->destination();
549 ISerializer* s = sm->serializer();
551 Int64 nb_info = s->getInt64();
552 if (is_verbose)
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]);
563 //info() << "EDGE old_uid=" << old_uid << " new_uid=" << new_uid;
564 impl::MutableItemBase iedge(edges_map.tryFind(old_uid));
565 if (iedge.null())
566 ARCANE_FATAL("Can not find own edge uid={0}", old_uid);
567 iedge.setUniqueId(new_uid);
568 iedge.setOwner(new_owner, m_my_rank);
569 Edge edge{ iedge };
570 if (is_verbose)
571 info() << "SetEdgeOwner uid=" << new_uid << " owner=" << new_owner
572 << " n0,n1=" << edge.node(0).uniqueId() << "," << edge.node(1).uniqueId()
573 << " n0=" << ItemPrinter(edge.node(0)) << " n1=" << ItemPrinter(edge.node(1));
574 }
575 }
576}
577
578/*---------------------------------------------------------------------------*/
579/*---------------------------------------------------------------------------*/
587{
588 bool is_verbose = m_mesh_builder->isVerbose();
589 Integer nb_cell = m_mesh_builder->oneMeshItemAdder()->nbCell();
590
591 ItemInternalMap& cells_map = m_mesh->cellsMap();
592
593 // En séquentiel, les uniqueId() des mailles ne peuvent dépasser la
594 // taille des Integers même en 32bits.
595 Int32 max_uid = 0;
596 cells_map.eachItem([&](Item cell) {
597 Int32 cell_uid = cell.uniqueId().asInt32();
598 if (cell_uid>max_uid)
599 max_uid = cell_uid;
600 });
601 info() << "Max uid=" << max_uid;
605
606 cells_map.eachItem([&](Cell cell) {
607 Int32 cell_uid = cell.uniqueId().asInt32();
608 Integer nb_num_back_edge = 0;
609 Integer nb_true_boundary_edge = 0;
610 for( Edge edge : cell.edges()){
611 if (edge.itemBase().backCell()==cell)
613 else if (edge.nbCell()==1){
615 }
616 }
619 });
620
621 Integer current_edge_uid = 0;
622 for( Integer i=0; i<nb_cell; ++i ){
625 }
626
627 if (is_verbose){
628 for( Integer i=0; i<nb_cell; ++i ){
629 info() << "Recv: Cell EdgeInfo celluid=" << i
630 << " firstedgeuid=" << cell_first_edge_uid[i]
631 << " nbback=" << cell_nb_num_back_edge[i]
632 << " nbbound=" << cell_true_boundary_edge[i];
633 }
634 }
635
636 cells_map.eachItem([&](Cell cell) {
637 Int32 cell_uid = cell.uniqueId().asInt32();
638 Integer nb_num_back_edge = 0;
639 Integer nb_true_boundary_edge = 0;
640 for( Edge edge : cell.edges() ){
641 Int64 edge_new_uid = NULL_ITEM_UNIQUE_ID;
642 //info() << "CHECK CELLUID=" << cell_uid << " EDGELID=" << edge->localId();
643 if (edge.itemBase().backCell()==cell){
646 }
647 else if (edge.nbCell()==1){
650 }
651 if (edge_new_uid!=NULL_ITEM_UNIQUE_ID){
652 //info() << "NEW EDGE UID: LID=" << edge->localId() << " OLDUID=" << edge->uniqueId()
653 //<< " NEWUID=" << edge_new_uid << " THIS=" << edge;
654 edge.mutableItemBase().setUniqueId(edge_new_uid);
655 }
656 }
657 });
658
659 if (is_verbose){
661 cells_map.eachItem([&](Cell cell) {
662 Int32 cell_uid = cell.uniqueId().asInt32();
663 Integer index = 0;
664 for( Edge edge : cell.edges() ){
665 Int64 opposite_cell_uid = NULL_ITEM_UNIQUE_ID;
666 bool true_boundary = false;
667 bool internal_other = false;
668 if (edge.itemBase().backCell()==cell){
669 }
670 else if (edge.nbCell()==1){
671 true_boundary = true;
672 }
673 else{
674 internal_other = true;
675 opposite_cell_uid = edge.itemBase().backCell().uniqueId().asInt64();
676 }
677 ostr() << "NEW LOCAL ID FOR CELLEDGE " << cell_uid << ' '
678 << index << ' ' << edge.uniqueId() << " (";
679 for( Node node : edge.nodes() ){
680 ostr() << ' ' << node.uniqueId();
681 }
682 ostr() << ")";
683 if (internal_other)
684 ostr() << " internal-other";
685 if (true_boundary)
686 ostr() << " true-boundary";
687 if (opposite_cell_uid!=NULL_ITEM_ID)
688 ostr() << " opposite " << opposite_cell_uid;
689 ostr() << '\n';
690 ++index;
691 }
692 });
693 info() << ostr.str();
694 }
695}
696
697/*---------------------------------------------------------------------------*/
698/*---------------------------------------------------------------------------*/
699
700void EdgeUniqueIdBuilder::
701_computeEdgesUniqueIdsParallelV2()
702{
703 // Positionne les uniqueId() des arêtes de manière très simple.
704 // Si le maximum des uniqueId() des noeuds est MAX_NODE_UID, alors
705 // le uniqueId() d'une arête est :
706 //
707 // node(0).uniqueId() * MAX_NODE_UID + node(1).uniqueId()
708 //
709 // Cela ne fonctionne que si MAX_NODE_UID est inférieur à 2^31.
710
711 IParallelMng* pm = m_mesh->parallelMng();
712
713 ItemInternalMap& nodes_map = m_mesh->nodesMap();
714 ItemInternalMap& edges_map = m_mesh->edgesMap();
715
716 Int64 max_uid = 0;
717 nodes_map.eachItem([&](Item node) {
718 if (node.uniqueId() > max_uid)
719 max_uid = node.uniqueId();
720 });
721 Int64 total_max_uid = pm->reduce(Parallel::ReduceMax,max_uid);
722 if (total_max_uid>INT32_MAX)
723 ARCANE_FATAL("Max uniqueId() for node is too big v={0} max_allowed={1}",total_max_uid,INT32_MAX);
724
725 edges_map.eachItem([&](Edge edge) {
726 Node node0{edge.node(0)};
727 Node node1{edge.node(1)};
728 Int64 new_uid = (node0.uniqueId().asInt64() * total_max_uid) + node1.uniqueId().asInt64();
729 edge.mutableItemBase().setUniqueId(new_uid);
730 });
731}
732
733/*---------------------------------------------------------------------------*/
734/*---------------------------------------------------------------------------*/
735
736void EdgeUniqueIdBuilder::
737_computeEdgesUniqueIdsParallel3()
738{
739 IParallelMng* pm = m_mesh->parallelMng();
740 ItemInternalMap& nodes_map = m_mesh->nodesMap();
741
742 // Détermine le maximum des uniqueId() des noeuds
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;
748 });
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;
752
753 Parallel3EdgeUniqueIdBuilder builder(traceMng(), m_mesh_builder, global_max_node_uid);
754 builder.compute();
755}
756
757/*---------------------------------------------------------------------------*/
758/*---------------------------------------------------------------------------*/
759
760void EdgeUniqueIdBuilder::
761_computeEdgesUniqueIdsParallel64bit()
762{
763 // Positionne les uniqueId() des arêtes
764 // en utilisant un hash des deux nœuds de l'arête.
765 ItemInternalMap& edges_map = m_mesh->edgesMap();
766
767 std::hash<Int64> hasher;
768
769 edges_map.eachItem([&](Edge edge) {
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);
777 });
778}
779
780/*---------------------------------------------------------------------------*/
781/*---------------------------------------------------------------------------*/
782
783} // End namespace Arcane::mesh
784
785/*---------------------------------------------------------------------------*/
786/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Tableau d'items de types quelconques.
Maille d'un maillage.
Definition Item.h:1178
EdgeConnectedListViewType edges() const
Liste des arêtes de la maille.
Definition Item.h:1276
Arête d'une maille.
Definition Item.h:798
Int32 nbCell() const
Nombre de mailles connectées à l'arête.
Definition Item.h:878
Face d'une maille.
Definition Item.h:932
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
Definition Item.h:1006
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.
Definition ItemTypeMng.h:66
ItemTypeInfo * typeFromId(Integer id) const
Type correspondant au numéro id.
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:771
NodeLocalIdView nodeIds() const
Liste des noeuds de l'entité
Definition Item.h:774
Classe de base d'un élément de maillage.
Definition Item.h:83
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:365
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
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
Int16 type() const
Type de l'entité
Definition Item.h:232
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Noeud d'un maillage.
Definition Dom.h:204
Flot de sortie lié à une String.
Construction d'un maillage de manière incrémentale.
Implémentation d'un maillage.
Definition DynamicMesh.h:97
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.
virtual void allocateBuffer()=0
Alloue la mémoire du sérialiseur.
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.
virtual MessageRank destination() const =0
Rang du destinataire (si isSend() est vrai) ou de l'envoyeur.
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.
Definition MathUtils.h:392
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
@ DT_Int64
Donnée de type entier 64 bits.
Definition DataTypes.h:44
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:638
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:519
Int32 Integer
Type représentant un entier.