Arcane  v4.1.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ItemsOwnerBuilder.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* ItemsOwnerBuilder.cc (C) 2000-2025 */
9/* */
10/* Classe pour calculer les propriétaires des entités. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/ItemsOwnerBuilder.h"
15
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/SmallArray.h"
18#include "arcane/utils/HashTableMap2.h"
19
20#include "arcane/core/IParallelMng.h"
21#include "arcane/core/ParallelMngUtils.h"
22#include "arcane/core/IParallelExchanger.h"
23#include "arcane/core/ISerializeMessage.h"
24#include "arcane/core/ISerializer.h"
25
26#include "arcane/parallel/BitonicSortT.H"
27
28#include "arcane/mesh/ItemInternalMap.h"
29#include "arcane/mesh/NodeFamily.h"
30#include "arcane/mesh/EdgeFamily.h"
31#include "arcane/mesh/DynamicMesh.h"
32
33#include <unordered_set>
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane::mesh
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43/*
44 * Ce fichier contient un algorithme pour calculer les propriétaires des
45 * entités autres que les mailles à partir des propriétaires des mailles.
46 *
47 * L'algorithme suppose que les propriétaires des mailles sont à jours et
48 * synchronisés. Le propriétaire d'une entité sera alors le propriétaire de
49 * la maille de plus petit uniqueId() connectée à cette entité.
50 *
51 * En parallèle, si une entité est à la frontière d'un sous-domaine, il n'est
52 * pas possible de connaitre toutes les mailles qui y sont connectées.
53 * Pour résoudre ce problème, on crée une liste des entités de la frontière
54 * contenant pour chaque maille connectée un triplet (uniqueId() de l'entité,
55 * uniqueId() de la maille connectée, owner() de la maille connectées).
56 * Cette liste est ensuite triée en parallèle (via BitonicSort) par uniqueId()
57 * de l'entité, puis par uniqueId() de la maille.
58 * Pour déterminer le propriétaire d'une entité, il suffit ensuite de prendre
59 * le propriétaire de la maille associée à la première occurrence de l'entité
60 * dans cette liste triée. Une fois ceci fait, on renvoie aux rangs qui possèdent
61 * cette entité cette information.
62 */
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
68class ItemsOwnerBuilderImpl
69: public TraceAccessor
70{
72
84 class ItemOwnerInfo
85 {
86 public:
87
88 ItemOwnerInfo() = default;
89 ItemOwnerInfo(Int64 item_uid, Int64 first_node_uid, Int64 cell_uid, Int32 sender_rank, Int32 cell_owner)
90 : m_item_uid(item_uid)
91 , m_first_node_uid(first_node_uid)
92 , m_cell_uid(cell_uid)
93 , m_item_sender_rank(sender_rank)
94 , m_cell_owner(cell_owner)
95 {
96 }
97
98 public:
99
101 Int64 m_item_uid = NULL_ITEM_UNIQUE_ID;
103 Int64 m_first_node_uid = NULL_ITEM_UNIQUE_ID;
105 Int64 m_cell_uid = NULL_ITEM_UNIQUE_ID;
109 Int32 m_cell_owner = A_NULL_RANK;
110 };
111
112 public:
113
114 explicit ItemsOwnerBuilderImpl(IMesh* mesh);
115
116 public:
117
118 void computeFacesOwner();
119 void computeEdgesOwner();
120 void computeNodesOwner();
121
122 private:
123
124 DynamicMesh* m_mesh = nullptr;
125 Int32 m_verbose_level = 0;
126 UniqueArray<ItemOwnerInfo> m_items_owner_info;
135
136 private:
137
138 void _sortInfos();
139 void _processSortedInfos(ItemInternalMap& items_map);
140};
141
142/*---------------------------------------------------------------------------*/
143/*---------------------------------------------------------------------------*/
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
149{
150 public:
151
152 explicit ItemOwnerInfoSortTraits(bool use_cell_uid_to_sort)
153 : m_use_cell_uid_to_sort(use_cell_uid_to_sort)
154 {}
155
156 public:
157
158 bool compareLess(const ItemOwnerInfo& k1, const ItemOwnerInfo& k2) const
159 {
161 return true;
163 return false;
164
165 if (k1.m_item_uid < k2.m_item_uid)
166 return true;
167 if (k1.m_item_uid > k2.m_item_uid)
168 return false;
169
170 if (m_use_cell_uid_to_sort) {
171 if (k1.m_cell_uid < k2.m_cell_uid)
172 return true;
173 if (k1.m_cell_uid > k2.m_cell_uid)
174 return false;
175
177 return true;
179 return false;
180 }
181 else {
183 return true;
185 return false;
186
187 if (k1.m_cell_uid < k2.m_cell_uid)
188 return true;
189 if (k1.m_cell_uid > k2.m_cell_uid)
190 return false;
191 }
192 // ke.node2_uid == k2.node2_uid
193 return (k1.m_cell_owner < k2.m_cell_owner);
194 }
195
197 {
198 const ItemOwnerInfo* fsi_base = values.data();
199 return pm->send(ByteConstArrayView(messageSize(values), reinterpret_cast<const Byte*>(fsi_base)), rank, false);
200 }
201 static Parallel::Request recv(IParallelMng* pm, Int32 rank, ArrayView<ItemOwnerInfo> values)
202 {
203 ItemOwnerInfo* fsi_base = values.data();
204 return pm->recv(ByteArrayView(messageSize(values), reinterpret_cast<Byte*>(fsi_base)), rank, false);
205 }
206 static Integer messageSize(ConstArrayView<ItemOwnerInfo> values)
207 {
208 return CheckedConvert::toInteger(values.size() * sizeof(ItemOwnerInfo));
209 }
210 static ItemOwnerInfo maxValue()
211 {
212 return ItemOwnerInfo(INT64_MAX, INT64_MAX, INT64_MAX, INT32_MAX, INT32_MAX);
213 }
214 static bool isValid(const ItemOwnerInfo& fsi)
215 {
216 return fsi.m_item_uid != INT64_MAX;
217 }
218
219 private:
220
221 bool m_use_cell_uid_to_sort = true;
222};
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
230ItemsOwnerBuilderImpl::
231ItemsOwnerBuilderImpl(IMesh* mesh)
233{
234 auto* dm = dynamic_cast<DynamicMesh*>(mesh);
235 if (!dm)
236 ARCANE_FATAL("Mesh is not an instance of 'DynamicMesh'");
237 m_mesh = dm;
238 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ITEMS_OWNER_BUILDER_IMPL_DEBUG_LEVEL", true))
239 m_verbose_level = v.value();
240 // Indique si on trie en fonction de la maille de plus petit uniqueId()
241 // ou en fonction du plus petit rang.
242 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ITEMS_OWNER_BUILDER_USE_RANK", true))
243 m_use_cell_uid_to_sort = !v.value();
244}
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
249void ItemsOwnerBuilderImpl::
250computeFacesOwner()
251{
252 m_items_owner_info.clear();
253
254 IParallelMng* pm = m_mesh->parallelMng();
255 const Int32 my_rank = pm->commRank();
256 ItemInternalMap& faces_map = m_mesh->facesMap();
257 FaceFamily& face_family = m_mesh->trueFaceFamily();
258
259 info() << "** BEGIN ComputeFacesOwner nb_face=" << faces_map.count();
260
261 // Parcours toutes les faces.
262 // Ne garde que celles qui sont frontières ou dont les propriétaires des
263 // deux mailles de part et d'autre sont différents de notre sous-domaine.
264 UniqueArray<Int32> faces_to_add;
265 UniqueArray<Int64> faces_to_add_uid;
266 faces_map.eachItem([&](Face face) {
267 Int32 nb_cell = face.nbCell();
268 if (nb_cell == 2)
269 if (face.cell(0).owner() == my_rank && face.cell(1).owner() == my_rank) {
270 face.mutableItemBase().setOwner(my_rank, my_rank);
271 return;
272 }
273 faces_to_add.add(face.localId());
274 faces_to_add_uid.add(face.uniqueId());
275 });
276 info() << "ItemsOwnerBuilder: NB_FACE_TO_TRANSFER=" << faces_to_add.size();
277 const Int32 verbose_level = m_verbose_level;
278
279 FaceInfoListView faces(&face_family);
280 for (Int32 lid : faces_to_add) {
281 Face face(faces[lid]);
282 Int64 face_uid = face.uniqueId();
283 for (Cell cell : face.cells()) {
284 if (verbose_level >= 2)
285 info() << "ADD lid=" << lid << " uid=" << face_uid << " cell_uid=" << cell.uniqueId() << " owner=" << cell.owner();
286 m_items_owner_info.add(ItemOwnerInfo(face_uid, face.node(0).uniqueId(), cell.uniqueId(), my_rank, cell.owner()));
287 }
288 }
289
290 // Tri les instances de ItemOwnerInfo et les place les valeurs triées
291 // dans items_owner_info.
292 _sortInfos();
293 _processSortedInfos(faces_map);
294
295 face_family.notifyItemsOwnerChanged();
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
301void ItemsOwnerBuilderImpl::
302computeEdgesOwner()
303{
304 m_items_owner_info.clear();
305
306 IParallelMng* pm = m_mesh->parallelMng();
307 const Int32 my_rank = pm->commRank();
308 ItemInternalMap& edges_map = m_mesh->edgesMap();
309 EdgeFamily& edge_family = m_mesh->trueEdgeFamily();
310
311 info() << "** BEGIN ComputeEdgesOwner nb_edge=" << edges_map.count();
312
313 // Parcours toutes les arêtes.
314 // Ne garde que celles qui sont frontières ou dont au moins un des propriétaires des
315 // mailles connectées sont différents de notre sous-domaine.
316 UniqueArray<Int32> edges_to_add;
317 UniqueArray<Int64> edges_to_add_uid;
318 // La force brute ajoute toutes les arêtes.
319 // Cela permet de garantir qu'on calcule bien les propriétaires, même si
320 // on ne sait pas déterminer les arêtes frontìères.
321 // Cela n'est pas optimum, car on envoie aussi nos arêtes internes
322 // alors qu'on est certain qu'on est leur propriétaire.
323 bool do_brute_force = true;
324 edges_map.eachItem([&](Edge edge) {
325 Int32 nb_cell = edge.nbCell();
326 Int32 nb_cell_with_my_rank = 0;
327 for (Cell cell : edge.cells())
328 if (cell.owner() == my_rank)
329 ++nb_cell_with_my_rank;
330 bool do_add = (nb_cell == 1 || (nb_cell != nb_cell_with_my_rank));
331 if (do_add || do_brute_force) {
332 edges_to_add.add(edge.localId());
333 edges_to_add_uid.add(edge.uniqueId());
334 }
335 else
336 edge.mutableItemBase().setOwner(my_rank, my_rank);
337 });
338 info() << "ItemsOwnerBuilder: NB_FACE_TO_TRANSFER=" << edges_to_add.size();
339 const Int32 verbose_level = m_verbose_level;
340
341 EdgeInfoListView edges(&edge_family);
342 for (Int32 lid : edges_to_add) {
343 Edge edge(edges[lid]);
344 Int64 edge_uid = edge.uniqueId();
345 for (Cell cell : edge.cells()) {
346 if (verbose_level >= 2)
347 info() << "ADD lid=" << lid << " uid=" << edge_uid << " cell_uid=" << cell.uniqueId() << " owner=" << cell.owner();
348 m_items_owner_info.add(ItemOwnerInfo(edge_uid, edge.node(0).uniqueId(), cell.uniqueId(), my_rank, cell.owner()));
349 }
350 }
351
352 // Tri les instances de ItemOwnerInfo et les place les valeurs triées
353 // dans items_owner_info.
354 _sortInfos();
355 _processSortedInfos(edges_map);
356
357 edge_family.notifyItemsOwnerChanged();
358}
359
360/*---------------------------------------------------------------------------*/
361/*---------------------------------------------------------------------------*/
362
363void ItemsOwnerBuilderImpl::
364computeNodesOwner()
365{
366 m_items_owner_info.clear();
367
368 IParallelMng* pm = m_mesh->parallelMng();
369 const Int32 my_rank = pm->commRank();
370 ItemInternalMap& faces_map = m_mesh->facesMap();
371 ItemInternalMap& nodes_map = m_mesh->nodesMap();
372 NodeFamily& node_family = m_mesh->trueNodeFamily();
373
374 info() << "** BEGIN ComputeNodesOwner nb_node=" << nodes_map.count();
375
376 // Place par défaut tous les noeuds dans ce sous-domaine
377 nodes_map.eachItem([&](Node node) {
378 node.mutableItemBase().setOwner(my_rank, my_rank);
379 });
380
381 // Parcours toutes les faces frontières et ajoute leurs noeuds
382 // à la liste des noeuds à traiter (nodes_to_add). Les faces frontières sont
383 // celles qui ne sont connectées qu'à une seule maille.
384 // qui connectées à une seule maille.
385 const Int32 verbose_level = m_verbose_level;
386
387 // Liste des noeuds à traiter
388 UniqueArray<Int32> nodes_to_add;
389
390 // Ensemble pour déterminer si un noeud a déjà été ajouté à \a nodes_to_add.
391 std::unordered_set<Int32> done_nodes;
392
393 const bool is_mono_dimension = m_mesh->meshKind().isMonoDimension();
394
395 FaceInfoListView faces(m_mesh->faceFamily());
396 if (is_mono_dimension) {
397 faces_map.eachItem([&](Face face) {
398 Int32 face_nb_cell = face.nbCell();
399 if (face_nb_cell == 2)
400 return;
401 for (Node node : face.nodes()) {
402 Int32 node_id = node.localId();
403 if (done_nodes.find(node_id) == done_nodes.end()) {
404 nodes_to_add.add(node_id);
405 done_nodes.insert(node_id);
406 node.mutableItemBase().setOwner(A_NULL_RANK, my_rank);
407 }
408 }
409 });
410 }
411 else {
412 // Dans le cas de maillage multi-dimension, il n'y a pas actuellement
413 // de moyen simple de détecter les noeuds frontières. On traite donc tous
414 // les noeuds même si cela n'est pas optimal.
415 // NOTE: La détection n'est difficile que pour les noeuds connectés à des mailles
416 // de dimension 1 ou 2. Pour les mailles 3D, on pourrait n'ajouter que
417 // les noeuds connectées à une face n'ayant qu'une maille.
418 ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
419 nodes_to_add.add(inode.itemLocalId());
420 }
421 }
422
423 info() << "ItemsOwnerBuilder: NB_NODE_TO_ADD=" << nodes_to_add.size() << " is_mono_dim=" << is_mono_dimension;
424 NodeInfoListView nodes(&node_family);
425 for (Int32 lid : nodes_to_add) {
426 Node node(nodes[lid]);
427 Int64 node_uid = node.uniqueId();
428 for (Cell cell : node.cells()) {
429 if (verbose_level >= 2)
430 info() << "ADD lid=" << lid << " uid=" << node_uid << " cell_uid=" << cell.uniqueId() << " owner=" << cell.owner();
431 m_items_owner_info.add(ItemOwnerInfo(node_uid, node_uid, cell.uniqueId(), my_rank, cell.owner()));
432 }
433 }
434
435 // Tri les instances de ItemOwnerInfo et les place les valeurs triées
436 // dans items_owner_info.
437 _sortInfos();
438 _processSortedInfos(nodes_map);
439
440 node_family.notifyItemsOwnerChanged();
441}
442
443/*---------------------------------------------------------------------------*/
444/*---------------------------------------------------------------------------*/
451{
452 IParallelMng* pm = m_mesh->parallelMng();
453 const Int32 verbose_level = m_verbose_level;
456 items_sorter.setNeedIndexAndRank(false);
457 Real sort_begin_time = platform::getRealTime();
458 items_sorter.sort(m_items_owner_info);
459 Real sort_end_time = platform::getRealTime();
460 m_items_owner_info = items_sorter.keys();
461 info() << "END_ALL_ITEM_OWNER_SORTER time=" << (Real)(sort_end_time - sort_begin_time);
462 if (verbose_level >= 2)
463 for (const ItemOwnerInfo& x : m_items_owner_info) {
464 info() << "Sorted first_node_uid=" << x.m_first_node_uid << " item_uid="
465 << x.m_item_uid << " cell_uid=" << x.m_cell_uid << " owner=" << x.m_cell_owner;
466 }
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471
472void ItemsOwnerBuilderImpl::
473_processSortedInfos(ItemInternalMap& items_map)
474{
475 IParallelMng* pm = m_mesh->parallelMng();
476 const Int32 my_rank = pm->commRank();
477 const Int32 nb_rank = pm->commSize();
478 ConstArrayView<ItemOwnerInfo> items_owner_info = m_items_owner_info;
479 Int32 nb_sorted = items_owner_info.size();
480 info() << "NbSorted=" << nb_sorted;
481 const bool is_last_rank = ((my_rank + 1) == nb_rank);
482 const bool is_first_rank = (my_rank == 0);
483 const Int32 verbose_level = m_verbose_level;
484
485 // Comme les informations d'une entité peuvent être réparties sur plusieurs rangs
486 // après le tri, chaque rang envoie au rang suivant les informations
487 // de la dernière entité de sa liste.
488 // Il faut faire attention à bien envoyer la liste dans le même ordre trié pour
489 // garantir la cohérence car on va prendre le premier élément de la liste pour
490 // positionner le propriétaire.
491
492 UniqueArray<ItemOwnerInfo> items_owner_info_send_to_next;
493 if (nb_sorted > 0 && !is_last_rank) {
494 Int32 send_index = nb_sorted;
495 Int64 last_uid = items_owner_info[nb_sorted - 1].m_item_uid;
496 for (Int32 i = (nb_sorted - 1); i >= 0; --i) {
497 const ItemOwnerInfo& x = items_owner_info[i];
498 if (x.m_item_uid != last_uid) {
499 send_index = i + 1;
500 break;
501 }
502 }
503 info() << "SendIndext=" << send_index << " nb_sorted=" << nb_sorted;
504 for (Int32 i = send_index; i < nb_sorted; ++i) {
505 const ItemOwnerInfo& x = items_owner_info[i];
506 items_owner_info_send_to_next.add(x);
507 if (verbose_level >= 2)
508 info() << "AddSendToNext item_uid=" << x.m_item_uid << " owner=" << x.m_cell_owner
509 << " from_rank=" << x.m_item_sender_rank << " index=" << i;
510 }
511 }
512 Int32 nb_send_to_next = items_owner_info_send_to_next.size();
513 info() << "NbSendToNext=" << nb_send_to_next;
514
515 Int32 nb_to_receive_from_previous = 0;
516 SmallArray<Parallel::Request> requests;
517 // Envoie et recoit les tailles des tableaux
518 if (!is_last_rank)
519 requests.add(pm->send(ConstArrayView<Int32>(1, &nb_send_to_next), my_rank + 1, false));
520 if (!is_first_rank)
521 requests.add(pm->recv(ArrayView<Int32>(1, &nb_to_receive_from_previous), my_rank - 1, false));
522
523 pm->waitAllRequests(requests);
524 requests.clear();
525
526 // Envoie le tableau au suivant et récupère celui du précédent.
527 UniqueArray<ItemOwnerInfo> items_owner_info_received_from_previous(nb_to_receive_from_previous);
528 if (!is_last_rank)
529 requests.add(ItemOwnerInfoSortTraits::send(pm, my_rank + 1, items_owner_info_send_to_next));
530 if (!is_first_rank)
531 requests.add(ItemOwnerInfoSortTraits::recv(pm, my_rank - 1, items_owner_info_received_from_previous));
532 pm->waitAllRequests(requests);
533
534 // Supprime de la liste les entités qu'on a envoyé au suivant
535 m_items_owner_info.resize(nb_sorted - nb_send_to_next);
536 items_owner_info = m_items_owner_info.view();
537 nb_sorted = items_owner_info.size();
538 info() << "NbRemaining=" << nb_sorted;
539
540 Int64 current_item_uid = NULL_ITEM_UNIQUE_ID;
541 Int32 current_item_owner = A_NULL_RANK;
542
543 // Parcours la liste des entités qu'on a recu.
544 // Chaque entité est présente plusieurs fois dans la liste : au moins
545 // une fois par maille connectée à cette entité. Comme cette liste est triée
546 // par uniqueId() croissant de ces mailles, et que c'est la maille de plus
547 // petit uniqueId() qui donne le propriétaire de l'entité, alors le propriétaire
548 // est celui du premier élément de cette liste.
549 // On envoie ensuite à tous les rangs qui possèdent cette entité ce nouveau propriétaire.
550 // Le tableau envoyé contient une liste de couples (item_uid, item_new_owner).
551 impl::HashTableMap2<Int32, UniqueArray<Int64>> resend_items_owner_info_map;
552 for (Int32 index = 0; index < (nb_sorted + nb_to_receive_from_previous); ++index) {
553 const ItemOwnerInfo* first_ioi = nullptr;
554 // Si \a i est inférieur à nb_to_receive_from_previous, on prend
555 // les informations de la liste recue.
556 if (index < nb_to_receive_from_previous)
557 first_ioi = &items_owner_info_received_from_previous[index];
558 else
559 first_ioi = &items_owner_info[index - nb_to_receive_from_previous];
560 Int64 item_uid = first_ioi->m_item_uid;
561
562 // Si l'id courant est différent du précédent, on commence une nouvelle liste.
563 if (item_uid != current_item_uid) {
564 current_item_uid = item_uid;
566 current_item_owner = first_ioi->m_cell_owner;
567 else
568 current_item_owner = first_ioi->m_item_sender_rank;
569 if (verbose_level >= 2)
570 info() << "SetOwner from sorted index=" << index << " item_uid=" << current_item_uid << " new_owner=" << current_item_owner;
571 }
572 Int32 orig_sender = first_ioi->m_item_sender_rank;
573 UniqueArray<Int64>& send_array = resend_items_owner_info_map[orig_sender];
574 send_array.add(current_item_uid);
575 send_array.add(current_item_owner);
576 if (verbose_level >= 2)
577 info() << "SEND i=" << index << " rank=" << orig_sender << " item_uid=" << current_item_uid << " new_owner=" << current_item_owner;
578 }
579
580 auto exchanger{ ParallelMngUtils::createExchangerRef(pm) };
581 info() << "NbResendRanks=" << resend_items_owner_info_map.size();
582 for (const auto& [key, value] : resend_items_owner_info_map) {
583 if (verbose_level >= 1)
584 info() << "RESEND_INFO to_rank=" << key << " nb=" << value.size();
585 exchanger->addSender(key);
586 }
587 exchanger->initializeCommunicationsMessages();
588 {
589 Int32 index = 0;
590 for (const auto& [key, value] : resend_items_owner_info_map) {
591 ISerializeMessage* sm = exchanger->messageToSend(index);
592 ++index;
593 ISerializer* s = sm->serializer();
594 s->setMode(ISerializer::ModeReserve);
595 s->reserveArray(value);
596 s->allocateBuffer();
597 s->setMode(ISerializer::ModePut);
598 s->putArray(value);
599 }
600 }
601 exchanger->processExchange();
602 UniqueArray<Int64> receive_info;
603
604 for (Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
605 ISerializeMessage* sm = exchanger->messageToReceive(i);
606 ISerializer* s = sm->serializer();
607 s->setMode(ISerializer::ModeGet);
608 s->getArray(receive_info);
609 Int32 receive_size = receive_info.size();
610 if (verbose_level >= 1)
611 info() << "RECEIVE_INFO size=" << receive_size << " rank2=" << sm->destination();
612 // Vérifie que la taille est un multiple de 2
613 if ((receive_size % 2) != 0)
614 ARCANE_FATAL("Size '{0}' is not a multiple of 2", receive_size);
615 Int32 buf_size = receive_size / 2;
616 for (Int32 z = 0; z < buf_size; ++z) {
617 Int64 item_uid = receive_info[z * 2];
618 Int32 item_owner = CheckedConvert::toInt32(receive_info[(z * 2) + 1]);
619 impl::ItemBase x = items_map.findItem(item_uid);
620 if (verbose_level >= 2)
621 info() << "SetOwner uid=" << item_uid << " new_owner=" << item_owner;
622 x.toMutable().setOwner(item_owner, my_rank);
623 }
624 }
625}
626
627/*---------------------------------------------------------------------------*/
628/*---------------------------------------------------------------------------*/
629
630/*---------------------------------------------------------------------------*/
631/*---------------------------------------------------------------------------*/
632
633ItemsOwnerBuilder::
634ItemsOwnerBuilder(IMesh* mesh)
635: m_p(std::make_unique<ItemsOwnerBuilderImpl>(mesh))
636{}
637
638ItemsOwnerBuilder::
639~ItemsOwnerBuilder()
640{
641 // Le destructeur doit être dans le '.cc' car 'ItemsOwnerBuilderImpl' n'est
642 // pas connu dans le '.h'.
643}
644
645/*---------------------------------------------------------------------------*/
646/*---------------------------------------------------------------------------*/
647
648void ItemsOwnerBuilder::
649computeFacesOwner()
650{
651 m_p->computeFacesOwner();
652}
653
654/*---------------------------------------------------------------------------*/
655/*---------------------------------------------------------------------------*/
656
657void ItemsOwnerBuilder::
658computeEdgesOwner()
659{
660 m_p->computeEdgesOwner();
661}
662
663/*---------------------------------------------------------------------------*/
664/*---------------------------------------------------------------------------*/
665
666void ItemsOwnerBuilder::
667computeNodesOwner()
668{
669 m_p->computeNodesOwner();
670}
671
672/*---------------------------------------------------------------------------*/
673/*---------------------------------------------------------------------------*/
674
675} // namespace Arcane::mesh
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr const_pointer data() const noexcept
Pointeur sur le début de la vue.
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.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Face d'une maille.
Definition Item.h:958
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1647
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
Definition Item.h:1033
CellConnectedListViewType cells() const
Liste des mailles de la face.
Definition Item.h:1039
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Bloque en attendant que les requêtes rvalues soient terminées.
@ ModePut
Le sérialiseur attend des reserve()
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:788
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:380
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
Requête d'un message.
Definition Request.h:77
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
Algorithme de tri bi-tonique parallèle.
ConstArrayView< KeyType > keys() const override
Après un tri, retourne la liste des éléments de ce rang.
void sort(ConstArrayView< KeyType > keys) override
Trie en parallèle les éléments de keys sur tous les rangs.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
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).
Implémentation d'un maillage.
Definition DynamicMesh.h:98
IParallelMng * parallelMng() override
Gestionnaire de parallèlisme.
Famille de faces.
Definition FaceFamily.h:53
void notifyItemsOwnerChanged() override
Notifie que les entités propres au sous-domaine de la famille ont été modifiées.
Tableau associatif de ItemInternal.
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.
Int32 count() const
Nombre d'éléments de la table.
Informations sur une entité partagée.
Int32 m_item_sender_rank
rang de celui qui a créé cette instance
Int64 m_first_node_uid
uniqueId() du premier noeud de l'entité
Int32 m_cell_owner
Propriétaire de la maille connectée à cette entité
Int64 m_cell_uid
uniqueId() de la maille à laquelle l'entité appartient
bool m_use_cell_uid_to_sort
Indique comment effectuer le tri.
void _sortInfos()
Tri les instances contenues dans m_items_owner_info replace les valeurs triées dans ce même tableau.
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.
ARCCORE_BASE_EXPORT Real getRealTime()
Temps Real utilisé en secondes.
ArrayView< Byte > ByteArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:476
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
double Real
Type représentant un réel.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:505
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:43
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52
std::int32_t Int32
Type entier signé sur 32 bits.