Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ItemsOwnerBuilder.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* Class for calculating entity owners. */
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 * This file contains an algorithm to calculate the owners of
45 * entities other than cells, based on the owners of the cells.
46 *
47 * The algorithm assumes that the owners of the cells are up-to-date and
48 * synchronized. The owner of an entity will then be the owner of the cell
49 * with the smallest uniqueId() connected to this entity.
50 *
51 * In parallel, if an entity is on the boundary of a subdomain, it is not
52 * possible to know all the cells connected to it.
53 * To solve this problem, we create a list of boundary entities containing for
54 * each connected cell a triplet (entity uniqueId(), connected cell uniqueId(),
55 * owner() of the connected cell).
56 * This list is then sorted in parallel (via BitonicSort) by the entity
57 * uniqueId(), then by the cell uniqueId().
58 * To determine the owner of an entity, it is enough to take the owner of the
59 * cell associated with the first occurrence of the entity in this sorted list.
60 * Once this is done, this information is sent to the ranks that possess this
61 * entity.
62 */
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
68class ItemsOwnerBuilderImpl
69: public TraceAccessor
70{
72
79 class ItemOwnerInfo
80 {
81 public:
82
83 ItemOwnerInfo() = default;
84 ItemOwnerInfo(Int64 item_uid, Int64 first_node_uid, Int64 cell_uid, Int32 sender_rank, Int32 cell_owner)
85 : m_item_uid(item_uid)
86 , m_first_node_uid(first_node_uid)
87 , m_cell_uid(cell_uid)
88 , m_item_sender_rank(sender_rank)
89 , m_cell_owner(cell_owner)
90 {
91 }
92
93 public:
94
96 Int64 m_item_uid = NULL_ITEM_UNIQUE_ID;
98 Int64 m_first_node_uid = NULL_ITEM_UNIQUE_ID;
100 Int64 m_cell_uid = NULL_ITEM_UNIQUE_ID;
104 Int32 m_cell_owner = A_NULL_RANK;
105 };
106
107 public:
108
109 explicit ItemsOwnerBuilderImpl(IMesh* mesh);
110
111 public:
112
113 void computeFacesOwner();
114 void computeEdgesOwner();
115 void computeNodesOwner();
116
117 private:
118
119 DynamicMesh* m_mesh = nullptr;
120 Int32 m_verbose_level = 0;
121 UniqueArray<ItemOwnerInfo> m_items_owner_info;
130
131 private:
132
133 void _sortInfos();
134 void _processSortedInfos(ItemInternalMap& items_map);
135};
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
144{
145 public:
146
147 explicit ItemOwnerInfoSortTraits(bool use_cell_uid_to_sort)
148 : m_use_cell_uid_to_sort(use_cell_uid_to_sort)
149 {}
150
151 public:
152
153 bool compareLess(const ItemOwnerInfo& k1, const ItemOwnerInfo& k2) const
154 {
156 return true;
158 return false;
159
160 if (k1.m_item_uid < k2.m_item_uid)
161 return true;
162 if (k1.m_item_uid > k2.m_item_uid)
163 return false;
164
165 if (m_use_cell_uid_to_sort) {
166 if (k1.m_cell_uid < k2.m_cell_uid)
167 return true;
168 if (k1.m_cell_uid > k2.m_cell_uid)
169 return false;
170
172 return true;
174 return false;
175 }
176 else {
178 return true;
180 return false;
181
182 if (k1.m_cell_uid < k2.m_cell_uid)
183 return true;
184 if (k1.m_cell_uid > k2.m_cell_uid)
185 return false;
186 }
187 // ke.node2_uid == k2.node2_uid
188 return (k1.m_cell_owner < k2.m_cell_owner);
189 }
190
192 {
193 const ItemOwnerInfo* fsi_base = values.data();
194 return pm->send(ByteConstArrayView(messageSize(values), reinterpret_cast<const Byte*>(fsi_base)), rank, false);
195 }
196 static Parallel::Request recv(IParallelMng* pm, Int32 rank, ArrayView<ItemOwnerInfo> values)
197 {
198 ItemOwnerInfo* fsi_base = values.data();
199 return pm->recv(ByteArrayView(messageSize(values), reinterpret_cast<Byte*>(fsi_base)), rank, false);
200 }
201 static Integer messageSize(ConstArrayView<ItemOwnerInfo> values)
202 {
203 return CheckedConvert::toInteger(values.size() * sizeof(ItemOwnerInfo));
204 }
205 static ItemOwnerInfo maxValue()
206 {
207 return ItemOwnerInfo(INT64_MAX, INT64_MAX, INT64_MAX, INT32_MAX, INT32_MAX);
208 }
209 static bool isValid(const ItemOwnerInfo& fsi)
210 {
211 return fsi.m_item_uid != INT64_MAX;
212 }
213
214 private:
215
216 bool m_use_cell_uid_to_sort = true;
217};
218
219/*---------------------------------------------------------------------------*/
220/*---------------------------------------------------------------------------*/
221
222/*---------------------------------------------------------------------------*/
223/*---------------------------------------------------------------------------*/
224
225ItemsOwnerBuilderImpl::
226ItemsOwnerBuilderImpl(IMesh* mesh)
228{
229 auto* dm = dynamic_cast<DynamicMesh*>(mesh);
230 if (!dm)
231 ARCANE_FATAL("Mesh is not an instance of 'DynamicMesh'");
232 m_mesh = dm;
233 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ITEMS_OWNER_BUILDER_IMPL_DEBUG_LEVEL", true))
234 m_verbose_level = v.value();
235 // Indicates if sorting is done based on the cell with the smallest uniqueId()
236 // or based on the smallest rank.
237 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ITEMS_OWNER_BUILDER_USE_RANK", true))
238 m_use_cell_uid_to_sort = !v.value();
239}
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
244void ItemsOwnerBuilderImpl::
245computeFacesOwner()
246{
247 m_items_owner_info.clear();
248
249 IParallelMng* pm = m_mesh->parallelMng();
250 const Int32 my_rank = pm->commRank();
251 ItemInternalMap& faces_map = m_mesh->facesMap();
252 FaceFamily& face_family = m_mesh->trueFaceFamily();
253
254 info() << "** BEGIN ComputeFacesOwner nb_face=" << faces_map.count();
255
256 // Iterates over all faces.
257 // Only keeps those that are boundary or whose owners of the two cells on
258 // either side are different from our subdomain.
259 UniqueArray<Int32> faces_to_add;
260 UniqueArray<Int64> faces_to_add_uid;
261 faces_map.eachItem([&](Face face) {
262 Int32 nb_cell = face.nbCell();
263 if (nb_cell == 2)
264 if (face.cell(0).owner() == my_rank && face.cell(1).owner() == my_rank) {
265 face.mutableItemBase().setOwner(my_rank, my_rank);
266 return;
267 }
268 faces_to_add.add(face.localId());
269 faces_to_add_uid.add(face.uniqueId());
270 });
271 info() << "ItemsOwnerBuilder: NB_FACE_TO_TRANSFER=" << faces_to_add.size();
272 const Int32 verbose_level = m_verbose_level;
273
274 FaceInfoListView faces(&face_family);
275 for (Int32 lid : faces_to_add) {
276 Face face(faces[lid]);
277 Int64 face_uid = face.uniqueId();
278 for (Cell cell : face.cells()) {
279 if (verbose_level >= 2)
280 info() << "ADD lid=" << lid << " uid=" << face_uid << " cell_uid=" << cell.uniqueId() << " owner=" << cell.owner();
281 m_items_owner_info.add(ItemOwnerInfo(face_uid, face.node(0).uniqueId(), cell.uniqueId(), my_rank, cell.owner()));
282 }
283 }
284
285 // Sorts the ItemOwnerInfo instances and places the sorted values
286 // into items_owner_info.
287 _sortInfos();
288 _processSortedInfos(faces_map);
289
290 face_family.notifyItemsOwnerChanged();
291}
292
293/*---------------------------------------------------------------------------*/
294/*---------------------------------------------------------------------------*/
295
296void ItemsOwnerBuilderImpl::
297computeEdgesOwner()
298{
299 m_items_owner_info.clear();
300
301 IParallelMng* pm = m_mesh->parallelMng();
302 const Int32 my_rank = pm->commRank();
303 ItemInternalMap& edges_map = m_mesh->edgesMap();
304 EdgeFamily& edge_family = m_mesh->trueEdgeFamily();
305
306 info() << "** BEGIN ComputeEdgesOwner nb_edge=" << edges_map.count();
307
308 // Iterates over all edges.
309 // Only keeps those that are boundary or whose owners of at least one of the
310 // connected cells are different from our subdomain.
311 UniqueArray<Int32> edges_to_add;
312 UniqueArray<Int64> edges_to_add_uid;
313 // Brute force adds all edges.
314 // This ensures that the owners are calculated correctly, even if we cannot
315 // determine the boundary edges.
316 // This is not optimal, because we also send our internal edges
317 // even though we are certain that we are their owner.
318 bool do_brute_force = true;
319 edges_map.eachItem([&](Edge edge) {
320 Int32 nb_cell = edge.nbCell();
321 Int32 nb_cell_with_my_rank = 0;
322 for (Cell cell : edge.cells())
323 if (cell.owner() == my_rank)
324 ++nb_cell_with_my_rank;
325 bool do_add = (nb_cell == 1 || (nb_cell != nb_cell_with_my_rank));
326 if (do_add || do_brute_force) {
327 edges_to_add.add(edge.localId());
328 edges_to_add_uid.add(edge.uniqueId());
329 }
330 else
331 edge.mutableItemBase().setOwner(my_rank, my_rank);
332 });
333 info() << "ItemsOwnerBuilder: NB_FACE_TO_TRANSFER=" << edges_to_add.size();
334 const Int32 verbose_level = m_verbose_level;
335
336 EdgeInfoListView edges(&edge_family);
337 for (Int32 lid : edges_to_add) {
338 Edge edge(edges[lid]);
339 Int64 edge_uid = edge.uniqueId();
340 for (Cell cell : edge.cells()) {
341 if (verbose_level >= 2)
342 info() << "ADD lid=" << lid << " uid=" << edge_uid << " cell_uid=" << cell.uniqueId() << " owner=" << cell.owner();
343 m_items_owner_info.add(ItemOwnerInfo(edge_uid, edge.node(0).uniqueId(), cell.uniqueId(), my_rank, cell.owner()));
344 }
345 }
346
347 // Sorts the ItemOwnerInfo instances and places the sorted values
348 // in items_owner_info.
349 _sortInfos();
350 _processSortedInfos(edges_map);
351
352 edge_family.notifyItemsOwnerChanged();
353}
354
355/*---------------------------------------------------------------------------*/
356/*---------------------------------------------------------------------------*/
357
358void ItemsOwnerBuilderImpl::
359computeNodesOwner()
360{
361 m_items_owner_info.clear();
362
363 IParallelMng* pm = m_mesh->parallelMng();
364 const Int32 my_rank = pm->commRank();
365 ItemInternalMap& faces_map = m_mesh->facesMap();
366 ItemInternalMap& nodes_map = m_mesh->nodesMap();
367 NodeFamily& node_family = m_mesh->trueNodeFamily();
368
369 info() << "** BEGIN ComputeNodesOwner nb_node=" << nodes_map.count();
370
371 // By default, place all nodes in this subdomain
372 nodes_map.eachItem([&](Node node) {
373 node.mutableItemBase().setOwner(my_rank, my_rank);
374 });
375
376 // Iterates over all boundary faces and adds their nodes
377 // to the list of nodes to process (nodes_to_add). Boundary faces are
378 // those connected to only one cell.
379 // connected to only one cell.
380 const Int32 verbose_level = m_verbose_level;
381
382 // List of nodes to process
383 UniqueArray<Int32> nodes_to_add;
384
385 // Set to determine if a node has already been added to \a nodes_to_add.
386 std::unordered_set<Int32> done_nodes;
387
388 const bool is_mono_dimension = m_mesh->meshKind().isMonoDimension();
389
390 FaceInfoListView faces(m_mesh->faceFamily());
391 if (is_mono_dimension) {
392 faces_map.eachItem([&](Face face) {
393 Int32 face_nb_cell = face.nbCell();
394 if (face_nb_cell == 2)
395 return;
396 for (Node node : face.nodes()) {
397 Int32 node_id = node.localId();
398 if (done_nodes.find(node_id) == done_nodes.end()) {
399 nodes_to_add.add(node_id);
400 done_nodes.insert(node_id);
401 node.mutableItemBase().setOwner(A_NULL_RANK, my_rank);
402 }
403 }
404 });
405 }
406 else {
407 // In the case of multi-dimension meshing, there is currently
408 // no simple way to detect boundary nodes. We therefore process all
409 // nodes even if it is not optimal.
410 // NOTE: Detection is difficult only for nodes connected to cells
411 // of dimension 1 or 2. For 3D cells, we could only add
412 // nodes connected to a face having only one cell.
413 ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
414 nodes_to_add.add(inode.itemLocalId());
415 }
416 }
417
418 info() << "ItemsOwnerBuilder: NB_NODE_TO_ADD=" << nodes_to_add.size() << " is_mono_dim=" << is_mono_dimension;
419 NodeInfoListView nodes(&node_family);
420 for (Int32 lid : nodes_to_add) {
421 Node node(nodes[lid]);
422 Int64 node_uid = node.uniqueId();
423 for (Cell cell : node.cells()) {
424 if (verbose_level >= 2)
425 info() << "ADD lid=" << lid << " uid=" << node_uid << " cell_uid=" << cell.uniqueId() << " owner=" << cell.owner();
426 m_items_owner_info.add(ItemOwnerInfo(node_uid, node_uid, cell.uniqueId(), my_rank, cell.owner()));
427 }
428 }
429
430 // Sorts the instances contained in m_items_owner_info and replaces the sorted values
431 // in this same array.
432 _sortInfos();
433 _processSortedInfos(nodes_map);
434
435 node_family.notifyItemsOwnerChanged();
436}
437
438/*---------------------------------------------------------------------------*/
439/*---------------------------------------------------------------------------*/
446{
447 IParallelMng* pm = m_mesh->parallelMng();
448 const Int32 verbose_level = m_verbose_level;
451 items_sorter.setNeedIndexAndRank(false);
452 Real sort_begin_time = platform::getRealTime();
453 items_sorter.sort(m_items_owner_info);
454 Real sort_end_time = platform::getRealTime();
455 m_items_owner_info = items_sorter.keys();
456 info() << "END_ALL_ITEM_OWNER_SORTER time=" << (Real)(sort_end_time - sort_begin_time);
457 if (verbose_level >= 2)
458 for (const ItemOwnerInfo& x : m_items_owner_info) {
459 info() << "Sorted first_node_uid=" << x.m_first_node_uid << " item_uid="
460 << x.m_item_uid << " cell_uid=" << x.m_cell_uid << " owner=" << x.m_cell_owner;
461 }
462}
463
464/*---------------------------------------------------------------------------*/
465/*---------------------------------------------------------------------------*/
466
467void ItemsOwnerBuilderImpl::
468_processSortedInfos(ItemInternalMap& items_map)
469{
470 IParallelMng* pm = m_mesh->parallelMng();
471 const Int32 my_rank = pm->commRank();
472 const Int32 nb_rank = pm->commSize();
473 ConstArrayView<ItemOwnerInfo> items_owner_info = m_items_owner_info;
474 Int32 nb_sorted = items_owner_info.size();
475 info() << "NbSorted=" << nb_sorted;
476 const bool is_last_rank = ((my_rank + 1) == nb_rank);
477 const bool is_first_rank = (my_rank == 0);
478 const Int32 verbose_level = m_verbose_level;
479
480 // Since the information for an entity can be distributed across multiple ranks
481 // after sorting, each rank sends the information of the last entity in its list
482 // to the next rank.
483 // Care must be taken to send the list in the same sorted order to guarantee
484 // consistency because we will take the first element of the list to
485 // position the owner.
486
487 UniqueArray<ItemOwnerInfo> items_owner_info_send_to_next;
488 if (nb_sorted > 0 && !is_last_rank) {
489 Int32 send_index = nb_sorted;
490 Int64 last_uid = items_owner_info[nb_sorted - 1].m_item_uid;
491 for (Int32 i = (nb_sorted - 1); i >= 0; --i) {
492 const ItemOwnerInfo& x = items_owner_info[i];
493 if (x.m_item_uid != last_uid) {
494 send_index = i + 1;
495 break;
496 }
497 }
498 info() << "SendIndext=" << send_index << " nb_sorted=" << nb_sorted;
499 for (Int32 i = send_index; i < nb_sorted; ++i) {
500 const ItemOwnerInfo& x = items_owner_info[i];
501 items_owner_info_send_to_next.add(x);
502 if (verbose_level >= 2)
503 info() << "AddSendToNext item_uid=" << x.m_item_uid << " owner=" << x.m_cell_owner
504 << " from_rank=" << x.m_item_sender_rank << " index=" << i;
505 }
506 }
507 Int32 nb_send_to_next = items_owner_info_send_to_next.size();
508 info() << "NbSendToNext=" << nb_send_to_next;
509
510 Int32 nb_to_receive_from_previous = 0;
511 SmallArray<Parallel::Request> requests;
512 // Sends and receives the sizes of the arrays
513 if (!is_last_rank)
514 requests.add(pm->send(ConstArrayView<Int32>(1, &nb_send_to_next), my_rank + 1, false));
515 if (!is_first_rank)
516 requests.add(pm->recv(ArrayView<Int32>(1, &nb_to_receive_from_previous), my_rank - 1, false));
517
518 pm->waitAllRequests(requests);
519 requests.clear();
520
521 // Sends the array to the next and receives the one from the previous.
522 UniqueArray<ItemOwnerInfo> items_owner_info_received_from_previous(nb_to_receive_from_previous);
523 if (!is_last_rank)
524 requests.add(ItemOwnerInfoSortTraits::send(pm, my_rank + 1, items_owner_info_send_to_next));
525 if (!is_first_rank)
526 requests.add(ItemOwnerInfoSortTraits::recv(pm, my_rank - 1, items_owner_info_received_from_previous));
527 pm->waitAllRequests(requests);
528
529 // Removes the entities that were sent to the next
530 m_items_owner_info.resize(nb_sorted - nb_send_to_next);
531 items_owner_info = m_items_owner_info.view();
532 nb_sorted = items_owner_info.size();
533 info() << "NbRemaining=" << nb_sorted;
534
535 Int64 current_item_uid = NULL_ITEM_UNIQUE_ID;
536 Int32 current_item_owner = A_NULL_RANK;
537
538 // Iterates over the list of entities received.
539 // Each entity is present multiple times in the list: at least
540 // once per cell connected to this entity. Since this list is sorted
541 // by increasing uniqueId() of these cells, and the cell with the smallest
542 // uniqueId() determines the owner of the entity, the owner is that of the first
543 // element in this list.
544 // This new owner is then sent to all ranks that own this entity.
545 // The array sent contains a list of pairs (item_uid, item_new_owner).
546 impl::HashTableMap2<Int32, UniqueArray<Int64>> resend_items_owner_info_map;
547 for (Int32 index = 0; index < (nb_sorted + nb_to_receive_from_previous); ++index) {
548 const ItemOwnerInfo* first_ioi = nullptr;
549 // If \a i is less than nb_to_receive_from_previous, take
550 // the information from the received list.
551 if (index < nb_to_receive_from_previous)
552 first_ioi = &items_owner_info_received_from_previous[index];
553 else
554 first_ioi = &items_owner_info[index - nb_to_receive_from_previous];
555 Int64 item_uid = first_ioi->m_item_uid;
556
557 // If the current id is different from the previous one, start a new list.
558 if (item_uid != current_item_uid) {
559 current_item_uid = item_uid;
561 current_item_owner = first_ioi->m_cell_owner;
562 else
563 current_item_owner = first_ioi->m_item_sender_rank;
564 if (verbose_level >= 2)
565 info() << "SetOwner from sorted index=" << index << " item_uid=" << current_item_uid << " new_owner=" << current_item_owner;
566 }
567 Int32 orig_sender = first_ioi->m_item_sender_rank;
568 UniqueArray<Int64>& send_array = resend_items_owner_info_map[orig_sender];
569 send_array.add(current_item_uid);
570 send_array.add(current_item_owner);
571 if (verbose_level >= 2)
572 info() << "SEND i=" << index << " rank=" << orig_sender << " item_uid=" << current_item_uid << " new_owner=" << current_item_owner;
573 }
574
575 auto exchanger{ ParallelMngUtils::createExchangerRef(pm) };
576 info() << "NbResendRanks=" << resend_items_owner_info_map.size();
577 for (const auto& [key, value] : resend_items_owner_info_map) {
578 if (verbose_level >= 1)
579 info() << "RESEND_INFO to_rank=" << key << " nb=" << value.size();
580 exchanger->addSender(key);
581 }
582 exchanger->initializeCommunicationsMessages();
583 {
584 Int32 index = 0;
585 for (const auto& [key, value] : resend_items_owner_info_map) {
586 ISerializeMessage* sm = exchanger->messageToSend(index);
587 ++index;
588 ISerializer* s = sm->serializer();
589 s->setMode(ISerializer::ModeReserve);
590 s->reserveArray(value);
591 s->allocateBuffer();
592 s->setMode(ISerializer::ModePut);
593 s->putArray(value);
594 }
595 }
596 exchanger->processExchange();
597 UniqueArray<Int64> receive_info;
598
599 for (Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
600 ISerializeMessage* sm = exchanger->messageToReceive(i);
601 ISerializer* s = sm->serializer();
602 s->setMode(ISerializer::ModeGet);
603 s->getArray(receive_info);
604 Int32 receive_size = receive_info.size();
605 if (verbose_level >= 1)
606 info() << "RECEIVE_INFO size=" << receive_size << " rank2=" << sm->destination();
607 // Checks that the size is a multiple of 2
608 if ((receive_size % 2) != 0)
609 ARCANE_FATAL("Size '{0}' is not a multiple of 2", receive_size);
610 Int32 buf_size = receive_size / 2;
611 for (Int32 z = 0; z < buf_size; ++z) {
612 Int64 item_uid = receive_info[z * 2];
613 Int32 item_owner = CheckedConvert::toInt32(receive_info[(z * 2) + 1]);
614 impl::ItemBase x = items_map.findItem(item_uid);
615 if (verbose_level >= 2)
616 info() << "SetOwner uid=" << item_uid << " new_owner=" << item_owner;
617 x.toMutable().setOwner(item_owner, my_rank);
618 }
619 }
620}
621
622/*---------------------------------------------------------------------------*/
623/*---------------------------------------------------------------------------*/
624
625/*---------------------------------------------------------------------------*/
626/*---------------------------------------------------------------------------*/
627
628ItemsOwnerBuilder::
629ItemsOwnerBuilder(IMesh* mesh)
630: m_p(std::make_unique<ItemsOwnerBuilderImpl>(mesh))
631{}
632
633ItemsOwnerBuilder::
634~ItemsOwnerBuilder()
635{
636 // The destructor must be in the '.cc' because 'ItemsOwnerBuilderImpl' is not
637 // known in the '.h'.
638}
639
640/*---------------------------------------------------------------------------*/
641/*---------------------------------------------------------------------------*/
642
643void ItemsOwnerBuilder::
644computeFacesOwner()
645{
646 m_p->computeFacesOwner();
647}
648
649/*---------------------------------------------------------------------------*/
650/*---------------------------------------------------------------------------*/
651
652void ItemsOwnerBuilder::
653computeEdgesOwner()
654{
655 m_p->computeEdgesOwner();
656}
657
658/*---------------------------------------------------------------------------*/
659/*---------------------------------------------------------------------------*/
660
661void ItemsOwnerBuilder::
662computeNodesOwner()
663{
664 m_p->computeNodesOwner();
665}
666
667/*---------------------------------------------------------------------------*/
668/*---------------------------------------------------------------------------*/
669
670} // namespace Arcane::mesh
671
672/*---------------------------------------------------------------------------*/
673/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the start of the view.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Constant view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
Template class for converting a type.
Face of a cell.
Definition Item.h:1032
Cell cell(Int32 i) const
i-th cell of the face
Definition Item.h:1793
Int32 nbCell() const
Number of cells of the face (1 or 2).
Definition Item.h:1129
CellConnectedListViewType cells() const
List of cells of the face.
Definition Item.h:1135
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Blocks while waiting for the rvalues requests to complete.
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
Int32 owner() const
Owner subdomain number of the entity.
Definition Item.h:252
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
Parallel bitonic sort algorithm.
ConstArrayView< KeyType > keys() const override
After a sort, returns the list of elements on this rank.
void sort(ConstArrayView< KeyType > keys) override
Parallelly sorts the elements of keys on all ranks.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Implementation of a mesh.
Definition DynamicMesh.h:98
IParallelMng * parallelMng() override
Parallelism manager.
void notifyItemsOwnerChanged() override
Notifies that the entities specific to the family's subdomain have been modified.
Associative array of ItemInternal.
impl::ItemBase findItem(Int64 uid) const
Returns the unique ID entity uid.
void eachItem(const Lambda &lambda)
Template function to iterate over the instance's entities.
Int32 count() const
Number of elements in the table.
Int32 m_item_sender_rank
rank of the one who created this instance
Int64 m_first_node_uid
uniqueId() of the first node of the entity
Int32 m_cell_owner
Owner of the cell connected to this entity.
Int64 m_cell_uid
uniqueId() of the cell to which the entity belongs
bool m_use_cell_uid_to_sort
Indicates how to perform the sort.
void _sortInfos()
Sorts the instances contained in m_items_owner_info and replaces the sorted values in this same array...
Ref< IParallelExchanger > createExchangerRef(IParallelMng *pm)
Returns an interface to transfer messages between ranks.
Real getRealTime()
Real time used in seconds.
ArrayView< Byte > ByteArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:447
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:43
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
std::int32_t Int32
Signed integer type of 32 bits.