Arcane  v3.16.9.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.
382 // Ne garde que celles qui sont frontières ou dont les propriétaires des
383 // deux mailles de part et d'autre sont différents de notre sous-domaine.
384 //UniqueArray<Int32> faces_to_add;
385 //faces_map.eachItem([&](Face face) {
386 //Int32 nb_cell = face.nbCell();
387 // if (nb_cell == 1)
388 // faces_to_add.add(face.localId());
389 //});
390 //info() << "ItemsOwnerBuilder: NB_FACE_TO_ADD=" << faces_to_add.size();
391 const Int32 verbose_level = m_verbose_level;
392
393 // Ajoute tous les noeuds des faces frontières.
394 std::unordered_set<Int32> done_nodes;
395
396 FaceInfoListView faces(m_mesh->faceFamily());
397 UniqueArray<Int32> nodes_to_add;
398 faces_map.eachItem([&](Face face) {
399 Int32 face_nb_cell = face.nbCell();
400 if (face_nb_cell == 2)
401 return;
402 for (Node node : face.nodes()) {
403 Int32 node_id = node.localId();
404 if (done_nodes.find(node_id) == done_nodes.end()) {
405 nodes_to_add.add(node_id);
406 done_nodes.insert(node_id);
407 node.mutableItemBase().setOwner(A_NULL_RANK, my_rank);
408 }
409 }
410 });
411
412 info() << "ItemsOwnerBuilder: NB_NODE_TO_ADD=" << nodes_to_add.size();
413 NodeInfoListView nodes(&node_family);
414 for (Int32 lid : nodes_to_add) {
415 Node node(nodes[lid]);
416 Int64 node_uid = node.uniqueId();
417 for (Cell cell : node.cells()) {
418 if (verbose_level >= 2)
419 info() << "ADD lid=" << lid << " uid=" << node_uid << " cell_uid=" << cell.uniqueId() << " owner=" << cell.owner();
420 m_items_owner_info.add(ItemOwnerInfo(node_uid, node_uid, cell.uniqueId(), my_rank, cell.owner()));
421 }
422 }
423
424 // Tri les instances de ItemOwnerInfo et les place les valeurs triées
425 // dans items_owner_info.
426 _sortInfos();
427 _processSortedInfos(nodes_map);
428
429 node_family.notifyItemsOwnerChanged();
430}
431
432/*---------------------------------------------------------------------------*/
433/*---------------------------------------------------------------------------*/
440{
441 IParallelMng* pm = m_mesh->parallelMng();
442 const Int32 verbose_level = m_verbose_level;
445 items_sorter.setNeedIndexAndRank(false);
446 Real sort_begin_time = platform::getRealTime();
447 items_sorter.sort(m_items_owner_info);
448 Real sort_end_time = platform::getRealTime();
449 m_items_owner_info = items_sorter.keys();
450 info() << "END_ALL_ITEM_OWNER_SORTER time=" << (Real)(sort_end_time - sort_begin_time);
451 if (verbose_level >= 2)
452 for (const ItemOwnerInfo& x : m_items_owner_info) {
453 info() << "Sorted first_node_uid=" << x.m_first_node_uid << " item_uid="
454 << x.m_item_uid << " cell_uid=" << x.m_cell_uid << " owner=" << x.m_cell_owner;
455 }
456}
457
458/*---------------------------------------------------------------------------*/
459/*---------------------------------------------------------------------------*/
460
461void ItemsOwnerBuilderImpl::
462_processSortedInfos(ItemInternalMap& items_map)
463{
464 IParallelMng* pm = m_mesh->parallelMng();
465 const Int32 my_rank = pm->commRank();
466 const Int32 nb_rank = pm->commSize();
467 ConstArrayView<ItemOwnerInfo> items_owner_info = m_items_owner_info;
468 Int32 nb_sorted = items_owner_info.size();
469 info() << "NbSorted=" << nb_sorted;
470 const bool is_last_rank = ((my_rank + 1) == nb_rank);
471 const bool is_first_rank = (my_rank == 0);
472 const Int32 verbose_level = m_verbose_level;
473
474 // Comme les informations d'une entité peuvent être réparties sur plusieurs rangs
475 // après le tri, chaque rang envoie au rang suivant les informations
476 // de la dernière entité de sa liste.
477 // Il faut faire attention à bien envoyer la liste dans le même ordre trié pour
478 // garantir la cohérence car on va prendre le premier élément de la liste pour
479 // positionner le propriétaire.
480
481 UniqueArray<ItemOwnerInfo> items_owner_info_send_to_next;
482 if (nb_sorted > 0 && !is_last_rank) {
483 Int32 send_index = nb_sorted;
484 Int64 last_uid = items_owner_info[nb_sorted - 1].m_item_uid;
485 for (Int32 i = (nb_sorted - 1); i >= 0; --i) {
486 const ItemOwnerInfo& x = items_owner_info[i];
487 if (x.m_item_uid != last_uid) {
488 send_index = i + 1;
489 break;
490 }
491 }
492 info() << "SendIndext=" << send_index << " nb_sorted=" << nb_sorted;
493 for (Int32 i = send_index; i < nb_sorted; ++i) {
494 const ItemOwnerInfo& x = items_owner_info[i];
495 items_owner_info_send_to_next.add(x);
496 if (verbose_level >= 2)
497 info() << "AddSendToNext item_uid=" << x.m_item_uid << " owner=" << x.m_cell_owner
498 << " from_rank=" << x.m_item_sender_rank << " index=" << i;
499 }
500 }
501 Int32 nb_send_to_next = items_owner_info_send_to_next.size();
502 info() << "NbSendToNext=" << nb_send_to_next;
503
504 Int32 nb_to_receive_from_previous = 0;
505 SmallArray<Parallel::Request> requests;
506 // Envoie et recoit les tailles des tableaux
507 if (!is_last_rank)
508 requests.add(pm->send(ConstArrayView<Int32>(1, &nb_send_to_next), my_rank + 1, false));
509 if (!is_first_rank)
510 requests.add(pm->recv(ArrayView<Int32>(1, &nb_to_receive_from_previous), my_rank - 1, false));
511
512 pm->waitAllRequests(requests);
513 requests.clear();
514
515 // Envoie le tableau au suivant et récupère celui du précédent.
516 UniqueArray<ItemOwnerInfo> items_owner_info_received_from_previous(nb_to_receive_from_previous);
517 if (!is_last_rank)
518 requests.add(ItemOwnerInfoSortTraits::send(pm, my_rank + 1, items_owner_info_send_to_next));
519 if (!is_first_rank)
520 requests.add(ItemOwnerInfoSortTraits::recv(pm, my_rank - 1, items_owner_info_received_from_previous));
521 pm->waitAllRequests(requests);
522
523 // Supprime de la liste les entités qu'on a envoyé au suivant
524 m_items_owner_info.resize(nb_sorted - nb_send_to_next);
525 items_owner_info = m_items_owner_info.view();
526 nb_sorted = items_owner_info.size();
527 info() << "NbRemaining=" << nb_sorted;
528
529 Int64 current_item_uid = NULL_ITEM_UNIQUE_ID;
530 Int32 current_item_owner = A_NULL_RANK;
531
532 // Parcours la liste des entités qu'on a recu.
533 // Chaque entité est présente plusieurs fois dans la liste : au moins
534 // une fois par maille connectée à cette entité. Comme cette liste est triée
535 // par uniqueId() croissant de ces mailles, et que c'est la maille de plus
536 // petit uniqueId() qui donne le propriétaire de l'entité, alors le propriétaire
537 // est celui du premier élément de cette liste.
538 // On envoie ensuite à tous les rangs qui possèdent cette entité ce nouveau propriétaire.
539 // Le tableau envoyé contient une liste de couples (item_uid, item_new_owner).
540 impl::HashTableMap2<Int32, UniqueArray<Int64>> resend_items_owner_info_map;
541 for (Int32 index = 0; index < (nb_sorted + nb_to_receive_from_previous); ++index) {
542 const ItemOwnerInfo* first_ioi = nullptr;
543 // Si \a i est inférieur à nb_to_receive_from_previous, on prend
544 // les informations de la liste recue.
545 if (index < nb_to_receive_from_previous)
546 first_ioi = &items_owner_info_received_from_previous[index];
547 else
548 first_ioi = &items_owner_info[index - nb_to_receive_from_previous];
549 Int64 item_uid = first_ioi->m_item_uid;
550
551 // Si l'id courant est différent du précédent, on commence une nouvelle liste.
552 if (item_uid != current_item_uid) {
553 current_item_uid = item_uid;
555 current_item_owner = first_ioi->m_cell_owner;
556 else
557 current_item_owner = first_ioi->m_item_sender_rank;
558 if (verbose_level >= 2)
559 info() << "SetOwner from sorted index=" << index << " item_uid=" << current_item_uid << " new_owner=" << current_item_owner;
560 }
561 Int32 orig_sender = first_ioi->m_item_sender_rank;
562 UniqueArray<Int64>& send_array = resend_items_owner_info_map[orig_sender];
563 send_array.add(current_item_uid);
564 send_array.add(current_item_owner);
565 if (verbose_level >= 2)
566 info() << "SEND i=" << index << " rank=" << orig_sender << " item_uid=" << current_item_uid << " new_owner=" << current_item_owner;
567 }
568
569 auto exchanger{ ParallelMngUtils::createExchangerRef(pm) };
570 info() << "NbResendRanks=" << resend_items_owner_info_map.size();
571 for (const auto& [key, value] : resend_items_owner_info_map) {
572 if (verbose_level >= 1)
573 info() << "RESEND_INFO to_rank=" << key << " nb=" << value.size();
574 exchanger->addSender(key);
575 }
576 exchanger->initializeCommunicationsMessages();
577 {
578 Int32 index = 0;
579 for (const auto& [key, value] : resend_items_owner_info_map) {
580 ISerializeMessage* sm = exchanger->messageToSend(index);
581 ++index;
582 ISerializer* s = sm->serializer();
583 s->setMode(ISerializer::ModeReserve);
584 s->reserveArray(value);
585 s->allocateBuffer();
586 s->setMode(ISerializer::ModePut);
587 s->putArray(value);
588 }
589 }
590 exchanger->processExchange();
591 UniqueArray<Int64> receive_info;
592
593 for (Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
594 ISerializeMessage* sm = exchanger->messageToReceive(i);
595 ISerializer* s = sm->serializer();
596 s->setMode(ISerializer::ModeGet);
597 s->getArray(receive_info);
598 Int32 receive_size = receive_info.size();
599 if (verbose_level >= 1)
600 info() << "RECEIVE_INFO size=" << receive_size << " rank2=" << sm->destination();
601 // Vérifie que la taille est un multiple de 2
602 if ((receive_size % 2) != 0)
603 ARCANE_FATAL("Size '{0}' is not a multiple of 2", receive_size);
604 Int32 buf_size = receive_size / 2;
605 for (Int32 z = 0; z < buf_size; ++z) {
606 Int64 item_uid = receive_info[z * 2];
607 Int32 item_owner = CheckedConvert::toInt32(receive_info[(z * 2) + 1]);
608 impl::ItemBase x = items_map.findItem(item_uid);
609 if (verbose_level >= 2)
610 info() << "SetOwner uid=" << item_uid << " new_owner=" << item_owner;
611 x.toMutable().setOwner(item_owner, my_rank);
612 }
613 }
614}
615
616/*---------------------------------------------------------------------------*/
617/*---------------------------------------------------------------------------*/
618
619/*---------------------------------------------------------------------------*/
620/*---------------------------------------------------------------------------*/
621
622ItemsOwnerBuilder::
623ItemsOwnerBuilder(IMesh* mesh)
624: m_p(std::make_unique<ItemsOwnerBuilderImpl>(mesh))
625{}
626
627ItemsOwnerBuilder::
628~ItemsOwnerBuilder()
629{
630 // Le destructeur doit être dans le '.cc' car 'ItemsOwnerBuilderImpl' n'est
631 // pas connu dans le '.h'.
632}
633
634/*---------------------------------------------------------------------------*/
635/*---------------------------------------------------------------------------*/
636
637void ItemsOwnerBuilder::
638computeFacesOwner()
639{
640 m_p->computeFacesOwner();
641}
642
643/*---------------------------------------------------------------------------*/
644/*---------------------------------------------------------------------------*/
645
646void ItemsOwnerBuilder::
647computeEdgesOwner()
648{
649 m_p->computeEdgesOwner();
650}
651
652/*---------------------------------------------------------------------------*/
653/*---------------------------------------------------------------------------*/
654
655void ItemsOwnerBuilder::
656computeNodesOwner()
657{
658 m_p->computeNodesOwner();
659}
660
661/*---------------------------------------------------------------------------*/
662/*---------------------------------------------------------------------------*/
663
664} // namespace Arcane::mesh
665
666/*---------------------------------------------------------------------------*/
667/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
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:534
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:563
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.