Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
MeshExchange.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/* MeshExchange.cc (C) 2000-2025 */
9/* */
10/* Exchanges a mesh between sub-domains. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Iterator.h"
15#include "arcane/utils/ITraceMng.h"
16#include "arcane/utils/ScopedPtr.h"
17#include "arcane/utils/Collection.h"
18
19#include "arcane/core/IMesh.h"
20#include "arcane/core/ISubDomain.h"
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/IParallelExchanger.h"
23#include "arcane/core/IItemFamily.h"
25#include "arcane/core/Item.h"
26#include "arcane/core/MeshVariable.h"
27#include "arcane/core/IParticleFamily.h"
28#include "arcane/core/ParallelMngUtils.h"
29#include "arcane/core/ConnectivityItemVector.h"
30#include "arcane/core/IndexedItemConnectivityView.h"
31#include "arcane/core/ItemPrinter.h"
32#include "arcane/core/IParallelMng.h"
33#include "arcane/core/VariableTypes.h"
34#include "arcane/core/IItemFamilyNetwork.h"
35#include "arcane/core/IGhostLayerMng.h"
36#include "arcane/core/ConnectivityItemVector.h"
37#include "arcane/core/IVariableSynchronizer.h"
38#include "arcane/core/ISerializeMessage.h"
39#include "arcane/core/ISerializer.h"
40
41#include "arcane/mesh/IndexedItemConnectivityAccessor.h"
42#include "arcane/mesh/MeshExchange.h"
43#include "arcane/mesh/NewItemOwnerBuilder.h"
44
45#include <algorithm>
46
47/*---------------------------------------------------------------------------*/
48/*---------------------------------------------------------------------------*/
49
50namespace Arcane::mesh
51{
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
55template <typename T>
57{
58 public:
59
60 IncrementalUnorderedMultiArray(Integer size)
61 : m_current_increment(-1)
62 , m_current_size(0)
63 , m_index(size, -1)
64 , m_size(size, 0)
65 {
66 }
67
68 IncrementalUnorderedMultiArray()
69 : m_current_increment(-1)
70 , m_current_size(0)
71 {}
72
73 inline void resize(Integer size)
74 {
75 m_index.resize(size, -1);
76 m_size.resize(size, 0);
77 }
78
79 inline Integer size() const
80 {
81 return m_index.size();
82 }
83
84 inline void dataReserve(Integer size)
85 {
86 m_data.reserve(size);
87 }
88
89 inline void addData(const T data)
90 {
91 m_data.add(data);
92 m_current_size++;
93 }
94
95 inline Int32 index(Integer id) const
96 {
97 return m_index[id];
98 }
99
100 inline void beginIncrement(Integer id)
101 {
102 ARCANE_ASSERT((m_current_increment == -1), ("call endIncrement before begin"));
103 m_current_increment = id;
104 m_current_size = 0;
105 m_index[m_current_increment] = m_data.size();
106 }
107
108 inline void endIncrement()
109 {
110 m_size[m_current_increment] = m_current_size;
111 m_current_increment = -1;
112 m_current_size = 0;
113 }
114
115 inline ArrayView<T> at(Integer id)
116 {
117 return m_data.subView(m_index[id], m_size[id]);
118 }
119
120 inline ConstArrayView<T> at(Integer id) const
121 {
122 return m_data.subView(m_index[id], m_size[id]);
123 }
124
125 private:
126
127 Integer m_current_increment;
128 Integer m_current_size;
129 Int32UniqueArray m_index;
130 Int32UniqueArray m_size;
131 UniqueArray<T> m_data;
132};
133
134/*---------------------------------------------------------------------------*/
135/*---------------------------------------------------------------------------*/
136
137template <typename T>
139{
140 public:
141
142 DynamicMultiArray(Integer size)
143 : m_data(size)
144 {}
145
146 DynamicMultiArray() {}
147
148 inline void resize(Integer size)
149 {
150 m_data.resize(size);
151 }
152
153 inline Integer size() const
154 {
155 return m_data.size();
156 }
157
158 inline void addData(Integer id, const T data)
159 {
160 m_data[id].add(data);
161 }
162
163 inline UniqueArray<T>& at(Integer id)
164 {
165 return m_data[id];
166 }
167
168 inline ConstArrayView<T> at(Integer id) const
169 {
170 return m_data[id];
171 }
172
173 private:
174
176};
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
181MeshExchange::
182MeshExchange(IMesh* mesh)
183: TraceAccessor(mesh->traceMng())
184, m_mesh(mesh)
185, m_parallel_mng(mesh->parallelMng())
186, m_nb_rank(m_parallel_mng->commSize())
187, m_rank(m_parallel_mng->commRank())
188, m_cell_family(mesh->itemFamily(IK_Cell))
189, m_neighbour_cells_owner(NULL)
190, m_neighbour_cells_new_owner(NULL)
191, m_neighbour_extra_cells_owner(NULL)
192, m_neighbour_extra_cells_new_owner(NULL)
193{
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
199MeshExchange::
200~MeshExchange()
201{
202 for (const auto& itosend : m_items_to_send)
203 delete itosend.second;
204 delete m_neighbour_cells_owner;
205 delete m_neighbour_cells_new_owner;
206 delete m_neighbour_extra_cells_owner;
207 delete m_neighbour_extra_cells_new_owner;
208 for (const auto& idestrank : m_item_dest_ranks_map)
209 delete idestrank.second;
210 for (const auto& ighostdestrank_map : m_ghost_item_dest_ranks_map)
211 for (const auto& ighostdestrank : ighostdestrank_map)
212 delete ighostdestrank.second;
213}
214
215/*---------------------------------------------------------------------------*/
216/*---------------------------------------------------------------------------*/
217
220getItemsToSend(IItemFamily* family) const
221{
222 auto iter = m_items_to_send.find(family);
223 if (iter == m_items_to_send.end())
224 ARCANE_FATAL("No items to send for family '{0}'", family->name());
225 return iter->second->constView();
226}
227
228/*---------------------------------------------------------------------------*/
229/*---------------------------------------------------------------------------*/
230
234{
235 auto iter = m_items_to_send.find(family);
236 if (iter == m_items_to_send.end())
237 ARCANE_FATAL("No items to send for family '{0}'", family->name());
238 return iter->second->view();
239}
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
246{
247 // Create the arrays containing the list of entities
248 // to send for each family.
249 for (IItemFamily* family : m_mesh->itemFamilies()) {
250 m_items_to_send.insert(std::make_pair(family, new UniqueArray<std::set<Int32>>));
251 }
252
253 Int32ConstArrayView cells_new_owner(m_cell_family->itemsNewOwner().asArray());
255 if (m_mesh->isAmrActivated()) {
256 _computeMeshConnectivityInfos2(cells_new_owner);
257 _computeGraphConnectivityInfos();
258 _exchangeCellDataInfos(cells_new_owner, true);
259 _markRemovableCells(cells_new_owner, true);
260 _markRemovableParticles();
261 _computeItemsToSend2();
262 }
263 else if (m_mesh->itemFamilyNetwork() && m_mesh->itemFamilyNetwork()->isActivated()) {
264 if (m_mesh->useMeshItemFamilyDependencies()) {
266 _computeGraphConnectivityInfos();
267 _exchangeCellDataInfos3(); // todo rename itemDataInfo
268 _exchangeGhostItemDataInfos();
269 _markRemovableItems();
270 _markRemovableParticles();
271 _computeItemsToSend3();
272 }
273 else {
274 //Manage Mesh item_families in standard way
275 _computeMeshConnectivityInfos(cells_new_owner);
277 _computeGraphConnectivityInfos();
278 _exchangeCellDataInfos(cells_new_owner, false);
279 _exchangeCellDataInfos3();
280 //_exchangeGhostItemDataInfos();
281 //_markRemovableItems();
282 _markRemovableDoFs();
283 _markRemovableCells(cells_new_owner, false);
284 _markRemovableParticles();
285 _computeItemsToSend(true);
286 }
287 }
288 else {
289 _computeMeshConnectivityInfos(cells_new_owner);
290 _computeGraphConnectivityInfos();
291 _exchangeCellDataInfos(cells_new_owner, false);
292 _markRemovableCells(cells_new_owner, false);
293 _markRemovableParticles();
294 _computeItemsToSend();
295 }
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
301void MeshExchange::
302_computeGraphConnectivityInfos()
303{
304 const Integer cell_variable_size = m_cell_family->maxLocalId();
305
306 Int32UniqueArray tmp_new_owner(m_nb_rank);
307 tmp_new_owner.fill(NULL_ITEM_ID);
308 Int32UniqueArray tmp_owner(m_nb_rank);
309 tmp_owner.fill(NULL_ITEM_ID);
310
311 Int32UniqueArray tmp_link_new_owner(m_nb_rank);
312 tmp_link_new_owner.fill(NULL_ITEM_ID);
313 Int32UniqueArray tmp_link_owner(m_nb_rank);
314 tmp_link_owner.fill(NULL_ITEM_ID);
315
316 mesh::NewItemOwnerBuilder owner_builder;
317
318 m_neighbour_extra_cells_owner = new DynamicMultiArray<Int32>(cell_variable_size);
319 m_neighbour_extra_cells_new_owner = new DynamicMultiArray<Int32>(cell_variable_size);
320
321 if (m_mesh->itemFamilyNetwork() && m_mesh->itemFamilyNetwork()->isActivated()) {
322 _addGraphConnectivityToNewConnectivityInfo();
323 }
324}
325
326/*---------------------------------------------------------------------------*/
327/*---------------------------------------------------------------------------*/
328
329void MeshExchange::
330_addGraphConnectivityToNewConnectivityInfo()
331{
332 ENUMERATE_CELL (icell, m_cell_family->allItems()) {
333 Int32Array& extra_new_owners = m_neighbour_extra_cells_new_owner->at(icell.localId());
334 Int32Array& extra_owners = m_neighbour_extra_cells_owner->at(icell.localId());
335 ItemDestRankArray* item_dest_ranks = nullptr;
336 if (icell->isOwn())
337 item_dest_ranks = m_item_dest_ranks_map[m_cell_family];
338 else
339 item_dest_ranks = m_ghost_item_dest_ranks_map[icell->owner()][m_cell_family];
340 item_dest_ranks->at(icell.localId()).addRange(extra_new_owners);
341 item_dest_ranks->at(icell.localId()).addRange(extra_owners);
342 }
343 // This exchange modify dest ranks of cells => need to update their dependencies (costly ??)
344 _propagatesToChildDependencies(m_cell_family);
345}
346
347/*---------------------------------------------------------------------------*/
348/*---------------------------------------------------------------------------*/
349
350void MeshExchange::
351_computeMeshConnectivityInfos(Int32ConstArrayView cells_new_owner)
352{
353 Integer cell_variable_size = m_cell_family->maxLocalId();
354
355 m_neighbour_cells_owner = new IncrementalUnorderedMultiArray<Int32>(cell_variable_size);
356 m_neighbour_cells_new_owner = new IncrementalUnorderedMultiArray<Int32>(cell_variable_size);
357
358 Int32UniqueArray tmp_new_owner(m_nb_rank);
359 tmp_new_owner.fill(NULL_ITEM_ID);
360 Int32UniqueArray tmp_owner(m_nb_rank);
361 tmp_owner.fill(NULL_ITEM_ID);
362
363 ENUMERATE_CELL (icell, m_cell_family->allItems().own()) {
364 Cell cell = *icell;
365 Integer cell_local_id = cell.localId();
366 // We do not add to our connected cell list
367 tmp_owner[m_rank] = cell_local_id;
368
369 m_neighbour_cells_owner->beginIncrement(cell_local_id);
370 m_neighbour_cells_new_owner->beginIncrement(cell_local_id);
371
372 for (NodeEnumerator inode(cell.nodes()); inode.hasNext(); ++inode) {
373 for (CellEnumerator icell2((*inode).cells()); icell2.hasNext(); ++icell2) {
374 Integer cell2_local_id = icell2.localId();
375 Integer cell2_new_owner = cells_new_owner[cell2_local_id];
376 Integer cell2_owner = icell2->owner();
377 // Checks if it is not in the list and if it is not there,
378 // adds it.
379 if (tmp_new_owner[cell2_new_owner] != cell_local_id) {
380 tmp_new_owner[cell2_new_owner] = cell_local_id;
381 m_neighbour_cells_new_owner->addData(cell2_new_owner);
382 }
383 if (tmp_owner[cell2_owner] != cell_local_id) {
384 tmp_owner[cell2_owner] = cell_local_id;
385 m_neighbour_cells_owner->addData(cell2_owner);
386 }
387 }
388 }
389 m_neighbour_cells_owner->endIncrement();
390 m_neighbour_cells_new_owner->endIncrement();
391 }
392}
393
394/*---------------------------------------------------------------------------*/
395/*---------------------------------------------------------------------------*/
396
397void MeshExchange::
398_exchangeCellDataInfos([[maybe_unused]] Int32ConstArrayView cells_new_owner, bool use_active_cells)
399{
400 auto sd_exchange{ ParallelMngUtils::createExchangerRef(m_parallel_mng) };
401
402 Int32UniqueArray recv_sub_domains;
403 m_cell_family->getCommunicatingSubDomains(recv_sub_domains);
404 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i)
405 sd_exchange->addSender(recv_sub_domains[i]);
406
407 sd_exchange->initializeCommunicationsMessages(recv_sub_domains);
408
409 UniqueArray<Int64> cells_to_comm_uid;
410 UniqueArray<Int32> cells_to_comm_owner;
411 UniqueArray<Int32> cells_to_comm_owner_size;
412 UniqueArray<Int32> cells_to_comm_new_owner;
413 UniqueArray<Int32> cells_to_comm_new_owner_size;
414
415 ItemGroup own_items = m_cell_family->allItems().own();
416 ItemGroup all_items = m_cell_family->allItems();
417 // With AMR, we use the active cells and not all the cells.
418 if (use_active_cells) {
419 own_items = m_cell_family->allItems().ownActiveCellGroup();
420 all_items = m_cell_family->allItems().activeCellGroup();
421 }
422
423 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
424 ISerializeMessage* comm = sd_exchange->messageToSend(i);
425 Int32 dest_sub_domain = comm->destination().value();
426 ISerializer* sbuf = comm->serializer();
427
428 cells_to_comm_uid.clear();
429 cells_to_comm_owner.clear();
430 cells_to_comm_owner_size.clear();
431 cells_to_comm_new_owner.clear();
432 cells_to_comm_new_owner_size.clear();
433
434 ENUMERATE_CELL (icell, own_items) {
435 Cell cell = *icell;
436 Integer cell_local_id = cell.localId();
437 Int32ConstArrayView owners = m_neighbour_cells_owner->at(cell_local_id);
438 bool need_send = owners.contains(dest_sub_domain);
439 Int32ConstArrayView extra_owners = m_neighbour_extra_cells_owner->at(cell_local_id);
440 if (!need_send) {
441 need_send = extra_owners.contains(dest_sub_domain);
442 }
443 if (!need_send)
444 continue;
445
446 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
447 const Integer nb_new_owner = new_owners.size();
448 const Integer nb_owner = owners.size();
449
450 Int32ConstArrayView extra_new_owner = m_neighbour_extra_cells_new_owner->at(cell_local_id);
451 const Integer nb_extra_new_owner = extra_new_owner.size();
452
453 cells_to_comm_uid.add(cell.uniqueId().asInt64());
454 cells_to_comm_owner_size.add(nb_owner);
455 cells_to_comm_new_owner_size.add(nb_new_owner + nb_extra_new_owner);
456 for (Integer zz = 0; zz < nb_owner; ++zz)
457 cells_to_comm_owner.add(owners[zz]);
458 for (Integer zz = 0; zz < nb_new_owner; ++zz)
459 cells_to_comm_new_owner.add(new_owners[zz]);
460 for (Integer zz = 0; zz < nb_extra_new_owner; ++zz)
461 cells_to_comm_new_owner.add(extra_new_owner[zz]);
462 }
463 sbuf->setMode(ISerializer::ModeReserve);
464
465 sbuf->reserveInt64(1); // For the number of cells
466 sbuf->reserveArray(cells_to_comm_uid);
467 sbuf->reserveArray(cells_to_comm_owner_size);
468 sbuf->reserveArray(cells_to_comm_owner);
469 sbuf->reserveArray(cells_to_comm_new_owner_size);
470 sbuf->reserveArray(cells_to_comm_new_owner);
471
472 sbuf->allocateBuffer();
473 sbuf->setMode(ISerializer::ModePut);
474
475 sbuf->putInt64(cells_to_comm_uid.size());
476 sbuf->putArray(cells_to_comm_uid);
477 sbuf->putArray(cells_to_comm_owner_size);
478 sbuf->putArray(cells_to_comm_owner);
479 sbuf->putArray(cells_to_comm_new_owner_size);
480 sbuf->putArray(cells_to_comm_new_owner);
481 }
482
483 sd_exchange->processExchange();
484
485 Int32UniqueArray cells_to_comm_local_id;
486 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
487 ISerializeMessage* comm = sd_exchange->messageToReceive(i);
488 ISerializer* sbuf = comm->serializer();
489 Integer owner_index = 0;
490 Integer new_owner_index = 0;
491 Int64 nb_cell = sbuf->getInt64();
492 sbuf->getArray(cells_to_comm_uid);
493 sbuf->getArray(cells_to_comm_owner_size);
494 sbuf->getArray(cells_to_comm_owner);
495 sbuf->getArray(cells_to_comm_new_owner_size);
496 sbuf->getArray(cells_to_comm_new_owner);
497 cells_to_comm_local_id.resize(nb_cell);
498 m_cell_family->itemsUniqueIdToLocalId(cells_to_comm_local_id, cells_to_comm_uid);
499 for (Integer icell = 0; icell < nb_cell; ++icell) {
500 Integer cell_local_id = cells_to_comm_local_id[icell];
501 Integer cell_nb_owner = cells_to_comm_owner_size[icell];
502 Integer cell_nb_new_owner = cells_to_comm_new_owner_size[icell];
503#ifdef DEBUG
504 info() << " cell " << icell
505 << " lid=" << cell_local_id
506 << " uid=" << cells_to_comm_uid[icell]
507 << " ind=" << m_neighbour_cells_owner->index(cell_local_id);
508#endif
509 if (m_neighbour_cells_owner->index(cell_local_id) != (-1))
510 fatal() << "Cell uid=" << cells_to_comm_uid[icell] << " already has neighbours 'owner'!";
511 if (m_neighbour_cells_new_owner->index(cell_local_id) != (-1))
512 fatal() << "Cell uid=" << cells_to_comm_uid[icell] << " already has neighbours 'new_owner'!";
513 m_neighbour_cells_owner->beginIncrement(cell_local_id);
514 m_neighbour_cells_new_owner->beginIncrement(cell_local_id);
515#ifdef DEBUG
516 info() << " cell " << icell
517 << " lid=" << cell_local_id
518 << " uid=" << cells_to_comm_uid[icell]
519 << " ind=" << m_neighbour_cells_owner->index(cell_local_id);
520#endif
521 for (Integer zz = 0; zz < cell_nb_owner; ++zz)
522 m_neighbour_cells_owner->addData(cells_to_comm_owner[owner_index + zz]);
523 owner_index += cell_nb_owner;
524 m_neighbour_cells_owner->endIncrement();
525
526 for (Integer zz = 0; zz < cell_nb_new_owner; ++zz)
527 m_neighbour_cells_new_owner->addData(cells_to_comm_new_owner[new_owner_index + zz]);
528 new_owner_index += cell_nb_new_owner;
529 m_neighbour_cells_new_owner->endIncrement();
530 }
531 }
532}
533
534/*---------------------------------------------------------------------------*/
535/*---------------------------------------------------------------------------*/
536
537void MeshExchange::
538_addItemToSend(ArrayView<std::set<Int32>> items_to_send,
539 Int32 local_id, Int32 cell_local_id,
540 bool use_itemfamily_network)
541{
542 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
543 for (Integer zz = 0, nb_new_owner = new_owners.size(); zz < nb_new_owner; ++zz)
544 items_to_send[new_owners[zz]].insert(local_id);
545
546 Int32ConstArrayView extra_new_owners = m_neighbour_extra_cells_new_owner->at(cell_local_id);
547 for (Integer zz = 0, nb_extra_new_owner = extra_new_owners.size(); zz < nb_extra_new_owner; ++zz)
548 items_to_send[extra_new_owners[zz]].insert(local_id);
549
550 if (use_itemfamily_network) {
551 Int32ConstArrayView network_new_owners = m_item_dest_ranks_map[m_cell_family]->at(cell_local_id);
552 for (Integer zz = 0, nb_network_new_owner = network_new_owners.size(); zz < nb_network_new_owner; ++zz) {
553 items_to_send[network_new_owners[zz]].insert(local_id);
554 }
555 }
556}
557
558/*---------------------------------------------------------------------------*/
559/*---------------------------------------------------------------------------*/
560
561void MeshExchange::
562_computeItemsToSend(bool send_dof)
563{
564 for (const auto& iter : m_items_to_send)
565 iter.second->resize(m_nb_rank);
566
567 IItemFamily* node_family = mesh()->nodeFamily();
568 IItemFamily* edge_family = mesh()->edgeFamily();
569 IItemFamily* face_family = mesh()->faceFamily();
570 IItemFamily* cell_family = m_cell_family;
571
572 ArrayView<std::set<Int32>> nodes_to_send = _getItemsToSend(node_family);
573 ArrayView<std::set<Int32>> edges_to_send = _getItemsToSend(edge_family);
574 ArrayView<std::set<Int32>> faces_to_send = _getItemsToSend(face_family);
575 ArrayView<std::set<Int32>> cells_to_send = _getItemsToSend(cell_family);
576
577 Int32ConstArrayView cells_new_owner(cell_family->itemsNewOwner().asArray());
578 Int32ConstArrayView faces_new_owner(face_family->itemsNewOwner().asArray());
579 bool use_itemfamily_network = m_mesh->itemFamilyNetwork() && m_mesh->itemFamilyNetwork()->isActivated();
580 ENUMERATE_CELL (icell, cell_family->allItems().own()) {
581 _addItemToSend(cells_to_send, icell.itemLocalId(), icell.itemLocalId(), use_itemfamily_network);
582 }
583
584 ENUMERATE_NODE (inode, node_family->allItems().own()) {
585 Node node = *inode;
586 Integer node_local_id = node.localId();
587 for (CellEnumerator icell(node.cells()); icell.hasNext(); ++icell)
588 _addItemToSend(nodes_to_send, node_local_id, icell.localId(), use_itemfamily_network);
589 }
590
591 ENUMERATE_EDGE (iedge, edge_family->allItems().own()) {
592 Edge edge = *iedge;
593 Integer edge_local_id = edge.localId();
594 for (CellEnumerator icell(edge.cells()); icell.hasNext(); ++icell)
595 _addItemToSend(edges_to_send, edge_local_id, icell.localId(), use_itemfamily_network);
596 }
597
598 ENUMERATE_FACE (iface, face_family->allItems().own()) {
599 Face face = *iface;
600 Integer face_local_id = face.localId();
601 for (CellEnumerator icell(face.cells()); icell.hasNext(); ++icell) {
602 _addItemToSend(faces_to_send, face_local_id, icell.localId(), use_itemfamily_network);
603 }
604 }
605
606 {
607 for (IItemFamily* family : m_mesh->itemFamilies()) {
608 IParticleFamily* particle_family = family->toParticleFamily();
609 if (particle_family && particle_family->getEnableGhostItems() == true) {
610 ArrayView<std::set<Int32>> to_send = _getItemsToSend(family);
611 ENUMERATE_PARTICLE (iparticle, particle_family->allItems().own()) {
612 Cell cell = iparticle->cell();
613 // Do not send the particle if it has no cell.
614 if (!cell.null())
615 _addItemToSend(to_send, iparticle->localId(), cell.localId(), use_itemfamily_network);
616 }
617 }
618 if (send_dof && family->itemKind() == IK_DoF) {
619 _setItemsToSend(family);
620 }
621 }
622 }
623
624 // Ensures that we do not send the entities
625 for (const auto& iter : m_items_to_send)
626 (*(iter.second))[m_rank].clear();
627
628 const bool is_print = false;
629 if (is_print) {
630 debug() << "PRINT ITEM TO SEND V1";
631 _printItemToSend(node_family);
632 _printItemToSend(edge_family);
633 _printItemToSend(face_family);
634 _printItemToSend(cell_family);
635 }
636}
637
638/*---------------------------------------------------------------------------*/
639/*---------------------------------------------------------------------------*/
640/*
641 * This version is more general than the first because it takes into account
642 * the AMR case. However, the current version is less performant than the first.
643 * For this reason, the initial version will remain the default version in the non-AMR case.
644 * NOTE: the initial version can be used in the AMR case, as the exchanges
645 * happen regarding the connectivity around the nodes. So the exchange happens
646 * on the tree of an active cell. This idea has not been TODO tested to confirm it.
647 */
648/*---------------------------------------------------------------------------*/
649/*---------------------------------------------------------------------------*/
650
653{
654 Integer cell_variable_size = m_cell_family->maxLocalId();
655
656 m_neighbour_cells_owner = new IncrementalUnorderedMultiArray<Int32>(cell_variable_size);
657 m_neighbour_cells_new_owner = new IncrementalUnorderedMultiArray<Int32>(cell_variable_size);
658
659 Int32UniqueArray tmp_new_owner(m_nb_rank);
660 tmp_new_owner.fill(NULL_ITEM_ID);
661 Int32UniqueArray tmp_owner(m_nb_rank);
662 tmp_owner.fill(NULL_ITEM_ID);
663
664 ENUMERATE_CELL (icell, m_cell_family->allItems().ownActiveCellGroup()) {
665 const Cell& cell = *icell;
666 Integer cell_local_id = cell.localId();
667 // We do not add ourselves to our list of connected cells.
668 tmp_owner[m_rank] = cell_local_id;
669
670 m_neighbour_cells_owner->beginIncrement(cell_local_id);
671 m_neighbour_cells_new_owner->beginIncrement(cell_local_id);
672
673 for (NodeEnumerator inode(cell.nodes()); inode.hasNext(); ++inode) {
674 Int32UniqueArray local_ids;
675 for (CellEnumerator icell2((*inode)._internalActiveCells(local_ids)); icell2.hasNext(); ++icell2) {
676 Integer cell2_local_id = icell2.localId();
677 Integer cell2_new_owner = cells_new_owner[cell2_local_id];
678 Integer cell2_owner = icell2->owner();
679 // Checks if it is not in the list and, if not, adds it.
680 if (tmp_new_owner[cell2_new_owner] != cell_local_id) {
681 tmp_new_owner[cell2_new_owner] = cell_local_id;
682 m_neighbour_cells_new_owner->addData(cell2_new_owner);
683 }
684 if (tmp_owner[cell2_owner] != cell_local_id) {
685 tmp_owner[cell2_owner] = cell_local_id;
686 m_neighbour_cells_owner->addData(cell2_owner);
687 }
688 }
689 local_ids.clear();
690 }
691 m_neighbour_cells_owner->endIncrement();
692 m_neighbour_cells_new_owner->endIncrement();
693 }
694}
695
696/*---------------------------------------------------------------------------*/
697/*---------------------------------------------------------------------------*/
698
699void MeshExchange::
700_addTreeCellToSend(ArrayView<std::set<Int32>> items_to_send,
701 Int32 local_id, Int32 cell_local_id,
702 CellInfoListView cells)
703{
704 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
705
706 Cell cell(cells[local_id]);
707 if (cell.level() == 0) {
708 for (Integer zz = 0, nb_new_owner = new_owners.size(); zz < nb_new_owner; ++zz)
709 items_to_send[new_owners[zz]].insert(local_id);
710 // Graph is okay on the active level
711 Int32ConstArrayView extra_new_owners = m_neighbour_extra_cells_new_owner->at(cell_local_id);
712 for (Integer zz = 0, nb_extra_new_owner = extra_new_owners.size(); zz < nb_extra_new_owner; ++zz)
713 items_to_send[extra_new_owners[zz]].insert(local_id);
714 }
715 else {
716 Int32UniqueArray family;
717 Cell top_parent = cell.topHParent();
718 _familyTree(family, top_parent);
719 for (Integer c = 0, cs = family.size(); c < cs; c++) {
720 for (Integer zz = 0, nb_new_owner = new_owners.size(); zz < nb_new_owner; ++zz)
721 items_to_send[new_owners[zz]].insert(family[c]);
722 }
723 }
724}
725
726/*---------------------------------------------------------------------------*/
727/*---------------------------------------------------------------------------*/
728
729void MeshExchange::
730_addTreeItemToSend(Int32 cell_local_id, CellInfoListView cells)
731{
732 Int32UniqueArray tree_cells_lid;
733
734 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
735
736 Cell cell(cells[cell_local_id]);
737
738 Int32UniqueArray family;
739
740 Cell top_parent = cell.topHParent();
741 _familyTree(family, top_parent);
742
743 IItemFamily* node_family = mesh()->nodeFamily();
744 IItemFamily* edge_family = mesh()->edgeFamily();
745 IItemFamily* face_family = mesh()->faceFamily();
746
747 ArrayView<std::set<Int32>> nodes_to_send = _getItemsToSend(node_family);
748 ArrayView<std::set<Int32>> edges_to_send = _getItemsToSend(edge_family);
749 ArrayView<std::set<Int32>> faces_to_send = _getItemsToSend(face_family);
750
751 // We assume that the containers nodes_to_send, edges_to_send and face_to_send
752 // are already allocated
753 for (Integer c = 0, cs = family.size(); c < cs; c++) // c=0 is the topParent cell.
754 for (Integer zz = 0, nb_new_owner = new_owners.size(); zz < nb_new_owner; ++zz) {
755 Cell cell2 = cells[family[c]];
756 for (Node node : cell2.nodes())
757 nodes_to_send[new_owners[zz]].insert(node.localId());
758 for (Edge edge : cell2.edges())
759 edges_to_send[new_owners[zz]].insert(edge.localId());
760 for (Face face : cell2.faces())
761 faces_to_send[new_owners[zz]].insert(face.localId());
762 }
763}
764
765/*---------------------------------------------------------------------------*/
766/*---------------------------------------------------------------------------*/
767
768void MeshExchange::
769_familyTree(Int32Array& family, Cell item, const bool reset) const
770{
771 ARCANE_ASSERT((!item.itemBase().isSubactive()), ("The family tree doesn't include subactive items"));
772 // Clear the array if the flag reset tells us to.
773 if (reset)
774 family.clear();
775 // Add this item to the family tree.
776 family.add(item.localId());
777 // Recurse into the items children, if it has them.
778 // Do not clear the array any more.
779 if (!item.isActive())
780 for (Integer c = 0, cs = item.nbHChildren(); c < cs; c++) {
781 Item ichild = item.hChild(c);
782 if (ichild.isOwn())
783 _familyTree(family, ichild.toCell(), false);
784 }
785}
786
787/*---------------------------------------------------------------------------*/
788/*---------------------------------------------------------------------------*/
789
790void MeshExchange::
791_computeItemsToSend2()
792{
793 for (const auto& iter : m_items_to_send)
794 iter.second->resize(m_nb_rank);
795
796 IItemFamily* node_family = mesh()->nodeFamily();
797 IItemFamily* edge_family = mesh()->edgeFamily();
798 IItemFamily* face_family = mesh()->faceFamily();
799
800 ArrayView<std::set<Int32>> nodes_to_send = _getItemsToSend(node_family);
801 ArrayView<std::set<Int32>> edges_to_send = _getItemsToSend(edge_family);
802 ArrayView<std::set<Int32>> faces_to_send = _getItemsToSend(face_family);
803 ArrayView<std::set<Int32>> cells_to_send = _getItemsToSend(m_cell_family);
804
805 Int32ConstArrayView cells_new_owner(m_cell_family->itemsNewOwner().asArray());
806 Int32ConstArrayView faces_new_owner(face_family->itemsNewOwner().asArray());
807
808 CellInfoListView cells(m_cell_family);
809 ENUMERATE_CELL (icell, m_cell_family->allItems().ownActiveCellGroup()) {
810 Cell cell = *icell;
811 _addTreeCellToSend(cells_to_send, icell.itemLocalId(), icell.itemLocalId(), cells);
812
813 if (cell.level() == 0) {
814
815 for (NodeEnumerator inode(cell.nodes()); inode.hasNext(); ++inode) {
816 Node node = *inode;
817 if (node.isOwn()) {
818 Integer node_local_id = node.localId();
819 for (CellEnumerator icell2(node.cells()); icell2.hasNext(); ++icell2) {
820 Cell cc = *icell2;
821 if (cc.isActive())
822 _addItemToSend(nodes_to_send, node_local_id, icell2.localId());
823 }
824 }
825 }
826
827 for (EdgeEnumerator iedge(cell.edges()); iedge.hasNext(); ++iedge) {
828 Edge edge = *iedge;
829 if (edge.isOwn()) {
830 Integer edge_local_id = edge.localId();
831 for (CellEnumerator icell2(edge.cells()); icell2.hasNext(); ++icell2)
832 _addItemToSend(edges_to_send, edge_local_id, icell2.localId());
833 }
834 }
835
836 for (FaceEnumerator iface(cell.faces()); iface.hasNext(); ++iface) {
837 Face face = *iface;
838 if (face.isOwn()) {
839 Integer face_local_id = face.localId();
840 for (CellEnumerator icell2(face.cells()); icell2.hasNext(); ++icell2) {
841 _addItemToSend(faces_to_send, face_local_id, icell2.localId());
842 }
843 }
844 }
845 }
846 else if (cell.level() > 0)
847 _addTreeItemToSend(icell.itemLocalId(), cells);
848 }
849
850 for (IItemFamily* family : m_mesh->itemFamilies()) {
851 IParticleFamily* particle_family = family->toParticleFamily();
852 if (particle_family && particle_family->getEnableGhostItems() == true) {
853 ArrayView<std::set<Int32>> to_send = _getItemsToSend(family);
854 ENUMERATE_PARTICLE (iparticle, particle_family->allItems().own()) {
855 _addItemToSend(to_send, iparticle->localId(), iparticle->cell().localId());
856 }
857 }
858 }
859
860 // Ensures that entities are not sent
861 for (const auto& iter : m_items_to_send)
862 (*(iter.second))[m_rank].clear();
863}
864
865/*---------------------------------------------------------------------------*/
866/*---------------------------------------------------------------------------*/
867
869
870/*---------------------------------------------------------------------------*/
871/*---------------------------------------------------------------------------*/
872/*
873 * This version provides an implementation for calculating items to exchange
874 * using the item family dependency graph (ItemFamilyNetwork)
875 * NOTE: For now, the algorithms for the IGraph arcane graph and for particle
876 * families remain unchanged.
877 */
878/*---------------------------------------------------------------------------*/
879/*---------------------------------------------------------------------------*/
880
882
885{
886 if (!m_mesh->itemFamilyNetwork())
887 info() << "Should have an IItemFamilyNetwork. Exiting.";
888 //1-Prepare data structure
889 m_ghost_item_dest_ranks_map.resize(m_parallel_mng->commSize());
890 m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family) {
891 _allocData(family);
892 },
893 IItemFamilyNetwork::TopologicalOrder);
894
895 // Here the algorithm propagates the owner to the neighborhood
896 // The propagation to the items owned (dependencies) has already been done in updateOwnersFromCell
897 // Todo include also the owned item propagation (would avoid to call updateOwnersFromCell...)
898 // What we do here is to build the number of ghost layers needed
899 //-For each ghost layer wanted:
900 // 1- For all items add Item new owner and all its dest ranks to all child item connected (dependency or relation) dest ranks
901 // This is done for all family, parsing the family graph from head to leaves
902 // 2- For all items add new dest ranks to its depending child (move with your downward dependencies)
903 if (!m_mesh->ghostLayerMng())
904 info() << "Should have a IGhostLayerMng. Exiting";
905 for (int ghost_layer_index = 0; ghost_layer_index < m_mesh->ghostLayerMng()->nbGhostLayer(); ++ghost_layer_index) {
906 //2-Diffuse destination rank info to connected items
907 m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family) {
908 _propagatesToChildConnectivities(family);
909 },
910 IItemFamilyNetwork::TopologicalOrder);
911
912 //m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family){
913 // _propagatesToChildDependencies(family);
914 //},
915 //IItemFamilyNetwork::TopologicalOrder);
916 }
917}
918
919/*---------------------------------------------------------------------------*/
920/*---------------------------------------------------------------------------*/
921
922void MeshExchange::
923_propagatesToChildConnectivities(IItemFamily* family)
924{
925 VariableItemInt32& item_new_owner = family->itemsNewOwner();
926 /* TODO : this propagation should be needed for all child dependencies and not all relations but only ghost providing relations
927 * eg for node to cell connectivity if ghosts are found via node neighbouring. This notion of ghost providing relations must be added
928 * In traditional case only node to cell is a ghost providing relation => a test can be made to add only this relation (along with all dependencies) :
929 * auto child_connectivities = m_mesh->itemFamilyNetwork()->getChildDependencies(family); // instead of getChildConnectivities
930 * if (family->itemKind()==IK_Node) {
931 * child_connectivities.add(m_mesh->itemFamilyNetwork()->getConnectivity(family,m_mesh->cellFamily(),mesh::connectivityName(family,m_mesh->cellFamily())));
932 * }
933 */
934 //auto child_connectivities = m_mesh->itemFamilyNetwork()->getChildConnectivities(family);
935 auto child_connectivities = m_mesh->itemFamilyNetwork()->getChildDependencies(family); // Only dependencies are required to propagate owner
936 for (const auto& child_connectivity : child_connectivities) {
937 if (child_connectivity) {
938 VariableItemInt32& conn_item_new_owner = child_connectivity->targetFamily()->itemsNewOwner();
939 auto accessor = IndexedItemConnectivityAccessor(child_connectivity);
940 ENUMERATE_ITEM (item, family->allItems()) {
941 // Parse child relations
942 _addDestRank(*item, family, item_new_owner[item]);
943 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
944 _addDestRank(*item, family, conn_item_new_owner[connected_item]);
945 }
946
947 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
948 _addDestRank(*connected_item, child_connectivity->targetFamily(), *item, family);
949 }
950 }
951 }
952 }
953 if (!m_mesh->useMeshItemFamilyDependencies()) {
954 switch (family->itemKind()) {
955 case IK_Face:
956 ENUMERATE_ (Face, item, family->allItems()) {
957 for (Cell cell : item->cells())
958 _addDestRank(cell, m_cell_family, *item, family);
959 }
960 break;
961 case IK_Edge:
962 ENUMERATE_ (Edge, item, family->allItems()) {
963 for (Cell cell : item->cells())
964 _addDestRank(cell, m_cell_family, *item, family);
965 }
966 break;
967 case IK_Node:
968 ENUMERATE_ (Node, item, family->allItems()) {
969 for (Cell cell : item->cells())
970 _addDestRank(cell, m_cell_family, *item, family);
971 }
972 break;
973 default:
974 break;
975 }
976 }
977}
978
979/*---------------------------------------------------------------------------*/
980/*---------------------------------------------------------------------------*/
981
982void MeshExchange::
983_propagatesToChildDependencies(IItemFamily* family)
984{
985 // Here we only propagates dest_ranks, since owner propagation to children has already been done in updateOwnersFromCell
986 // todo 1 use these new algo to propagates the owner
987 // todo 2 when using the graph we do not need to access to all child connectivities, only the one of the immediately inferior level.
988 // => we should allow graph task to take the signature task(IItemFamily*,FirstRankChildren) where FirstRankChildren (better name ??)
989 // would contain the immediate children (FirstRankChildren) would be an EdgeSet or smthg near
990 // => thus we would need to add to the DAG a method children(const Edge&) (see for the name firstRankChildren ??)
991 auto child_dependencies = m_mesh->itemFamilyNetwork()->getChildDependencies(family);
992 for (const auto& child_dependency : child_dependencies) {
993 if (child_dependency) {
994 auto accessor = IndexedItemConnectivityAccessor(child_dependency);
995 ENUMERATE_ITEM (item, family->allItems()) {
996 // Parse child dependencies
997 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
998 _addDestRank(*connected_item, child_dependency->targetFamily(), *item, family); // as simple as that ??
999 }
1000 }
1001 }
1002 }
1003}
1004
1005/*---------------------------------------------------------------------------*/
1006/*---------------------------------------------------------------------------*/
1007
1008void MeshExchange::
1009_addDestRank(const Item& item, IItemFamily* item_family, const Integer new_owner) // take an ItemInternal* ?
1010{
1011 ItemDestRankArray* item_dest_ranks = nullptr;
1012 if (item.owner() == m_rank) {
1013 item_dest_ranks = m_item_dest_ranks_map[item_family]; // this search could be written outside the enumerate (but the enumerate is cheap : on connected items)
1014 }
1015 else {
1016 item_dest_ranks = m_ghost_item_dest_ranks_map[item.owner()][item_family];
1017 }
1018 // Insert element only if not present
1019 auto& item_ranks_internal = item_dest_ranks->at(item.localId());
1020 if (!item_ranks_internal.contains(new_owner))
1021 item_dest_ranks->at(item.localId()).add(new_owner);
1022}
1023
1024/*---------------------------------------------------------------------------*/
1025/*---------------------------------------------------------------------------*/
1026
1027void MeshExchange::
1028_addDestRank(const Item& item, IItemFamily* item_family, const Item& followed_item, IItemFamily* followed_item_family)
1029{
1030 // todo : a getDestRank method
1031 ItemDestRankArray* item_dest_ranks = nullptr;
1032 if (item.owner() == m_rank) {
1033 item_dest_ranks = m_item_dest_ranks_map[item_family]; // this search could be written outside the enumerate (but the enumerate is cheap : on connected items)
1034 }
1035 else {
1036 item_dest_ranks = m_ghost_item_dest_ranks_map[item.owner()][item_family];
1037 }
1038 ItemDestRankArray* followed_item_dest_ranks = nullptr;
1039 if (followed_item.owner() == m_rank)
1040 followed_item_dest_ranks = m_item_dest_ranks_map[followed_item_family]; // this search could be written outside the enumerate (but the enumerate is cheap : on connected items)
1041 else
1042 followed_item_dest_ranks = m_ghost_item_dest_ranks_map[followed_item.owner()][followed_item_family];
1043 // Add only new dest rank only if not already present
1044 auto& new_dest_ranks = followed_item_dest_ranks->at(followed_item.localId());
1045 auto& current_dest_ranks = item_dest_ranks->at(item.localId());
1046 IntegerUniqueArray new_dest_rank_to_add;
1047 new_dest_rank_to_add.reserve((new_dest_ranks.size()));
1048 for (auto& new_dest_rank : new_dest_ranks) {
1049 if (!current_dest_ranks.contains(new_dest_rank))
1050 new_dest_rank_to_add.add(new_dest_rank);
1051 }
1052 current_dest_ranks.addRange(new_dest_rank_to_add);
1053}
1054
1055/*---------------------------------------------------------------------------*/
1056/*---------------------------------------------------------------------------*/
1057
1058void MeshExchange::
1059_allocData(IItemFamily* family)
1060{
1061 m_item_dest_ranks_map[family] = new ItemDestRankArray(family->maxLocalId());
1062 for (auto& ghost_item_map : m_ghost_item_dest_ranks_map) {
1063 ghost_item_map[family] = new ItemDestRankArray(family->maxLocalId());
1064 }
1065}
1066/*---------------------------------------------------------------------------*/
1067/*---------------------------------------------------------------------------*/
1068
1069void MeshExchange::
1070_debugPrint()
1071{
1072 info() << "-ENTERING NEW EXCHANGE DEBUG PRINT";
1073 for (auto& item_dest_ranks : m_item_dest_ranks_map) {
1074 info() << "--PRINT NEW EXCHANGE INFO";
1075 info() << "---Destination rank for family " << item_dest_ranks.first->name();
1076 for (int item_lid = 0; item_lid < item_dest_ranks.first->maxLocalId(); ++item_lid) {
1077 info() << "---Destination rank for item lid " << item_lid;
1078 for (auto& item_dest_rank : item_dest_ranks.second->at(item_lid)) {
1079 info() << "---- Rank " << item_dest_rank;
1080 }
1081 }
1082 }
1083}
1084
1085/*---------------------------------------------------------------------------*/
1086/*---------------------------------------------------------------------------*/
1087
1088void MeshExchange::
1089_exchangeCellDataInfos3()
1090{
1091 // Graph connectivity taken into account thanks to the call to _addGraphConnectivityToNewConnectivityInfo
1092 auto sd_exchange{ ParallelMngUtils::createExchangerRef(m_parallel_mng) };
1093
1094 Int32UniqueArray recv_sub_domains;
1095 m_cell_family->getCommunicatingSubDomains(recv_sub_domains);
1096 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i)
1097 sd_exchange->addSender(recv_sub_domains[i]);
1098
1099 sd_exchange->initializeCommunicationsMessages(recv_sub_domains);
1100
1101 UniqueArray<IItemFamily*> item_families;
1102 Int32UniqueArray item_lids;
1103 Int32UniqueArray item_dest_ranks;
1104 Int32UniqueArray item_nb_dest_ranks;
1105 Int32UniqueArray family_nb_items;
1106 Int64UniqueArray item_uids;
1107
1108 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
1109 ISerializeMessage* comm = sd_exchange->messageToSend(i);
1110 Int32 dest_sub_domain = comm->destination().value();
1111 ISerializer* sbuf = comm->serializer();
1112 item_families.clear();
1113 item_dest_ranks.clear();
1114 item_nb_dest_ranks.clear();
1115 family_nb_items.clear();
1116 item_uids.clear();
1117 for (const auto& family_ghost_item_dest_ranks : m_ghost_item_dest_ranks_map[dest_sub_domain]) {
1118 Integer family_nb_item = 0;
1119 item_lids.clear();
1120 item_families.add(family_ghost_item_dest_ranks.first);
1121 for (Integer item_lid = 0; item_lid < family_ghost_item_dest_ranks.second->size(); ++item_lid) {
1122 if (family_ghost_item_dest_ranks.second->at(item_lid).size() == 0)
1123 continue;
1124 item_lids.add(item_lid);
1125 item_dest_ranks.addRange(family_ghost_item_dest_ranks.second->at(item_lid));
1126 item_nb_dest_ranks.add(family_ghost_item_dest_ranks.second->at(item_lid).size());
1127 family_nb_item++;
1128 }
1129 family_nb_items.add(family_nb_item);
1130 ENUMERATE_ITEM (item, family_ghost_item_dest_ranks.first->view(item_lids)) {
1131 item_uids.add(item->uniqueId().asInt64());
1132 }
1133 }
1134 sbuf->setMode(ISerializer::ModeReserve);
1135 sbuf->reserveInt64(1); // nb_item_family
1136 for (const auto& family : item_families)
1137 sbuf->reserve(family->name()); // ItemFamily->name
1138 sbuf->reserveInteger(item_families.size()); // ItemFamily->itemKind
1139 sbuf->reserveArray(item_uids);
1140 sbuf->reserveArray(family_nb_items);
1141 sbuf->reserveArray(item_nb_dest_ranks);
1142 sbuf->reserveArray(item_dest_ranks);
1143
1144 sbuf->allocateBuffer();
1145 sbuf->setMode(ISerializer::ModePut);
1146
1147 sbuf->putInt64(item_families.size());
1148 for (const auto& family : item_families)
1149 sbuf->put(family->name()); // ItemFamily->name
1150 for (const auto& family : item_families)
1151 sbuf->putInteger(family->itemKind()); // ItemFamily->itemKind
1152 sbuf->putArray(item_uids);
1153 sbuf->putArray(family_nb_items);
1154 sbuf->putArray(item_nb_dest_ranks);
1155 sbuf->putArray(item_dest_ranks);
1156 }
1157
1158 sd_exchange->processExchange();
1159
1160 for (Integer i = 0, n = recv_sub_domains.size(); i < n; ++i) {
1161 ISerializeMessage* comm = sd_exchange->messageToReceive(i);
1162 ISerializer* sbuf = comm->serializer();
1163 Int64 nb_families = sbuf->getInt64();
1164 StringUniqueArray item_family_names(nb_families);
1165 Int32UniqueArray item_family_kinds(nb_families);
1166 for (auto& family_name : item_family_names)
1167 sbuf->get(family_name); // ItemFamily->name
1168 for (auto& family_kind : item_family_kinds)
1169 family_kind = sbuf->getInteger(); // ItemFamily->itemKind
1170 sbuf->getArray(item_uids);
1171 sbuf->getArray(family_nb_items);
1172 sbuf->getArray(item_nb_dest_ranks);
1173 sbuf->getArray(item_dest_ranks);
1174 Integer item_uid_index = 0;
1175 Integer item_nb_dest_rank_index = 0;
1176 Integer item_dest_rank_index = 0;
1177 for (int family_index = 0; family_index < nb_families; ++family_index) {
1178 IItemFamily* family = m_mesh->findItemFamily(eItemKind(item_family_kinds[family_index]),
1179 item_family_names[family_index], false);
1180 Int64ArrayView family_item_uids = item_uids.subView(item_uid_index, family_nb_items[family_index]);
1181 item_lids.resize(family_item_uids.size());
1182 family->itemsUniqueIdToLocalId(item_lids, family_item_uids, true);
1183 for (const auto& item_lid : item_lids) {
1184 auto sub_view = item_dest_ranks.subView(item_dest_rank_index, item_nb_dest_ranks[item_nb_dest_rank_index]);
1185 m_item_dest_ranks_map[family]->at(item_lid).addRange(sub_view);
1186 item_dest_rank_index += item_nb_dest_ranks[item_nb_dest_rank_index++];
1187 }
1188 item_uid_index += family_nb_items[family_index];
1189 }
1190 }
1191 // Dest rank propagation needed since they have been updated for own items
1192 // copy of propagation part of method computeMeshConnectivityInfo3
1193 for (int ghost_layer_index = 0; ghost_layer_index < m_mesh->ghostLayerMng()->nbGhostLayer(); ++ghost_layer_index) {
1194 //2-Diffuse destination rank info to connected items
1195 m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family) {
1196 _propagatesToChildConnectivities(family);
1197 },
1198 IItemFamilyNetwork::TopologicalOrder);
1199
1200 //m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family){
1201 // _propagatesToChildDependencies(family);
1202 //},
1203 //IItemFamilyNetwork::TopologicalOrder);
1204 }
1205}
1206/*---------------------------------------------------------------------------*/
1207/*---------------------------------------------------------------------------*/
1208
1209void MeshExchange::
1210_computeItemsToSend3()
1211{
1212 for (const auto& iter : m_items_to_send)
1213 iter.second->resize(m_nb_rank);
1214
1215 IItemFamily* node_family = mesh()->nodeFamily();
1216 IItemFamily* edge_family = mesh()->edgeFamily();
1217 IItemFamily* face_family = mesh()->faceFamily();
1218 IItemFamily* cell_family = m_cell_family;
1219
1220 _setItemsToSend(node_family);
1221 _setItemsToSend(edge_family);
1222 _setItemsToSend(face_family);
1223 _setItemsToSend(cell_family);
1224
1225 // Tmp for particles : they should be in the family graph
1226 {
1227 for (IItemFamily* family : m_mesh->itemFamilies()) {
1228 IParticleFamily* particle_family = family->toParticleFamily();
1229 if (particle_family && particle_family->getEnableGhostItems() == true) {
1230 ArrayView<std::set<Int32>> to_send = _getItemsToSend(family);
1231 ENUMERATE_PARTICLE (iparticle, particle_family->allItems().own()) {
1232 for (const auto& dest_rank : m_item_dest_ranks_map[m_cell_family]->at(iparticle->cell().localId())) {
1233 to_send[dest_rank].insert(iparticle->localId());
1234 }
1235 }
1236 }
1237 }
1238 }
1239
1240 // Ensures that the entities are not sent
1241 for (const auto& iter : m_items_to_send)
1242 (*(iter.second))[m_rank].clear();
1243
1244 // SDC DEBUG
1245 // debug() << "PRINT ITEM TO SEND V2";
1246 // _printItemToSend(node_family);
1247 // _printItemToSend(edge_family);
1248 // _printItemToSend(face_family);
1249 // _printItemToSend(cell_family);
1250}
1251
1252/*---------------------------------------------------------------------------*/
1253/*---------------------------------------------------------------------------*/
1254
1255void MeshExchange::
1256_setItemsToSend(IItemFamily* family)
1257{
1258 if (family->nbItem() == 0)
1259 return;
1260 auto iter = m_items_to_send.find(family);
1261 if (iter == m_items_to_send.end())
1262 ARCANE_FATAL("No items to send for family '{0}'", family->name());
1263 ArrayView<std::set<Int32>> items_to_send = iter->second->view();
1264 for (Integer item_lid = 0; item_lid < m_item_dest_ranks_map[family]->size(); ++item_lid) {
1265 for (const auto& dest_rank : m_item_dest_ranks_map[family]->at(item_lid)) {
1266 items_to_send[dest_rank].insert(item_lid);
1267 }
1268 }
1269}
1270
1271/*---------------------------------------------------------------------------*/
1272/*---------------------------------------------------------------------------*/
1273
1276{
1277 auto iter = m_items_to_send.find(family);
1278 if (iter == m_items_to_send.end())
1279 ARCANE_FATAL("No items to send for family '{0}'", family->name());
1280 ArrayView<std::set<Int32>> items_to_send = iter->second->view();
1281 // SDC DEBUG print
1282 Integer rank = 0;
1283 debug() << "= ITEM TO SEND FOR FAMILY " << family->name();
1284 for (const auto& owner_lids : items_to_send) {
1285 debug() << "== RANK " << rank++;
1286 for (auto item_lid : owner_lids) {
1287 debug() << "=== has items " << item_lid;
1288 }
1289 }
1290}
1291
1292/*---------------------------------------------------------------------------*/
1293/*---------------------------------------------------------------------------*/
1294
1295void MeshExchange::
1296_printItemToRemove(IItemFamily* family)
1297{
1298 // SDC DEBUG PRINT
1299 debug() << "= ITEM TO REMOVE FOR FAMILY " << family->name();
1300 ENUMERATE_ITEM (item, family->allItems()) {
1301 if (item->hasFlags(ItemFlags::II_NeedRemove))
1302 debug() << "== TO REMOVE ITEM " << item->uniqueId() << " kind " << item->kind();
1303 }
1304}
1305
1306/*---------------------------------------------------------------------------*/
1307/*---------------------------------------------------------------------------*/
1308void MeshExchange::
1309_markRemovableDoFs()
1310{
1311 for (const auto& item_dest_ranks_iter : m_item_dest_ranks_map) {
1312 // todo use C++17 structured bindings
1313 IItemFamily* family = item_dest_ranks_iter.first;
1314 if (family->itemKind() == IK_DoF) {
1315 auto& item_new_owners = family->itemsNewOwner();
1316 ENUMERATE_ITEM (item, family->allItems()) {
1317 Int32ArrayView item_dest_ranks;
1318 // Get destination rank for item (depending if it's ghost or own)
1319 if (item->isOwn())
1320 item_dest_ranks = item_dest_ranks_iter.second->at(item->localId()).view();
1321 else
1322 item_dest_ranks = m_ghost_item_dest_ranks_map[item->owner()][family]->at(item->localId()).view();
1323 // Check if the item must stay on the subdomain (ie dest_rank or new_owner contain the subdomain)
1324 if (!item_dest_ranks.contains(m_rank) && item_new_owners[item] != m_rank) {
1325 item->mutableItemBase().addFlags(ItemFlags::II_NeedRemove);
1326 }
1327 }
1328 }
1329 // _printItemToRemove(item_dest_ranks_iter.first); // SDC DEBUG
1330 }
1331}
1332
1333void MeshExchange::
1334_markRemovableItems(bool with_cell_family)
1335{
1336 for (const auto& item_dest_ranks_iter : m_item_dest_ranks_map) {
1337 // todo use C++17 structured bindings
1338 IItemFamily* family = item_dest_ranks_iter.first;
1339 if (with_cell_family || family->name() != m_cell_family->name()) {
1340 auto& item_new_owners = family->itemsNewOwner();
1341 ENUMERATE_ITEM (item, family->allItems()) {
1342 Int32ArrayView item_dest_ranks;
1343 // Get destination rank for item (depending if it's ghost or own)
1344 if (item->isOwn())
1345 item_dest_ranks = item_dest_ranks_iter.second->at(item.localId()).view();
1346 else
1347 item_dest_ranks = m_ghost_item_dest_ranks_map[item->owner()][family]->at(item.localId()).view();
1348 // Check if the item must stay on the subdomain (ie dest_rank or new_owner contain the subdomain)
1349 if (!item_dest_ranks.contains(m_rank) && item_new_owners[item] != m_rank) {
1350 item->mutableItemBase().addFlags(ItemFlags::II_NeedRemove);
1351 }
1352 }
1353 }
1354 // _printItemToRemove(item_dest_ranks_iter.first); // SDC DEBUG
1355 }
1356}
1357
1358void MeshExchange::
1359_markRemovableCells(Int32ConstArrayView cells_new_owner, bool use_active_cells)
1360{
1361 // This test is no longer representative with the extraghost concept
1362 // Should we find an alternative ??
1363 // Checks that all cells have had their neighbors calculated
1364 // ENUMERATE_CELL(icell,m_cell_family->allItems()){
1365 // const Cell& cell = *icell;
1366 // Integer cell_local_id = cell.localId();
1367 // if (m_neighbour_cells_owner->index(cell_local_id) == -1 &&
1368 // m_neighbour_extra_cells_owner->at(cell_local_id).size() == 0 )
1369 // fatal() << ItemPrinter(cell) << " has no neighbours! (no owner)";
1370 // if (m_neighbour_cells_new_owner->index(cell_local_id)==(-1))
1371 // fatal() << ItemPrinter(cell) << " has no neighbours! (no new owner index)";
1372 // }
1373
1374 // Determines which cells can be deleted.
1375 // A cell can be deleted if the list of its new owners does not
1376 // contain this subdomain.
1377
1378 ItemGroup all_items = m_cell_family->allItems();
1379
1380 auto itemfamily_network = m_mesh->itemFamilyNetwork();
1381 bool use_itemfamily_network = (itemfamily_network != nullptr && itemfamily_network->isActivated());
1382
1383 // With AMR, we use active cells and not all cells.
1384 if (use_active_cells)
1385 all_items = m_cell_family->allItems().activeCellGroup();
1386
1387 ENUMERATE_CELL (icell, all_items) {
1388 Cell cell = *icell;
1389 Integer cell_local_id = cell.localId();
1390 if (cells_new_owner[cell_local_id] == m_rank)
1391 continue;
1392
1393 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
1394 bool keep_cell = new_owners.contains(m_rank);
1395 if (!keep_cell) {
1396 Int32ConstArrayView extra_new_owners = m_neighbour_extra_cells_new_owner->at(cell_local_id);
1397 keep_cell = extra_new_owners.contains(m_rank);
1398 }
1399 if (!keep_cell && use_itemfamily_network) {
1400 Int32ArrayView item_dest_ranks;
1401 // Get destination rank for item (depending if it's ghost or own)
1402 if (icell->isOwn())
1403 item_dest_ranks = m_item_dest_ranks_map[m_cell_family]->at(icell->localId()).view();
1404 else
1405 item_dest_ranks = m_ghost_item_dest_ranks_map[icell->owner()][m_cell_family]->at(icell->localId()).view();
1406 // Check if the item must stay on the subdomain (ie dest_rank or new_owner contain the subdomain)
1407 keep_cell = item_dest_ranks.contains(m_rank);
1408 }
1409 if (!keep_cell) {
1410 cell.mutableItemBase().addFlags(ItemFlags::II_NeedRemove);
1411 }
1412 }
1413}
1414/*---------------------------------------------------------------------------*/
1415/*---------------------------------------------------------------------------*/
1416
1417void MeshExchange::
1418_markRemovableParticles()
1419{
1420 for (IItemFamily* family : m_mesh->itemFamilies()) {
1421 IParticleFamily* particle_family = family->toParticleFamily();
1422 if (particle_family && particle_family->getEnableGhostItems()) {
1423 mesh::NewItemOwnerBuilder owner_builder;
1424
1425 ENUMERATE_PARTICLE (iparticle, particle_family->allItems()) {
1426 Particle particle = *iparticle;
1427 Cell cell = owner_builder.connectedCellOfItem(particle);
1428 // NOTE GG: 10/2026. This code is very strange
1429 // I think we should only modify some flags (II_NeedRemove?)
1430 if (!cell.null())
1431 particle.mutableItemBase().setFlags(cell.itemBase().flags());
1432 }
1433 }
1434 }
1435}
1436
1437/*---------------------------------------------------------------------------*/
1438/*---------------------------------------------------------------------------*/
1439
1440void MeshExchange::
1441_checkSubItemsDestRanks()
1442{
1443 // Check subitems dest_ranks contain parent dest_rank (even after exchangeDataInfo...)
1444 // Check for items that the subdomain do send : ie own items
1445 m_mesh->itemFamilyNetwork()->schedule([this](IItemFamily* family) {
1446 ENUMERATE_ITEM (item, family->allItems().own()) {
1447 const auto& item_dest_ranks = m_item_dest_ranks_map[family]->at(item.localId());
1448 for (const auto& child_dependency : m_mesh->itemFamilyNetwork()->getChildDependencies(family)) {
1449 auto accessor = IndexedItemConnectivityAccessor(child_dependency);
1450 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
1451 Int32ConstArrayView subitem_dest_ranks;
1452 // test can only be done for own subitems, otherwise their dest_ranks are only partially known => to see
1453 if (connected_item->isOwn()) {
1454 subitem_dest_ranks = m_item_dest_ranks_map[child_dependency->targetFamily()]->at(connected_item.localId()).constView();
1455 for (auto dest_rank : item_dest_ranks) {
1456 if (!subitem_dest_ranks.contains(dest_rank))
1457 fatal() << "Dest Rank " << dest_rank << " for item " << item->kind() << " uid " << item->uniqueId()
1458 << " not present in subitem " << connected_item->kind() << " uid " << connected_item->uniqueId()
1459 << " dest ranks " << subitem_dest_ranks << " ower " << connected_item->owner();
1460 }
1461 }
1462 }
1463 }
1464 }
1465 },
1466 IItemFamilyNetwork::TopologicalOrder);
1467}
1468
1469/*---------------------------------------------------------------------------*/
1470/*---------------------------------------------------------------------------*/
1471
1472void MeshExchange::
1473_exchangeGhostItemDataInfos()
1474{
1475 /* necessary for dark corner cases (with graph for example) :
1476 * we need to know if a ghost item will stay ghost
1477 * otherwise we will destroy it and when we receive it again
1478 * we won't be able to restore some relations pointing on it
1479 * ex a cell ghost on Sd_0(subdomain 0) is removed while a face (owner = 0) stays on the subdomain
1480 * when the cell comes back, send by Sd_1, the face is not send by Sd_1 since it belongs to Sd_0
1481 * the relation from the cell to the face is restored but the one from the face to the cell is not
1482 * This case should not happen with contiguous partitions,
1483 * but when you start to add extra ghost to follow graph for example, it occurs...
1484 */
1485
1486 // Graph connectivity taken into account thanks to the call to _addGraphConnectivityToNewConnectivityInfo
1487 auto sd_exchange{ ParallelMngUtils::createExchangerRef(m_parallel_mng) };
1488
1489 Int32UniqueArray recv_sub_domains;
1490 m_cell_family->getCommunicatingSubDomains(recv_sub_domains);
1491 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i)
1492 sd_exchange->addSender(recv_sub_domains[i]);
1493
1494 sd_exchange->initializeCommunicationsMessages(recv_sub_domains);
1495
1496 UniqueArray<IItemFamily*> item_families;
1497 Int32UniqueArray item_dest_ranks;
1498 Int32UniqueArray item_nb_dest_ranks;
1499 Int32UniqueArray family_nb_items;
1500 Int64UniqueArray item_uids;
1501
1502 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
1503 ISerializeMessage* comm = sd_exchange->messageToSend(i);
1504 Int32 dest_sub_domain = comm->destination().value();
1505 ISerializer* sbuf = comm->serializer();
1506 item_families.clear();
1507 item_dest_ranks.clear();
1508 item_nb_dest_ranks.clear();
1509 family_nb_items.clear();
1510 item_uids.clear();
1511 for (const auto& family_item_dest_ranks : m_item_dest_ranks_map) {
1512 Integer family_nb_item = 0;
1513 IItemFamily* family = family_item_dest_ranks.first;
1514 if (family->nbItem() == 0)
1515 continue; // skip empty family
1516 item_families.add(family);
1517 // Get shared items with dest_sub_domain
1518 auto subdomain_index = _getSubdomainIndexInCommunicatingRanks(dest_sub_domain, family->allItemsSynchronizer()->communicatingRanks());
1519 auto shared_item_lids = family->allItemsSynchronizer()->sharedItems(subdomain_index);
1520 for (const auto& item_lid : shared_item_lids) {
1521 if (family_item_dest_ranks.second->at(item_lid).size() == 0)
1522 continue;
1523 item_dest_ranks.addRange(family_item_dest_ranks.second->at(item_lid));
1524 item_nb_dest_ranks.add(family_item_dest_ranks.second->at(item_lid).size());
1525 family_nb_item++;
1526 }
1527 family_nb_items.add(family_nb_item);
1528 ENUMERATE_ITEM (item, family_item_dest_ranks.first->view(shared_item_lids)) {
1529 item_uids.add(item->uniqueId().asInt64());
1530 }
1531 }
1532 sbuf->setMode(ISerializer::ModeReserve);
1533
1534 sbuf->reserveInt64(1); // nb_item_family
1535 for (const auto& family : item_families)
1536 sbuf->reserve(family->name()); // ItemFamily->name
1537 sbuf->reserveInt64(item_families.size()); // ItemFamily->itemKind
1538
1539 sbuf->reserveArray(item_uids);
1540 sbuf->reserveArray(family_nb_items);
1541 sbuf->reserveArray(item_nb_dest_ranks);
1542 sbuf->reserveArray(item_dest_ranks);
1543
1544 sbuf->allocateBuffer();
1545 sbuf->setMode(ISerializer::ModePut);
1546
1547 sbuf->putInt64(item_families.size());
1548 for (const auto& family : item_families)
1549 sbuf->put(family->name()); // ItemFamily->name
1550 for (const auto& family : item_families)
1551 sbuf->putInteger(family->itemKind()); // ItemFamily->itemKind
1552
1553 sbuf->putArray(item_uids);
1554 sbuf->putArray(family_nb_items);
1555 sbuf->putArray(item_nb_dest_ranks);
1556 sbuf->putArray(item_dest_ranks);
1557 }
1558
1559 sd_exchange->processExchange();
1560
1561 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
1562 ISerializeMessage* comm = sd_exchange->messageToReceive(i);
1563 ISerializer* sbuf = comm->serializer();
1564 Int64 nb_families = sbuf->getInt64();
1565 StringUniqueArray item_family_names(nb_families);
1566 Int32UniqueArray item_family_kinds(nb_families);
1567 for (auto& family_name : item_family_names)
1568 sbuf->get(family_name); // ItemFamily->name
1569 for (auto& family_kind : item_family_kinds)
1570 family_kind = sbuf->getInteger(); // ItemFamily->itemKind
1571 sbuf->getArray(item_uids);
1572 sbuf->getArray(family_nb_items);
1573 sbuf->getArray(item_nb_dest_ranks);
1574 sbuf->getArray(item_dest_ranks);
1575 Integer item_uid_index = 0;
1576 Integer item_nb_dest_rank_index = 0;
1577 Integer item_dest_rank_index = 0;
1578 for (int family_index = 0; family_index < nb_families; ++family_index) {
1579 IItemFamily* family = m_mesh->findItemFamily(eItemKind(item_family_kinds[family_index]), item_family_names[family_index], false);
1580 Int64ArrayView family_item_uids = item_uids.subView(item_uid_index, family_nb_items[family_index]);
1581 Int32UniqueArray item_lids(family_item_uids.size());
1582 family->itemsUniqueIdToLocalId(item_lids, family_item_uids, true);
1583 for (const auto& item_lid : item_lids) {
1584 auto sub_view = item_dest_ranks.subView(item_dest_rank_index, item_nb_dest_ranks[item_nb_dest_rank_index]);
1585 Int32 dest_rank = comm->destination().value();
1586 m_ghost_item_dest_ranks_map[dest_rank][family]->at(item_lid).addRange(sub_view);
1587 item_dest_rank_index += item_nb_dest_ranks[item_nb_dest_rank_index++];
1588 }
1589 item_uid_index += family_nb_items[family_index];
1590 }
1591 }
1592 // _checkSubItemsDestRanks();
1593}
1594
1595/*---------------------------------------------------------------------------*/
1596/*---------------------------------------------------------------------------*/
1597
1598Integer MeshExchange::
1599_getSubdomainIndexInCommunicatingRanks(Integer rank, Int32ConstArrayView communicating_ranks)
1600{
1601 Integer i = 0;
1602 while (communicating_ranks[i] != rank) {
1603 ++i;
1604 }
1605 return i;
1606}
1607
1608/*---------------------------------------------------------------------------*/
1609/*---------------------------------------------------------------------------*/
1610
1611ISubDomain* MeshExchange::
1612subDomain() const
1613{
1614 return m_mesh->subDomain();
1615}
1616
1617/*---------------------------------------------------------------------------*/
1618/*---------------------------------------------------------------------------*/
1619
1620} // End namespace Arcane::mesh
1621
1622/*---------------------------------------------------------------------------*/
1623/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
#define ENUMERATE_PARTICLE(name, group)
Generic enumerator for a particle group.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
#define ENUMERATE_EDGE(name, group)
Generic enumerator for an edge group.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
constexpr ArrayView< T > subView(Integer abegin, Integer asize) noexcept
Sub-view starting from element abegin and containing asize elements.
void fill(ConstReferenceType value)
Fills the array with the value value.
void addRange(ConstReferenceType val, Int64 n)
Adds n elements of value val to the end of the array.
void clear()
Removes the elements from the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
View of cell information.
Cell of a mesh.
Definition Item.h:1300
Cell topHParent() const
level 0 parent for AMR
Definition Item.h:1444
Constant view of an array of type T.
constexpr ConstArrayView< T > subView(Integer abegin, Integer asize) const noexcept
Sub-view (constant) starting from element abegin and containing asize elements.
bool contains(const_reference v) const
true if the array contains the element of value v
constexpr Integer size() const noexcept
Number of elements in the array.
virtual SharedArray< IIncrementalItemConnectivity * > getChildDependencies(IItemFamily *source_family)=0
Get the list of all dependencies, children of a family source_family or.
Interface of an entity family.
Definition IItemFamily.h:85
virtual ItemGroup allItems() const =0
Group of all entities.
virtual Int32 maxLocalId() const =0
virtual String name() const =0
Family name.
virtual eItemKind itemKind() const =0
Entity kind.
virtual VariableItemInt32 & itemsNewOwner()=0
Variable containing the number of the new subdomain owning the entity.
virtual IItemFamilyNetwork * itemFamilyNetwork()=0
Family network interface (connected families).
constexpr bool hasNext()
True if the end of the enumerator has not been reached (index()<count()).
@ II_NeedRemove
The entity must be removed.
Definition ItemFlags.h:63
Index of an Item in a variable.
Definition ItemLocalId.h:42
NodeConnectedListViewType nodes() const
List of nodes of the entity.
Definition Item.h:843
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
void setFlags(Int32 f)
Sets the entity flags.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage fatal() const
Flow for a fatal error message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
ConstArrayView< std::set< Int32 > > getItemsToSend(IItemFamily *family) const
List of entities to send by subdomain for the family family.
void computeInfos()
Compute the info.
ArrayView< std::set< Int32 > > _getItemsToSend(IItemFamily *family)
List of entities to send by subdomain for the family family.
void _printItemToSend(IItemFamily *family)
Using ItemFamilyNetwork.
void _computeMeshConnectivityInfos2(Int32ConstArrayView cells_new_owner)
AMR.
void _computeMeshConnectivityInfos3()
AMR OFF.
ItemEnumeratorT< Node > NodeEnumerator
Enumerators over nodes.
Definition ItemTypes.h:255
ItemEnumeratorT< Face > FaceEnumerator
Enumerators over faces.
Definition ItemTypes.h:266
ItemEnumeratorT< Edge > EdgeEnumerator
Enumerators over edges.
Definition ItemTypes.h:260
ItemEnumeratorT< Cell > CellEnumerator
Enumerators over cells.
Definition ItemTypes.h:272
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
Ref< IParallelExchanger > createExchangerRef(IParallelMng *pm)
Returns an interface to transfer messages between ranks.
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:445
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:333
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:476
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:447
eItemKind
Mesh entity type.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Face
Face mesh entity.
@ IK_DoF
Degree of Freedom mesh entity.
@ IK_Edge
Edge mesh entity.
Array< Int32 > Int32Array
Dynamic one-dimensional array of 32-bit integers.
Definition UtilsTypes.h:121
UniqueArray< String > StringUniqueArray
Dynamic 1D array of strings.
Definition UtilsTypes.h:353
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:341
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
std::int32_t Int32
Signed integer type of 32 bits.