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