From 53fac2e35b4489e989e77cd0f87b1323ae0b9d4b Mon Sep 17 00:00:00 2001 From: Gilles GROSPELLIER Date: Thu, 22 Oct 2026 10:53:48 +0200 Subject: [PATCH 1/3] [arcane,mesh] Add support for particles with no cell in mesh loadbalance. --- arcane/src/arcane/mesh/MeshExchange.cc | 12 +++++++++--- arcane/src/arcane/mesh/MeshExchanger.cc | 2 +- arcane/src/arcane/mesh/UnstructuredMeshUtilities.cc | 7 ++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/arcane/src/arcane/mesh/MeshExchange.cc b/arcane/src/arcane/mesh/MeshExchange.cc index 0450f25785..751bf0f211 100644 --- a/arcane/src/arcane/mesh/MeshExchange.cc +++ b/arcane/src/arcane/mesh/MeshExchange.cc @@ -609,7 +609,10 @@ _computeItemsToSend(bool send_dof) if (particle_family && particle_family->getEnableGhostItems() == true) { ArrayView> to_send = _getItemsToSend(family); ENUMERATE_PARTICLE (iparticle, particle_family->allItems().own()) { - _addItemToSend(to_send, iparticle->localId(), iparticle->cell().localId(), use_itemfamily_network); + Cell cell = iparticle->cell(); + // Do not send the particle if it has no cell. + if (!cell.null()) + _addItemToSend(to_send, iparticle->localId(), cell.localId(), use_itemfamily_network); } } if (send_dof && family->itemKind() == IK_DoF) { @@ -1416,13 +1419,16 @@ _markRemovableParticles() { for (IItemFamily* family : m_mesh->itemFamilies()) { IParticleFamily* particle_family = family->toParticleFamily(); - if (particle_family && particle_family->getEnableGhostItems() == true) { + if (particle_family && particle_family->getEnableGhostItems()) { mesh::NewItemOwnerBuilder owner_builder; ENUMERATE_PARTICLE (iparticle, particle_family->allItems()) { Particle particle = *iparticle; Cell cell = owner_builder.connectedCellOfItem(particle); - particle.mutableItemBase().setFlags(cell.itemBase().flags()); + // NOTE GG: 10/2026. This code is very strange + // I think we should only modify some flags (II_NeedRemove?) + if (!cell.null()) + particle.mutableItemBase().setFlags(cell.itemBase().flags()); } } } diff --git a/arcane/src/arcane/mesh/MeshExchanger.cc b/arcane/src/arcane/mesh/MeshExchanger.cc index 149f3201db..bb3131ac93 100644 --- a/arcane/src/arcane/mesh/MeshExchanger.cc +++ b/arcane/src/arcane/mesh/MeshExchanger.cc @@ -240,7 +240,7 @@ computeExchangeInfos() // of ghost items, this list has already been determined during the call to // mesh_exchange.computeInfos(). IParticleFamily* particle_family = family->toParticleFamily(); - if (particle_family && particle_family->getEnableGhostItems() == false) + if (particle_family && !particle_family->getEnableGhostItems()) exchanger->computeExchangeItems(); else exchanger->setExchangeItems(mesh_exchange.getItemsToSend(family)); diff --git a/arcane/src/arcane/mesh/UnstructuredMeshUtilities.cc b/arcane/src/arcane/mesh/UnstructuredMeshUtilities.cc index 37084e53ec..fd6985bba2 100644 --- a/arcane/src/arcane/mesh/UnstructuredMeshUtilities.cc +++ b/arcane/src/arcane/mesh/UnstructuredMeshUtilities.cc @@ -169,7 +169,12 @@ changeOwnersFromCells() VariableItemInt32& particles_owner(family->itemsNewOwner()); ENUMERATE_PARTICLE (i_particle, family->allItems()) { Particle particle = *i_particle; - particles_owner[particle] = cells_owner[particle.cell()]; + Cell pcell = particle.cell(); + if (!pcell.null()) + particles_owner[particle] = cells_owner[pcell]; + else + // If the particle has no cell, its new owner is the current owner. + particles_owner[particle] = particle.owner(); } } From 41e6bfa95331c3aa025d2ea0bc47c0f8af3dcac9 Mon Sep 17 00:00:00 2001 From: Gilles GROSPELLIER Date: Thu, 22 Oct 2026 10:54:53 +0200 Subject: [PATCH 2/3] [arcane,tests] Add load-balance test for particles with no cell. --- arcane/src/arcane/tests/ParallelTesterModule.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/arcane/src/arcane/tests/ParallelTesterModule.cc b/arcane/src/arcane/tests/ParallelTesterModule.cc index 4fa900f90e..9c6487473f 100644 --- a/arcane/src/arcane/tests/ParallelTesterModule.cc +++ b/arcane/src/arcane/tests/ParallelTesterModule.cc @@ -174,8 +174,8 @@ class ParticleFamilyTester Integer particle_per_cell = 12; info() << " BuildParticleFamily increment=" << particle_per_cell << " nb_particle=" << m_family->nbItem(); - Int64UniqueArray uids; - Int32UniqueArray cells_lid; + UniqueArray uids; + UniqueArray cells_lid; IParallelMng* pm = m_family->parallelMng(); CellGroup own_cells = m_family->mesh()->ownCells(); Integer nb_own_cell = own_cells.size(); @@ -191,7 +191,14 @@ class ParticleFamilyTester ++first_uid; } } - + // To check load-balance with particles with no cells, make sure some + // particles have no cells. + { + Int32 nb_particle_to_add = uids.size(); + for (Int32 i = 0; i < nb_particle_to_add; ++i) + if ((i % 10) == 0) + cells_lid[i] = ItemLocalId{}; + } m_first_uid = m_first_uid + uid_increment * comm_size; info() << "Create " << uids.size() << " particles"; @@ -202,7 +209,7 @@ class ParticleFamilyTester m_family->partialEndUpdateVariable(m_values1.variable()); ENUMERATE_PARTICLE (ipart, particles) { Particle particle = *ipart; - m_values1[ipart] = (Real)(particle.uniqueId().asInt64()); + m_values1[ipart] = static_cast(particle.uniqueId().asInt64()); } m_family->endUpdate(); } From 1c8b86edc4e068505aa682f353a92e28c44762c8 Mon Sep 17 00:00:00 2001 From: Gilles Grospellier Date: Thu, 22 Oct 2026 14:12:21 +0200 Subject: [PATCH 3/3] [arcane,tests] Do not set particles without cell when using 'IItemFamilyNetwork'. The mesh exchanger using graph network does not support particles without cells. --- arcane/src/arcane/tests/ParallelTesterModule.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arcane/src/arcane/tests/ParallelTesterModule.cc b/arcane/src/arcane/tests/ParallelTesterModule.cc index 9c6487473f..17b1566dc6 100644 --- a/arcane/src/arcane/tests/ParallelTesterModule.cc +++ b/arcane/src/arcane/tests/ParallelTesterModule.cc @@ -5,7 +5,7 @@ // SPDX-License-Identifier: Apache-2.0 //----------------------------------------------------------------------------- /*---------------------------------------------------------------------------*/ -/* ParallelTesterModule.cc (C) 2000-2024 */ +/* ParallelTesterModule.cc (C) 2000-2026 */ /* */ /* Parallelism test module. */ /*---------------------------------------------------------------------------*/ @@ -193,7 +193,9 @@ class ParticleFamilyTester } // To check load-balance with particles with no cells, make sure some // particles have no cells. - { + // NOTE: Having particles without cells is not supported when using + // graph network. + if (!m_family->mesh()->itemFamilyNetwork()) { Int32 nb_particle_to_add = uids.size(); for (Int32 i = 0; i < nb_particle_to_add; ++i) if ((i % 10) == 0)