Arcane  4.1.12.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 _addItemToSend(to_send, iparticle->localId(), iparticle->cell().localId(), use_itemfamily_network);
613 }
614 }
615 if (send_dof && family->itemKind() == IK_DoF) {
616 _setItemsToSend(family);
617 }
618 }
619 }
620
621 // Ensures that we do not send the entities
622 for (const auto& iter : m_items_to_send)
623 (*(iter.second))[m_rank].clear();
624
625 const bool is_print = false;
626 if (is_print) {
627 debug() << "PRINT ITEM TO SEND V1";
628 _printItemToSend(node_family);
629 _printItemToSend(edge_family);
630 _printItemToSend(face_family);
631 _printItemToSend(cell_family);
632 }
633}
634
635/*---------------------------------------------------------------------------*/
636/*---------------------------------------------------------------------------*/
637/*
638 * This version is more general than the first because it takes into account
639 * the AMR case. However, the current version is less performant than the first.
640 * For this reason, the initial version will remain the default version in the non-AMR case.
641 * NOTE: the initial version can be used in the AMR case, as the exchanges
642 * happen regarding the connectivity around the nodes. So the exchange happens
643 * on the tree of an active cell. This idea has not been TODO tested to confirm it.
644 */
645/*---------------------------------------------------------------------------*/
646/*---------------------------------------------------------------------------*/
647
650{
651 Integer cell_variable_size = m_cell_family->maxLocalId();
652
653 m_neighbour_cells_owner = new IncrementalUnorderedMultiArray<Int32>(cell_variable_size);
654 m_neighbour_cells_new_owner = new IncrementalUnorderedMultiArray<Int32>(cell_variable_size);
655
656 Int32UniqueArray tmp_new_owner(m_nb_rank);
657 tmp_new_owner.fill(NULL_ITEM_ID);
658 Int32UniqueArray tmp_owner(m_nb_rank);
659 tmp_owner.fill(NULL_ITEM_ID);
660
661 ENUMERATE_CELL (icell, m_cell_family->allItems().ownActiveCellGroup()) {
662 const Cell& cell = *icell;
663 Integer cell_local_id = cell.localId();
664 // We do not add ourselves to our list of connected cells.
665 tmp_owner[m_rank] = cell_local_id;
666
667 m_neighbour_cells_owner->beginIncrement(cell_local_id);
668 m_neighbour_cells_new_owner->beginIncrement(cell_local_id);
669
670 for (NodeEnumerator inode(cell.nodes()); inode.hasNext(); ++inode) {
671 Int32UniqueArray local_ids;
672 for (CellEnumerator icell2((*inode)._internalActiveCells(local_ids)); icell2.hasNext(); ++icell2) {
673 Integer cell2_local_id = icell2.localId();
674 Integer cell2_new_owner = cells_new_owner[cell2_local_id];
675 Integer cell2_owner = icell2->owner();
676 // Checks if it is not in the list and, if not, adds it.
677 if (tmp_new_owner[cell2_new_owner] != cell_local_id) {
678 tmp_new_owner[cell2_new_owner] = cell_local_id;
679 m_neighbour_cells_new_owner->addData(cell2_new_owner);
680 }
681 if (tmp_owner[cell2_owner] != cell_local_id) {
682 tmp_owner[cell2_owner] = cell_local_id;
683 m_neighbour_cells_owner->addData(cell2_owner);
684 }
685 }
686 local_ids.clear();
687 }
688 m_neighbour_cells_owner->endIncrement();
689 m_neighbour_cells_new_owner->endIncrement();
690 }
691}
692
693/*---------------------------------------------------------------------------*/
694/*---------------------------------------------------------------------------*/
695
696void MeshExchange::
697_addTreeCellToSend(ArrayView<std::set<Int32>> items_to_send,
698 Int32 local_id, Int32 cell_local_id,
699 CellInfoListView cells)
700{
701 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
702
703 Cell cell(cells[local_id]);
704 if (cell.level() == 0) {
705 for (Integer zz = 0, nb_new_owner = new_owners.size(); zz < nb_new_owner; ++zz)
706 items_to_send[new_owners[zz]].insert(local_id);
707 // Graph is okay on the active level
708 Int32ConstArrayView extra_new_owners = m_neighbour_extra_cells_new_owner->at(cell_local_id);
709 for (Integer zz = 0, nb_extra_new_owner = extra_new_owners.size(); zz < nb_extra_new_owner; ++zz)
710 items_to_send[extra_new_owners[zz]].insert(local_id);
711 }
712 else {
713 Int32UniqueArray family;
714 Cell top_parent = cell.topHParent();
715 _familyTree(family, top_parent);
716 for (Integer c = 0, cs = family.size(); c < cs; c++) {
717 for (Integer zz = 0, nb_new_owner = new_owners.size(); zz < nb_new_owner; ++zz)
718 items_to_send[new_owners[zz]].insert(family[c]);
719 }
720 }
721}
722
723/*---------------------------------------------------------------------------*/
724/*---------------------------------------------------------------------------*/
725
726void MeshExchange::
727_addTreeItemToSend(Int32 cell_local_id, CellInfoListView cells)
728{
729 Int32UniqueArray tree_cells_lid;
730
731 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
732
733 Cell cell(cells[cell_local_id]);
734
735 Int32UniqueArray family;
736
737 Cell top_parent = cell.topHParent();
738 _familyTree(family, top_parent);
739
740 IItemFamily* node_family = mesh()->nodeFamily();
741 IItemFamily* edge_family = mesh()->edgeFamily();
742 IItemFamily* face_family = mesh()->faceFamily();
743
744 ArrayView<std::set<Int32>> nodes_to_send = _getItemsToSend(node_family);
745 ArrayView<std::set<Int32>> edges_to_send = _getItemsToSend(edge_family);
746 ArrayView<std::set<Int32>> faces_to_send = _getItemsToSend(face_family);
747
748 // We assume that the containers nodes_to_send, edges_to_send and face_to_send
749 // are already allocated
750 for (Integer c = 0, cs = family.size(); c < cs; c++) // c=0 is the topParent cell.
751 for (Integer zz = 0, nb_new_owner = new_owners.size(); zz < nb_new_owner; ++zz) {
752 Cell cell2 = cells[family[c]];
753 for (Node node : cell2.nodes())
754 nodes_to_send[new_owners[zz]].insert(node.localId());
755 for (Edge edge : cell2.edges())
756 edges_to_send[new_owners[zz]].insert(edge.localId());
757 for (Face face : cell2.faces())
758 faces_to_send[new_owners[zz]].insert(face.localId());
759 }
760}
761
762/*---------------------------------------------------------------------------*/
763/*---------------------------------------------------------------------------*/
764
765void MeshExchange::
766_familyTree(Int32Array& family, Cell item, const bool reset) const
767{
768 ARCANE_ASSERT((!item.itemBase().isSubactive()), ("The family tree doesn't include subactive items"));
769 // Clear the array if the flag reset tells us to.
770 if (reset)
771 family.clear();
772 // Add this item to the family tree.
773 family.add(item.localId());
774 // Recurse into the items children, if it has them.
775 // Do not clear the array any more.
776 if (!item.isActive())
777 for (Integer c = 0, cs = item.nbHChildren(); c < cs; c++) {
778 Item ichild = item.hChild(c);
779 if (ichild.isOwn())
780 _familyTree(family, ichild.toCell(), false);
781 }
782}
783
784/*---------------------------------------------------------------------------*/
785/*---------------------------------------------------------------------------*/
786
787void MeshExchange::
788_computeItemsToSend2()
789{
790 for (const auto& iter : m_items_to_send)
791 iter.second->resize(m_nb_rank);
792
793 IItemFamily* node_family = mesh()->nodeFamily();
794 IItemFamily* edge_family = mesh()->edgeFamily();
795 IItemFamily* face_family = mesh()->faceFamily();
796
797 ArrayView<std::set<Int32>> nodes_to_send = _getItemsToSend(node_family);
798 ArrayView<std::set<Int32>> edges_to_send = _getItemsToSend(edge_family);
799 ArrayView<std::set<Int32>> faces_to_send = _getItemsToSend(face_family);
800 ArrayView<std::set<Int32>> cells_to_send = _getItemsToSend(m_cell_family);
801
802 Int32ConstArrayView cells_new_owner(m_cell_family->itemsNewOwner().asArray());
803 Int32ConstArrayView faces_new_owner(face_family->itemsNewOwner().asArray());
804
805 CellInfoListView cells(m_cell_family);
806 ENUMERATE_CELL (icell, m_cell_family->allItems().ownActiveCellGroup()) {
807 Cell cell = *icell;
808 _addTreeCellToSend(cells_to_send, icell.itemLocalId(), icell.itemLocalId(), cells);
809
810 if (cell.level() == 0) {
811
812 for (NodeEnumerator inode(cell.nodes()); inode.hasNext(); ++inode) {
813 Node node = *inode;
814 if (node.isOwn()) {
815 Integer node_local_id = node.localId();
816 for (CellEnumerator icell2(node.cells()); icell2.hasNext(); ++icell2) {
817 Cell cc = *icell2;
818 if (cc.isActive())
819 _addItemToSend(nodes_to_send, node_local_id, icell2.localId());
820 }
821 }
822 }
823
824 for (EdgeEnumerator iedge(cell.edges()); iedge.hasNext(); ++iedge) {
825 Edge edge = *iedge;
826 if (edge.isOwn()) {
827 Integer edge_local_id = edge.localId();
828 for (CellEnumerator icell2(edge.cells()); icell2.hasNext(); ++icell2)
829 _addItemToSend(edges_to_send, edge_local_id, icell2.localId());
830 }
831 }
832
833 for (FaceEnumerator iface(cell.faces()); iface.hasNext(); ++iface) {
834 Face face = *iface;
835 if (face.isOwn()) {
836 Integer face_local_id = face.localId();
837 for (CellEnumerator icell2(face.cells()); icell2.hasNext(); ++icell2) {
838 _addItemToSend(faces_to_send, face_local_id, icell2.localId());
839 }
840 }
841 }
842 }
843 else if (cell.level() > 0)
844 _addTreeItemToSend(icell.itemLocalId(), cells);
845 }
846
847 for (IItemFamily* family : m_mesh->itemFamilies()) {
848 IParticleFamily* particle_family = family->toParticleFamily();
849 if (particle_family && particle_family->getEnableGhostItems() == true) {
850 ArrayView<std::set<Int32>> to_send = _getItemsToSend(family);
851 ENUMERATE_PARTICLE (iparticle, particle_family->allItems().own()) {
852 _addItemToSend(to_send, iparticle->localId(), iparticle->cell().localId());
853 }
854 }
855 }
856
857 // Ensures that entities are not sent
858 for (const auto& iter : m_items_to_send)
859 (*(iter.second))[m_rank].clear();
860}
861
862/*---------------------------------------------------------------------------*/
863/*---------------------------------------------------------------------------*/
864
866
867/*---------------------------------------------------------------------------*/
868/*---------------------------------------------------------------------------*/
869/*
870 * This version provides an implementation for calculating items to exchange
871 * using the item family dependency graph (ItemFamilyNetwork)
872 * NOTE: For now, the algorithms for the IGraph arcane graph and for particle
873 * families remain unchanged.
874 */
875/*---------------------------------------------------------------------------*/
876/*---------------------------------------------------------------------------*/
877
879
882{
883 if (!m_mesh->itemFamilyNetwork())
884 info() << "Should have an IItemFamilyNetwork. Exiting.";
885 //1-Prepare data structure
886 m_ghost_item_dest_ranks_map.resize(m_parallel_mng->commSize());
887 m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family) {
888 _allocData(family);
889 },
890 IItemFamilyNetwork::TopologicalOrder);
891
892 // Here the algorithm propagates the owner to the neighborhood
893 // The propagation to the items owned (dependencies) has already been done in updateOwnersFromCell
894 // Todo include also the owned item propagation (would avoid to call updateOwnersFromCell...)
895 // What we do here is to build the number of ghost layers needed
896 //-For each ghost layer wanted:
897 // 1- For all items add Item new owner and all its dest ranks to all child item connected (dependency or relation) dest ranks
898 // This is done for all family, parsing the family graph from head to leaves
899 // 2- For all items add new dest ranks to its depending child (move with your downward dependencies)
900 if (!m_mesh->ghostLayerMng())
901 info() << "Should have a IGhostLayerMng. Exiting";
902 for (int ghost_layer_index = 0; ghost_layer_index < m_mesh->ghostLayerMng()->nbGhostLayer(); ++ghost_layer_index) {
903 //2-Diffuse destination rank info to connected items
904 m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family) {
905 _propagatesToChildConnectivities(family);
906 },
907 IItemFamilyNetwork::TopologicalOrder);
908
909 //m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family){
910 // _propagatesToChildDependencies(family);
911 //},
912 //IItemFamilyNetwork::TopologicalOrder);
913 }
914}
915
916/*---------------------------------------------------------------------------*/
917/*---------------------------------------------------------------------------*/
918
919void MeshExchange::
920_propagatesToChildConnectivities(IItemFamily* family)
921{
922 VariableItemInt32& item_new_owner = family->itemsNewOwner();
923 /* TODO : this propagation should be needed for all child dependencies and not all relations but only ghost providing relations
924 * eg for node to cell connectivity if ghosts are found via node neighbouring. This notion of ghost providing relations must be added
925 * 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) :
926 * auto child_connectivities = m_mesh->itemFamilyNetwork()->getChildDependencies(family); // instead of getChildConnectivities
927 * if (family->itemKind()==IK_Node) {
928 * child_connectivities.add(m_mesh->itemFamilyNetwork()->getConnectivity(family,m_mesh->cellFamily(),mesh::connectivityName(family,m_mesh->cellFamily())));
929 * }
930 */
931 //auto child_connectivities = m_mesh->itemFamilyNetwork()->getChildConnectivities(family);
932 auto child_connectivities = m_mesh->itemFamilyNetwork()->getChildDependencies(family); // Only dependencies are required to propagate owner
933 for (const auto& child_connectivity : child_connectivities) {
934 if (child_connectivity) {
935 VariableItemInt32& conn_item_new_owner = child_connectivity->targetFamily()->itemsNewOwner();
936 auto accessor = IndexedItemConnectivityAccessor(child_connectivity);
937 ENUMERATE_ITEM (item, family->allItems()) {
938 // Parse child relations
939 _addDestRank(*item, family, item_new_owner[item]);
940 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
941 _addDestRank(*item, family, conn_item_new_owner[connected_item]);
942 }
943
944 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
945 _addDestRank(*connected_item, child_connectivity->targetFamily(), *item, family);
946 }
947 }
948 }
949 }
950 if (!m_mesh->useMeshItemFamilyDependencies()) {
951 switch (family->itemKind()) {
952 case IK_Face:
953 ENUMERATE_ (Face, item, family->allItems()) {
954 for (Cell cell : item->cells())
955 _addDestRank(cell, m_cell_family, *item, family);
956 }
957 break;
958 case IK_Edge:
959 ENUMERATE_ (Edge, item, family->allItems()) {
960 for (Cell cell : item->cells())
961 _addDestRank(cell, m_cell_family, *item, family);
962 }
963 break;
964 case IK_Node:
965 ENUMERATE_ (Node, item, family->allItems()) {
966 for (Cell cell : item->cells())
967 _addDestRank(cell, m_cell_family, *item, family);
968 }
969 break;
970 default:
971 break;
972 }
973 }
974}
975
976/*---------------------------------------------------------------------------*/
977/*---------------------------------------------------------------------------*/
978
979void MeshExchange::
980_propagatesToChildDependencies(IItemFamily* family)
981{
982 // Here we only propagates dest_ranks, since owner propagation to children has already been done in updateOwnersFromCell
983 // todo 1 use these new algo to propagates the owner
984 // todo 2 when using the graph we do not need to access to all child connectivities, only the one of the immediately inferior level.
985 // => we should allow graph task to take the signature task(IItemFamily*,FirstRankChildren) where FirstRankChildren (better name ??)
986 // would contain the immediate children (FirstRankChildren) would be an EdgeSet or smthg near
987 // => thus we would need to add to the DAG a method children(const Edge&) (see for the name firstRankChildren ??)
988 auto child_dependencies = m_mesh->itemFamilyNetwork()->getChildDependencies(family);
989 for (const auto& child_dependency : child_dependencies) {
990 if (child_dependency) {
991 auto accessor = IndexedItemConnectivityAccessor(child_dependency);
992 ENUMERATE_ITEM (item, family->allItems()) {
993 // Parse child dependencies
994 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
995 _addDestRank(*connected_item, child_dependency->targetFamily(), *item, family); // as simple as that ??
996 }
997 }
998 }
999 }
1000}
1001
1002/*---------------------------------------------------------------------------*/
1003/*---------------------------------------------------------------------------*/
1004
1005void MeshExchange::
1006_addDestRank(const Item& item, IItemFamily* item_family, const Integer new_owner) // take an ItemInternal* ?
1007{
1008 ItemDestRankArray* item_dest_ranks = nullptr;
1009 if (item.owner() == m_rank) {
1010 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)
1011 }
1012 else {
1013 item_dest_ranks = m_ghost_item_dest_ranks_map[item.owner()][item_family];
1014 }
1015 // Insert element only if not present
1016 auto& item_ranks_internal = item_dest_ranks->at(item.localId());
1017 if (!item_ranks_internal.contains(new_owner))
1018 item_dest_ranks->at(item.localId()).add(new_owner);
1019}
1020
1021/*---------------------------------------------------------------------------*/
1022/*---------------------------------------------------------------------------*/
1023
1024void MeshExchange::
1025_addDestRank(const Item& item, IItemFamily* item_family, const Item& followed_item, IItemFamily* followed_item_family)
1026{
1027 // todo : a getDestRank method
1028 ItemDestRankArray* item_dest_ranks = nullptr;
1029 if (item.owner() == m_rank) {
1030 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)
1031 }
1032 else {
1033 item_dest_ranks = m_ghost_item_dest_ranks_map[item.owner()][item_family];
1034 }
1035 ItemDestRankArray* followed_item_dest_ranks = nullptr;
1036 if (followed_item.owner() == m_rank)
1037 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)
1038 else
1039 followed_item_dest_ranks = m_ghost_item_dest_ranks_map[followed_item.owner()][followed_item_family];
1040 // Add only new dest rank only if not already present
1041 auto& new_dest_ranks = followed_item_dest_ranks->at(followed_item.localId());
1042 auto& current_dest_ranks = item_dest_ranks->at(item.localId());
1043 IntegerUniqueArray new_dest_rank_to_add;
1044 new_dest_rank_to_add.reserve((new_dest_ranks.size()));
1045 for (auto& new_dest_rank : new_dest_ranks) {
1046 if (!current_dest_ranks.contains(new_dest_rank))
1047 new_dest_rank_to_add.add(new_dest_rank);
1048 }
1049 current_dest_ranks.addRange(new_dest_rank_to_add);
1050}
1051
1052/*---------------------------------------------------------------------------*/
1053/*---------------------------------------------------------------------------*/
1054
1055void MeshExchange::
1056_allocData(IItemFamily* family)
1057{
1058 m_item_dest_ranks_map[family] = new ItemDestRankArray(family->maxLocalId());
1059 for (auto& ghost_item_map : m_ghost_item_dest_ranks_map) {
1060 ghost_item_map[family] = new ItemDestRankArray(family->maxLocalId());
1061 }
1062}
1063/*---------------------------------------------------------------------------*/
1064/*---------------------------------------------------------------------------*/
1065
1066void MeshExchange::
1067_debugPrint()
1068{
1069 info() << "-ENTERING NEW EXCHANGE DEBUG PRINT";
1070 for (auto& item_dest_ranks : m_item_dest_ranks_map) {
1071 info() << "--PRINT NEW EXCHANGE INFO";
1072 info() << "---Destination rank for family " << item_dest_ranks.first->name();
1073 for (int item_lid = 0; item_lid < item_dest_ranks.first->maxLocalId(); ++item_lid) {
1074 info() << "---Destination rank for item lid " << item_lid;
1075 for (auto& item_dest_rank : item_dest_ranks.second->at(item_lid)) {
1076 info() << "---- Rank " << item_dest_rank;
1077 }
1078 }
1079 }
1080}
1081
1082/*---------------------------------------------------------------------------*/
1083/*---------------------------------------------------------------------------*/
1084
1085void MeshExchange::
1086_exchangeCellDataInfos3()
1087{
1088 // Graph connectivity taken into account thanks to the call to _addGraphConnectivityToNewConnectivityInfo
1089 auto sd_exchange{ ParallelMngUtils::createExchangerRef(m_parallel_mng) };
1090
1091 Int32UniqueArray recv_sub_domains;
1092 m_cell_family->getCommunicatingSubDomains(recv_sub_domains);
1093 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i)
1094 sd_exchange->addSender(recv_sub_domains[i]);
1095
1096 sd_exchange->initializeCommunicationsMessages(recv_sub_domains);
1097
1098 UniqueArray<IItemFamily*> item_families;
1099 Int32UniqueArray item_lids;
1100 Int32UniqueArray item_dest_ranks;
1101 Int32UniqueArray item_nb_dest_ranks;
1102 Int32UniqueArray family_nb_items;
1103 Int64UniqueArray item_uids;
1104
1105 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
1106 ISerializeMessage* comm = sd_exchange->messageToSend(i);
1107 Int32 dest_sub_domain = comm->destination().value();
1108 ISerializer* sbuf = comm->serializer();
1109 item_families.clear();
1110 item_dest_ranks.clear();
1111 item_nb_dest_ranks.clear();
1112 family_nb_items.clear();
1113 item_uids.clear();
1114 for (const auto& family_ghost_item_dest_ranks : m_ghost_item_dest_ranks_map[dest_sub_domain]) {
1115 Integer family_nb_item = 0;
1116 item_lids.clear();
1117 item_families.add(family_ghost_item_dest_ranks.first);
1118 for (Integer item_lid = 0; item_lid < family_ghost_item_dest_ranks.second->size(); ++item_lid) {
1119 if (family_ghost_item_dest_ranks.second->at(item_lid).size() == 0)
1120 continue;
1121 item_lids.add(item_lid);
1122 item_dest_ranks.addRange(family_ghost_item_dest_ranks.second->at(item_lid));
1123 item_nb_dest_ranks.add(family_ghost_item_dest_ranks.second->at(item_lid).size());
1124 family_nb_item++;
1125 }
1126 family_nb_items.add(family_nb_item);
1127 ENUMERATE_ITEM (item, family_ghost_item_dest_ranks.first->view(item_lids)) {
1128 item_uids.add(item->uniqueId().asInt64());
1129 }
1130 }
1131 sbuf->setMode(ISerializer::ModeReserve);
1132 sbuf->reserveInt64(1); // nb_item_family
1133 for (const auto& family : item_families)
1134 sbuf->reserve(family->name()); // ItemFamily->name
1135 sbuf->reserveInteger(item_families.size()); // ItemFamily->itemKind
1136 sbuf->reserveArray(item_uids);
1137 sbuf->reserveArray(family_nb_items);
1138 sbuf->reserveArray(item_nb_dest_ranks);
1139 sbuf->reserveArray(item_dest_ranks);
1140
1141 sbuf->allocateBuffer();
1142 sbuf->setMode(ISerializer::ModePut);
1143
1144 sbuf->putInt64(item_families.size());
1145 for (const auto& family : item_families)
1146 sbuf->put(family->name()); // ItemFamily->name
1147 for (const auto& family : item_families)
1148 sbuf->putInteger(family->itemKind()); // ItemFamily->itemKind
1149 sbuf->putArray(item_uids);
1150 sbuf->putArray(family_nb_items);
1151 sbuf->putArray(item_nb_dest_ranks);
1152 sbuf->putArray(item_dest_ranks);
1153 }
1154
1155 sd_exchange->processExchange();
1156
1157 for (Integer i = 0, n = recv_sub_domains.size(); i < n; ++i) {
1158 ISerializeMessage* comm = sd_exchange->messageToReceive(i);
1159 ISerializer* sbuf = comm->serializer();
1160 Int64 nb_families = sbuf->getInt64();
1161 StringUniqueArray item_family_names(nb_families);
1162 Int32UniqueArray item_family_kinds(nb_families);
1163 for (auto& family_name : item_family_names)
1164 sbuf->get(family_name); // ItemFamily->name
1165 for (auto& family_kind : item_family_kinds)
1166 family_kind = sbuf->getInteger(); // ItemFamily->itemKind
1167 sbuf->getArray(item_uids);
1168 sbuf->getArray(family_nb_items);
1169 sbuf->getArray(item_nb_dest_ranks);
1170 sbuf->getArray(item_dest_ranks);
1171 Integer item_uid_index = 0;
1172 Integer item_nb_dest_rank_index = 0;
1173 Integer item_dest_rank_index = 0;
1174 for (int family_index = 0; family_index < nb_families; ++family_index) {
1175 IItemFamily* family = m_mesh->findItemFamily(eItemKind(item_family_kinds[family_index]),
1176 item_family_names[family_index], false);
1177 Int64ArrayView family_item_uids = item_uids.subView(item_uid_index, family_nb_items[family_index]);
1178 item_lids.resize(family_item_uids.size());
1179 family->itemsUniqueIdToLocalId(item_lids, family_item_uids, true);
1180 for (const auto& item_lid : item_lids) {
1181 auto sub_view = item_dest_ranks.subView(item_dest_rank_index, item_nb_dest_ranks[item_nb_dest_rank_index]);
1182 m_item_dest_ranks_map[family]->at(item_lid).addRange(sub_view);
1183 item_dest_rank_index += item_nb_dest_ranks[item_nb_dest_rank_index++];
1184 }
1185 item_uid_index += family_nb_items[family_index];
1186 }
1187 }
1188 // Dest rank propagation needed since they have been updated for own items
1189 // copy of propagation part of method computeMeshConnectivityInfo3
1190 for (int ghost_layer_index = 0; ghost_layer_index < m_mesh->ghostLayerMng()->nbGhostLayer(); ++ghost_layer_index) {
1191 //2-Diffuse destination rank info to connected items
1192 m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family) {
1193 _propagatesToChildConnectivities(family);
1194 },
1195 IItemFamilyNetwork::TopologicalOrder);
1196
1197 //m_mesh->itemFamilyNetwork()->schedule([&](IItemFamily* family){
1198 // _propagatesToChildDependencies(family);
1199 //},
1200 //IItemFamilyNetwork::TopologicalOrder);
1201 }
1202}
1203/*---------------------------------------------------------------------------*/
1204/*---------------------------------------------------------------------------*/
1205
1206void MeshExchange::
1207_computeItemsToSend3()
1208{
1209 for (const auto& iter : m_items_to_send)
1210 iter.second->resize(m_nb_rank);
1211
1212 IItemFamily* node_family = mesh()->nodeFamily();
1213 IItemFamily* edge_family = mesh()->edgeFamily();
1214 IItemFamily* face_family = mesh()->faceFamily();
1215 IItemFamily* cell_family = m_cell_family;
1216
1217 _setItemsToSend(node_family);
1218 _setItemsToSend(edge_family);
1219 _setItemsToSend(face_family);
1220 _setItemsToSend(cell_family);
1221
1222 // Tmp for particles : they should be in the family graph
1223 {
1224 for (IItemFamily* family : m_mesh->itemFamilies()) {
1225 IParticleFamily* particle_family = family->toParticleFamily();
1226 if (particle_family && particle_family->getEnableGhostItems() == true) {
1227 ArrayView<std::set<Int32>> to_send = _getItemsToSend(family);
1228 ENUMERATE_PARTICLE (iparticle, particle_family->allItems().own()) {
1229 for (const auto& dest_rank : m_item_dest_ranks_map[m_cell_family]->at(iparticle->cell().localId())) {
1230 to_send[dest_rank].insert(iparticle->localId());
1231 }
1232 }
1233 }
1234 }
1235 }
1236
1237 // Ensures that the entities are not sent
1238 for (const auto& iter : m_items_to_send)
1239 (*(iter.second))[m_rank].clear();
1240
1241 // SDC DEBUG
1242 // debug() << "PRINT ITEM TO SEND V2";
1243 // _printItemToSend(node_family);
1244 // _printItemToSend(edge_family);
1245 // _printItemToSend(face_family);
1246 // _printItemToSend(cell_family);
1247}
1248
1249/*---------------------------------------------------------------------------*/
1250/*---------------------------------------------------------------------------*/
1251
1252void MeshExchange::
1253_setItemsToSend(IItemFamily* family)
1254{
1255 if (family->nbItem() == 0)
1256 return;
1257 auto iter = m_items_to_send.find(family);
1258 if (iter == m_items_to_send.end())
1259 ARCANE_FATAL("No items to send for family '{0}'", family->name());
1260 ArrayView<std::set<Int32>> items_to_send = iter->second->view();
1261 for (Integer item_lid = 0; item_lid < m_item_dest_ranks_map[family]->size(); ++item_lid) {
1262 for (const auto& dest_rank : m_item_dest_ranks_map[family]->at(item_lid)) {
1263 items_to_send[dest_rank].insert(item_lid);
1264 }
1265 }
1266}
1267
1268/*---------------------------------------------------------------------------*/
1269/*---------------------------------------------------------------------------*/
1270
1273{
1274 auto iter = m_items_to_send.find(family);
1275 if (iter == m_items_to_send.end())
1276 ARCANE_FATAL("No items to send for family '{0}'", family->name());
1277 ArrayView<std::set<Int32>> items_to_send = iter->second->view();
1278 // SDC DEBUG print
1279 Integer rank = 0;
1280 debug() << "= ITEM TO SEND FOR FAMILY " << family->name();
1281 for (const auto& owner_lids : items_to_send) {
1282 debug() << "== RANK " << rank++;
1283 for (auto item_lid : owner_lids) {
1284 debug() << "=== has items " << item_lid;
1285 }
1286 }
1287}
1288
1289/*---------------------------------------------------------------------------*/
1290/*---------------------------------------------------------------------------*/
1291
1292void MeshExchange::
1293_printItemToRemove(IItemFamily* family)
1294{
1295 // SDC DEBUG PRINT
1296 debug() << "= ITEM TO REMOVE FOR FAMILY " << family->name();
1297 ENUMERATE_ITEM (item, family->allItems()) {
1298 if (item->hasFlags(ItemFlags::II_NeedRemove))
1299 debug() << "== TO REMOVE ITEM " << item->uniqueId() << " kind " << item->kind();
1300 }
1301}
1302
1303/*---------------------------------------------------------------------------*/
1304/*---------------------------------------------------------------------------*/
1305void MeshExchange::
1306_markRemovableDoFs()
1307{
1308 for (const auto& item_dest_ranks_iter : m_item_dest_ranks_map) {
1309 // todo use C++17 structured bindings
1310 IItemFamily* family = item_dest_ranks_iter.first;
1311 if (family->itemKind() == IK_DoF) {
1312 auto& item_new_owners = family->itemsNewOwner();
1313 ENUMERATE_ITEM (item, family->allItems()) {
1314 Int32ArrayView item_dest_ranks;
1315 // Get destination rank for item (depending if it's ghost or own)
1316 if (item->isOwn())
1317 item_dest_ranks = item_dest_ranks_iter.second->at(item->localId()).view();
1318 else
1319 item_dest_ranks = m_ghost_item_dest_ranks_map[item->owner()][family]->at(item->localId()).view();
1320 // Check if the item must stay on the subdomain (ie dest_rank or new_owner contain the subdomain)
1321 if (!item_dest_ranks.contains(m_rank) && item_new_owners[item] != m_rank) {
1322 item->mutableItemBase().addFlags(ItemFlags::II_NeedRemove);
1323 }
1324 }
1325 }
1326 // _printItemToRemove(item_dest_ranks_iter.first); // SDC DEBUG
1327 }
1328}
1329
1330void MeshExchange::
1331_markRemovableItems(bool with_cell_family)
1332{
1333 for (const auto& item_dest_ranks_iter : m_item_dest_ranks_map) {
1334 // todo use C++17 structured bindings
1335 IItemFamily* family = item_dest_ranks_iter.first;
1336 if (with_cell_family || family->name() != m_cell_family->name()) {
1337 auto& item_new_owners = family->itemsNewOwner();
1338 ENUMERATE_ITEM (item, family->allItems()) {
1339 Int32ArrayView item_dest_ranks;
1340 // Get destination rank for item (depending if it's ghost or own)
1341 if (item->isOwn())
1342 item_dest_ranks = item_dest_ranks_iter.second->at(item.localId()).view();
1343 else
1344 item_dest_ranks = m_ghost_item_dest_ranks_map[item->owner()][family]->at(item.localId()).view();
1345 // Check if the item must stay on the subdomain (ie dest_rank or new_owner contain the subdomain)
1346 if (!item_dest_ranks.contains(m_rank) && item_new_owners[item] != m_rank) {
1347 item->mutableItemBase().addFlags(ItemFlags::II_NeedRemove);
1348 }
1349 }
1350 }
1351 // _printItemToRemove(item_dest_ranks_iter.first); // SDC DEBUG
1352 }
1353}
1354
1355void MeshExchange::
1356_markRemovableCells(Int32ConstArrayView cells_new_owner, bool use_active_cells)
1357{
1358 // This test is no longer representative with the extraghost concept
1359 // Should we find an alternative ??
1360 // Checks that all cells have had their neighbors calculated
1361 // ENUMERATE_CELL(icell,m_cell_family->allItems()){
1362 // const Cell& cell = *icell;
1363 // Integer cell_local_id = cell.localId();
1364 // if (m_neighbour_cells_owner->index(cell_local_id) == -1 &&
1365 // m_neighbour_extra_cells_owner->at(cell_local_id).size() == 0 )
1366 // fatal() << ItemPrinter(cell) << " has no neighbours! (no owner)";
1367 // if (m_neighbour_cells_new_owner->index(cell_local_id)==(-1))
1368 // fatal() << ItemPrinter(cell) << " has no neighbours! (no new owner index)";
1369 // }
1370
1371 // Determines which cells can be deleted.
1372 // A cell can be deleted if the list of its new owners does not
1373 // contain this subdomain.
1374
1375 ItemGroup all_items = m_cell_family->allItems();
1376
1377 auto itemfamily_network = m_mesh->itemFamilyNetwork();
1378 bool use_itemfamily_network = (itemfamily_network != nullptr && itemfamily_network->isActivated());
1379
1380 // With AMR, we use active cells and not all cells.
1381 if (use_active_cells)
1382 all_items = m_cell_family->allItems().activeCellGroup();
1383
1384 ENUMERATE_CELL (icell, all_items) {
1385 Cell cell = *icell;
1386 Integer cell_local_id = cell.localId();
1387 if (cells_new_owner[cell_local_id] == m_rank)
1388 continue;
1389
1390 Int32ConstArrayView new_owners = m_neighbour_cells_new_owner->at(cell_local_id);
1391 bool keep_cell = new_owners.contains(m_rank);
1392 if (!keep_cell) {
1393 Int32ConstArrayView extra_new_owners = m_neighbour_extra_cells_new_owner->at(cell_local_id);
1394 keep_cell = extra_new_owners.contains(m_rank);
1395 }
1396 if (!keep_cell && use_itemfamily_network) {
1397 Int32ArrayView item_dest_ranks;
1398 // Get destination rank for item (depending if it's ghost or own)
1399 if (icell->isOwn())
1400 item_dest_ranks = m_item_dest_ranks_map[m_cell_family]->at(icell->localId()).view();
1401 else
1402 item_dest_ranks = m_ghost_item_dest_ranks_map[icell->owner()][m_cell_family]->at(icell->localId()).view();
1403 // Check if the item must stay on the subdomain (ie dest_rank or new_owner contain the subdomain)
1404 keep_cell = item_dest_ranks.contains(m_rank);
1405 }
1406 if (!keep_cell) {
1407 cell.mutableItemBase().addFlags(ItemFlags::II_NeedRemove);
1408 }
1409 }
1410}
1411/*---------------------------------------------------------------------------*/
1412/*---------------------------------------------------------------------------*/
1413
1414void MeshExchange::
1415_markRemovableParticles()
1416{
1417 for (IItemFamily* family : m_mesh->itemFamilies()) {
1418 IParticleFamily* particle_family = family->toParticleFamily();
1419 if (particle_family && particle_family->getEnableGhostItems() == true) {
1420 mesh::NewItemOwnerBuilder owner_builder;
1421
1422 ENUMERATE_PARTICLE (iparticle, particle_family->allItems()) {
1423 Particle particle = *iparticle;
1424 Cell cell = owner_builder.connectedCellOfItem(particle);
1425 particle.mutableItemBase().setFlags(cell.itemBase().flags());
1426 }
1427 }
1428 }
1429}
1430
1431/*---------------------------------------------------------------------------*/
1432/*---------------------------------------------------------------------------*/
1433
1434void MeshExchange::
1435_checkSubItemsDestRanks()
1436{
1437 // Check subitems dest_ranks contain parent dest_rank (even after exchangeDataInfo...)
1438 // Check for items that the subdomain do send : ie own items
1439 m_mesh->itemFamilyNetwork()->schedule([this](IItemFamily* family) {
1440 ENUMERATE_ITEM (item, family->allItems().own()) {
1441 const auto& item_dest_ranks = m_item_dest_ranks_map[family]->at(item.localId());
1442 for (const auto& child_dependency : m_mesh->itemFamilyNetwork()->getChildDependencies(family)) {
1443 auto accessor = IndexedItemConnectivityAccessor(child_dependency);
1444 ENUMERATE_ITEM (connected_item, accessor(ItemLocalId(item))) {
1445 Int32ConstArrayView subitem_dest_ranks;
1446 // test can only be done for own subitems, otherwise their dest_ranks are only partially known => to see
1447 if (connected_item->isOwn()) {
1448 subitem_dest_ranks = m_item_dest_ranks_map[child_dependency->targetFamily()]->at(connected_item.localId()).constView();
1449 for (auto dest_rank : item_dest_ranks) {
1450 if (!subitem_dest_ranks.contains(dest_rank))
1451 fatal() << "Dest Rank " << dest_rank << " for item " << item->kind() << " uid " << item->uniqueId()
1452 << " not present in subitem " << connected_item->kind() << " uid " << connected_item->uniqueId()
1453 << " dest ranks " << subitem_dest_ranks << " ower " << connected_item->owner();
1454 }
1455 }
1456 }
1457 }
1458 }
1459 },
1460 IItemFamilyNetwork::TopologicalOrder);
1461}
1462
1463/*---------------------------------------------------------------------------*/
1464/*---------------------------------------------------------------------------*/
1465
1466void MeshExchange::
1467_exchangeGhostItemDataInfos()
1468{
1469 /* necessary for dark corner cases (with graph for example) :
1470 * we need to know if a ghost item will stay ghost
1471 * otherwise we will destroy it and when we receive it again
1472 * we won't be able to restore some relations pointing on it
1473 * ex a cell ghost on Sd_0(subdomain 0) is removed while a face (owner = 0) stays on the subdomain
1474 * when the cell comes back, send by Sd_1, the face is not send by Sd_1 since it belongs to Sd_0
1475 * the relation from the cell to the face is restored but the one from the face to the cell is not
1476 * This case should not happen with contiguous partitions,
1477 * but when you start to add extra ghost to follow graph for example, it occurs...
1478 */
1479
1480 // Graph connectivity taken into account thanks to the call to _addGraphConnectivityToNewConnectivityInfo
1481 auto sd_exchange{ ParallelMngUtils::createExchangerRef(m_parallel_mng) };
1482
1483 Int32UniqueArray recv_sub_domains;
1484 m_cell_family->getCommunicatingSubDomains(recv_sub_domains);
1485 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i)
1486 sd_exchange->addSender(recv_sub_domains[i]);
1487
1488 sd_exchange->initializeCommunicationsMessages(recv_sub_domains);
1489
1490 UniqueArray<IItemFamily*> item_families;
1491 Int32UniqueArray item_dest_ranks;
1492 Int32UniqueArray item_nb_dest_ranks;
1493 Int32UniqueArray family_nb_items;
1494 Int64UniqueArray item_uids;
1495
1496 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
1497 ISerializeMessage* comm = sd_exchange->messageToSend(i);
1498 Int32 dest_sub_domain = comm->destination().value();
1499 ISerializer* sbuf = comm->serializer();
1500 item_families.clear();
1501 item_dest_ranks.clear();
1502 item_nb_dest_ranks.clear();
1503 family_nb_items.clear();
1504 item_uids.clear();
1505 for (const auto& family_item_dest_ranks : m_item_dest_ranks_map) {
1506 Integer family_nb_item = 0;
1507 IItemFamily* family = family_item_dest_ranks.first;
1508 if (family->nbItem() == 0)
1509 continue; // skip empty family
1510 item_families.add(family);
1511 // Get shared items with dest_sub_domain
1512 auto subdomain_index = _getSubdomainIndexInCommunicatingRanks(dest_sub_domain, family->allItemsSynchronizer()->communicatingRanks());
1513 auto shared_item_lids = family->allItemsSynchronizer()->sharedItems(subdomain_index);
1514 for (const auto& item_lid : shared_item_lids) {
1515 if (family_item_dest_ranks.second->at(item_lid).size() == 0)
1516 continue;
1517 item_dest_ranks.addRange(family_item_dest_ranks.second->at(item_lid));
1518 item_nb_dest_ranks.add(family_item_dest_ranks.second->at(item_lid).size());
1519 family_nb_item++;
1520 }
1521 family_nb_items.add(family_nb_item);
1522 ENUMERATE_ITEM (item, family_item_dest_ranks.first->view(shared_item_lids)) {
1523 item_uids.add(item->uniqueId().asInt64());
1524 }
1525 }
1526 sbuf->setMode(ISerializer::ModeReserve);
1527
1528 sbuf->reserveInt64(1); // nb_item_family
1529 for (const auto& family : item_families)
1530 sbuf->reserve(family->name()); // ItemFamily->name
1531 sbuf->reserveInt64(item_families.size()); // ItemFamily->itemKind
1532
1533 sbuf->reserveArray(item_uids);
1534 sbuf->reserveArray(family_nb_items);
1535 sbuf->reserveArray(item_nb_dest_ranks);
1536 sbuf->reserveArray(item_dest_ranks);
1537
1538 sbuf->allocateBuffer();
1539 sbuf->setMode(ISerializer::ModePut);
1540
1541 sbuf->putInt64(item_families.size());
1542 for (const auto& family : item_families)
1543 sbuf->put(family->name()); // ItemFamily->name
1544 for (const auto& family : item_families)
1545 sbuf->putInteger(family->itemKind()); // ItemFamily->itemKind
1546
1547 sbuf->putArray(item_uids);
1548 sbuf->putArray(family_nb_items);
1549 sbuf->putArray(item_nb_dest_ranks);
1550 sbuf->putArray(item_dest_ranks);
1551 }
1552
1553 sd_exchange->processExchange();
1554
1555 for (Integer i = 0, is = recv_sub_domains.size(); i < is; ++i) {
1556 ISerializeMessage* comm = sd_exchange->messageToReceive(i);
1557 ISerializer* sbuf = comm->serializer();
1558 Int64 nb_families = sbuf->getInt64();
1559 StringUniqueArray item_family_names(nb_families);
1560 Int32UniqueArray item_family_kinds(nb_families);
1561 for (auto& family_name : item_family_names)
1562 sbuf->get(family_name); // ItemFamily->name
1563 for (auto& family_kind : item_family_kinds)
1564 family_kind = sbuf->getInteger(); // ItemFamily->itemKind
1565 sbuf->getArray(item_uids);
1566 sbuf->getArray(family_nb_items);
1567 sbuf->getArray(item_nb_dest_ranks);
1568 sbuf->getArray(item_dest_ranks);
1569 Integer item_uid_index = 0;
1570 Integer item_nb_dest_rank_index = 0;
1571 Integer item_dest_rank_index = 0;
1572 for (int family_index = 0; family_index < nb_families; ++family_index) {
1573 IItemFamily* family = m_mesh->findItemFamily(eItemKind(item_family_kinds[family_index]), item_family_names[family_index], false);
1574 Int64ArrayView family_item_uids = item_uids.subView(item_uid_index, family_nb_items[family_index]);
1575 Int32UniqueArray item_lids(family_item_uids.size());
1576 family->itemsUniqueIdToLocalId(item_lids, family_item_uids, true);
1577 for (const auto& item_lid : item_lids) {
1578 auto sub_view = item_dest_ranks.subView(item_dest_rank_index, item_nb_dest_ranks[item_nb_dest_rank_index]);
1579 Int32 dest_rank = comm->destination().value();
1580 m_ghost_item_dest_ranks_map[dest_rank][family]->at(item_lid).addRange(sub_view);
1581 item_dest_rank_index += item_nb_dest_ranks[item_nb_dest_rank_index++];
1582 }
1583 item_uid_index += family_nb_items[family_index];
1584 }
1585 }
1586 // _checkSubItemsDestRanks();
1587}
1588
1589/*---------------------------------------------------------------------------*/
1590/*---------------------------------------------------------------------------*/
1591
1592Integer MeshExchange::
1593_getSubdomainIndexInCommunicatingRanks(Integer rank, Int32ConstArrayView communicating_ranks)
1594{
1595 Integer i = 0;
1596 while (communicating_ranks[i] != rank) {
1597 ++i;
1598 }
1599 return i;
1600}
1601
1602/*---------------------------------------------------------------------------*/
1603/*---------------------------------------------------------------------------*/
1604
1605ISubDomain* MeshExchange::
1606subDomain() const
1607{
1608 return m_mesh->subDomain();
1609}
1610
1611/*---------------------------------------------------------------------------*/
1612/*---------------------------------------------------------------------------*/
1613
1614} // End namespace Arcane::mesh
1615
1616/*---------------------------------------------------------------------------*/
1617/*---------------------------------------------------------------------------*/
#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:83
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:451
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
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:482
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
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:127
UniqueArray< String > StringUniqueArray
Dynamic 1D array of strings.
Definition UtilsTypes.h:359
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
std::int32_t Int32
Signed integer type of 32 bits.