Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ParticleFamily.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/* ParticleFamily.cc (C) 2000-2024 */
9/* */
10/* Particle family. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/ParticleFamily.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/PlatformUtils.h"
18
19#include "arcane/core/ISubDomain.h"
20#include "arcane/core/IMesh.h"
21#include "arcane/core/IVariableMng.h"
22#include "arcane/core/Properties.h"
23#include "arcane/core/ItemPrinter.h"
24
25#include "arcane/mesh/ItemsExchangeInfo2.h"
26#include "arcane/mesh/DynamicMesh.h"
27#include "arcane/mesh/ItemConnectivitySelector.h"
28#include "arcane/mesh/DynamicMeshKindInfos.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::mesh
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39ParticleFamily::
40ParticleFamily(IMesh* mesh, const String& name)
41: ItemFamily(mesh, IK_Particle, name)
42, m_particle_type_info(nullptr)
43, m_particle_shared_info(nullptr)
44, m_sub_domain_id(NULL_SUB_DOMAIN_ID)
45, m_enable_ghost_items(false)
46, m_cell_connectivity(nullptr)
47{
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53ParticleFamily::
54~ParticleFamily()
55{
56}
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61void ParticleFamily::
62build()
63{
64 ItemFamily::build();
65 ItemTypeMng* itm = m_mesh->itemTypeMng();
66 m_particle_type_info = itm->typeFromId(IT_NullType);
67 m_sub_domain_id = subDomain()->subDomainId();
68
69 // Temporary: to disable the hash table for uniqueId
70 if (!platform::getEnvironmentVariable("ARCANE_PARTICLE_NO_UNIQUE_ID_MAP").null()) {
71 pwarning() << "TEMPORARY: suppress particule uniqueId map";
72 setHasUniqueIdMap(false);
73 }
74 else {
75 bool has_unique_id_map = !m_properties->getBool("no-unique-id-map");
76 _setHasUniqueIdMap(has_unique_id_map);
77 }
78
79 m_cell_connectivity = new CellConnectivity(this, mesh()->cellFamily(), "ParticleCell");
80
81 _addConnectivitySelector(m_cell_connectivity);
82
83 _buildConnectivitySelectors();
84
85 // Pre-allocates a cell per particle.
86 m_cell_connectivity->setPreAllocatedSize(1);
87
88 _setSharedInfo();
89
90 auto network = m_mesh->itemFamilyNetwork();
91 if (network) {
92 network->addDependency(this, mesh()->cellFamily(), m_cell_connectivity->customConnectivity(), false);
93 }
94}
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
101inline void ParticleFamily::
102_initializeNewlyAllocatedParticle(ItemInternal* particle, Int64 uid)
103{
104 _allocateInfos(particle, uid, m_particle_shared_info);
105 m_cell_connectivity->addConnectedItem(ItemLocalId(particle), ItemLocalId(NULL_ITEM_LOCAL_ID));
106}
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
111inline ItemInternal* ParticleFamily::
112_allocParticle(Int64 uid, bool& need_alloc)
113{
114 ItemInternal* ii = _allocOne(uid, need_alloc);
115
116 if (!need_alloc)
117 ii->setUniqueId(uid);
118 else
119 _initializeNewlyAllocatedParticle(ii, uid);
120
121 // A particle always belongs to the sub-domain that created it
122 ii->setOwner(m_sub_domain_id, m_sub_domain_id);
123 return ii;
124}
125
126/*---------------------------------------------------------------------------*/
127/*---------------------------------------------------------------------------*/
128
129inline ItemInternal* ParticleFamily::
130_findOrAllocParticle(Int64 uid, bool& is_alloc)
131{
132 ItemInternal* ii = ItemFamily::_findOrAllocOne(uid, is_alloc);
133 if (is_alloc)
134 _initializeNewlyAllocatedParticle(ii, uid);
135 return ii;
136}
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
140
141ParticleVectorView ParticleFamily::
142addParticles(Int64ConstArrayView unique_ids, Int32ArrayView items)
143{
144 _addItems(unique_ids, items);
145 return view(items);
146}
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
151ParticleVectorView ParticleFamily::
152addParticles2(Int64ConstArrayView unique_ids,
153 Int32ConstArrayView owners,
154 Int32ArrayView items)
155{
156 addItems(unique_ids, owners, items);
157 return view(items);
158}
159
160/*---------------------------------------------------------------------------*/
161/*---------------------------------------------------------------------------*/
162
163void ParticleFamily::
164_setCell(ItemLocalId particle, ItemLocalId cell)
165{
166 m_cell_connectivity->replaceItem(particle, 0, cell);
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172ParticleVectorView ParticleFamily::
173addParticles(Int64ConstArrayView unique_ids,
174 Int32ConstArrayView cells_local_id,
175 Int32ArrayView items)
176{
177 _addItems(unique_ids, items);
178 Integer n = items.size();
179 for (Integer i = 0; i < n; ++i) {
180 _setCell(ItemLocalId(items[i]), ItemLocalId(cells_local_id[i]));
181 }
182
183 return view(items);
184}
185
186/*---------------------------------------------------------------------------*/
187/*---------------------------------------------------------------------------*/
188
189void ParticleFamily::
190setParticleCell(Particle particle, Cell new_cell)
191{
192 _setCell(particle, new_cell);
193 m_need_prepare_dump = true;
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
199void ParticleFamily::
200setParticlesCell(ParticleVectorView particles, CellVectorView new_cells)
201{
202 Int32ConstArrayView cell_ids = new_cells.localIds();
203 Int32ConstArrayView particle_ids = particles.localIds();
204 for (Integer i = 0, n = particle_ids.size(); i < n; ++i)
205 _setCell(ItemLocalId(particle_ids[i]), ItemLocalId(cell_ids[i]));
206 m_need_prepare_dump = true;
207}
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211
212void ParticleFamily::
213_addItems(Int64ConstArrayView unique_ids, Int32ArrayView items)
214{
215 Integer nb_item = unique_ids.size();
216 if (nb_item == 0)
217 return;
218 preAllocate(nb_item);
219
220 bool need_alloc = false;
221 for (Integer i = 0; i < nb_item; ++i) {
222 Int64 uid = unique_ids[i];
223 ItemInternal* ii = _allocParticle(uid, need_alloc);
224 items[i] = ii->localId();
225 }
226
227 m_need_prepare_dump = true;
228 _printInfos(nb_item);
229}
230
231/*---------------------------------------------------------------------------*/
232/*---------------------------------------------------------------------------*/
233
234void ParticleFamily::
235addItems(Int64ConstArrayView unique_ids, Int32ConstArrayView owners, Int32ArrayView items)
236{
237 Integer nb_item = unique_ids.size();
238 if (nb_item == 0)
239 return;
240 preAllocate(nb_item);
241 // The _findOrAlloc method requires the uniqueId hash map.
242 if (!hasUniqueIdMap())
243 ARCANE_FATAL("Can not add particles with owners when hasUniqueIdMap()==false family={0}",
244 name());
245
246 bool need_alloc = false;
247 for (Integer i = 0; i < nb_item; ++i) {
248 Int64 uid = unique_ids[i];
249 ItemInternal* ii = _findOrAllocParticle(uid, need_alloc);
250 ii->setOwner(owners[i], m_sub_domain_id);
251
252 items[i] = ii->localId();
253 }
254
255 m_need_prepare_dump = true;
256 _printInfos(nb_item);
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
262void ParticleFamily::
263exchangeParticles()
264{
265 ItemsExchangeInfo2 ex(this);
268 ex.prepareToSend();
269 ex.processExchange();
270 ex.removeSentItems();
273 endUpdate();
274 ex.readGroups();
275 ex.readVariables();
276}
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
281void ParticleFamily::
282_printInfos(Integer nb_added)
283{
284 ARCANE_UNUSED(nb_added);
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290void ParticleFamily::
291internalRemoveItems(Int32ConstArrayView local_ids, bool keep_ghost)
292{
293 ARCANE_UNUSED(keep_ghost);
294
295 InternalConnectivityPolicy policy = mesh()->_connectivityPolicy();
296
297 // Note that this loop is not useful for the moment if we
298 // are not using the new connectivities.
299 // It will be if we want to have inverse connectivities
300 // cell->particle.
301 bool want_nullify_cell = (policy != InternalConnectivityPolicy::Legacy);
302 ItemLocalId null_item_lid(NULL_ITEM_LOCAL_ID);
303
304 auto network = m_mesh->itemFamilyNetwork();
305 if (network) {
306 std::set<Int32> remove_lids;
307 if (want_nullify_cell) {
308 for (Integer i = 0, n = local_ids.size(); i < n; ++i) {
309 ItemLocalId lid(local_ids[i]);
310 m_cell_connectivity->replaceItem(lid, 0, null_item_lid);
311 remove_lids.insert(local_ids[i]);
312 }
313 }
314 for (auto parent_connectivity : m_mesh->itemFamilyNetwork()->getParentConnectivities(this)) {
315 //for (auto parent_connectivity : m_mesh->itemFamilyNetwork()->getParentRelations(this)) { // Should be getParentConnectivities, but because legacy connectivity cannot remove a connectivity with a Node as target, we need to restrain to Relations...
316 for (auto source_item : parent_connectivity->sourceFamily()->itemsInternal()) {
317 if (source_item->isSuppressed())
318 continue;
319 ConnectivityItemVector connectivity_accessor(parent_connectivity);
320 ENUMERATE_ITEM (connected_item, connectivity_accessor.connectedItems(ItemLocalId(source_item))) {
321 if (remove_lids.find(connected_item->localId()) != remove_lids.end()) {
322 parent_connectivity->removeConnectedItem(ItemLocalId(source_item), connected_item);
323 }
324 }
325 }
326 }
327 }
328 else {
329 if (want_nullify_cell) {
330 for (Integer i = 0, n = local_ids.size(); i < n; ++i) {
331 ItemLocalId lid(local_ids[i]);
332 m_cell_connectivity->replaceItem(lid, 0, null_item_lid);
333 }
334 }
335 }
336 _removeMany(local_ids);
337
338 m_need_prepare_dump = true;
339}
340
341/*---------------------------------------------------------------------------*/
342/*---------------------------------------------------------------------------*/
343
344void ParticleFamily::
345removeParticles(Int32ConstArrayView items_local_id)
346{
347 internalRemoveItems(items_local_id, false);
348}
349
350/*---------------------------------------------------------------------------*/
351/*---------------------------------------------------------------------------*/
352
353void ParticleFamily::
354prepareForDump()
355{
356 Integer nb_item = nbItem();
357 info(4) << "ParticleFamily::prepareForDump: " << name()
358 << " n=" << nb_item;
360}
361
362/*---------------------------------------------------------------------------*/
363/*---------------------------------------------------------------------------*/
364
365void ParticleFamily::
366readFromDump()
367{
369 // Updates the shared_info because it may change after a reload
370 _setSharedInfo();
371}
372
373/*---------------------------------------------------------------------------*/
374/*---------------------------------------------------------------------------*/
375
376void ParticleFamily::
377preAllocate(Integer nb_item)
378{
379 Integer nb_hash = itemsMap().nbBucket();
380 Integer wanted_size = 2 * (nb_item + nbItem());
381 if (nb_hash < wanted_size)
382 itemsMap().resize(wanted_size, true);
383}
384
385/*---------------------------------------------------------------------------*/
386/*---------------------------------------------------------------------------*/
387
388void ParticleFamily::
389setHasUniqueIdMap(bool v)
390{
391 _setHasUniqueIdMap(v);
392 m_properties->setBool("no-unique-id-map", !v);
393}
394
395/*---------------------------------------------------------------------------*/
396/*---------------------------------------------------------------------------*/
397
398bool ParticleFamily::
399hasUniqueIdMap() const
400{
401 return _infos().hasUniqueIdMap();
402}
403
404/*---------------------------------------------------------------------------*/
405/*---------------------------------------------------------------------------*/
406
407void ParticleFamily::
408_setSharedInfo()
409{
410 m_particle_shared_info = _findSharedInfo(m_particle_type_info);
411}
412
413/*---------------------------------------------------------------------------*/
414/*---------------------------------------------------------------------------*/
415
416void ParticleFamily::
417checkValidConnectivity()
418{
420}
421
422/*---------------------------------------------------------------------------*/
423/*---------------------------------------------------------------------------*/
424
425void ParticleFamily::
426removeNeedRemoveMarkedItems()
427{
428 if (getEnableGhostItems()) {
429 UniqueArray<Integer> lids_to_remove;
430 lids_to_remove.reserve(1000);
431
432 ItemInternalMap& particle_map = itemsMap();
433 particle_map.eachItem([&](Item item) {
434 Integer f = item.itemBase().flags();
435 if (f & ItemFlags::II_NeedRemove) {
436 f &= ~ItemFlags::II_NeedRemove;
437 item.mutableItemBase().setFlags(f);
438 lids_to_remove.add(item.localId());
439 }
440 });
441
442 info() << "Number of particles of family " << name() << " to remove: " << lids_to_remove.size();
443 if (lids_to_remove.size() > 0)
444 removeParticles(lids_to_remove);
445 }
446}
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
451} // End namespace Arcane::mesh
452
453/*---------------------------------------------------------------------------*/
454/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
Integer size() const
Number of elements in the vector.
constexpr Integer size() const noexcept
Returns the size of the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
Cell of a mesh.
Definition Item.h:1300
Manages the retrieval of connectivity information.
ItemVectorView connectedItems(ItemLocalId item)
Returns the entities connected to item.
constexpr Integer size() const noexcept
Number of elements in the array.
Int32 flags() const
Flags of the entity.
Int32 localId() const
Local number (in the subdomain) of the entity.
Flags for entity characteristics.
Definition ItemFlags.h:39
@ II_NeedRemove
The entity must be removed.
Definition ItemFlags.h:63
Internal structure of a mesh entity.
Index of an Item in a variable.
Definition ItemLocalId.h:42
Int32ConstArrayView localIds() const
Array of local IDs of entities.
Base class for a mesh element.
Definition Item.h:84
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
impl::ItemBase itemBase() const
Internal part of the entity.
Definition Item.h:383
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
void setFlags(Int32 f)
Sets the entity flags.
Particle.
Definition Item.h:1529
TraceMessage info() const
Flow for an information message.
1D data vector with value semantics (STL style).
IMesh * mesh() const override
Associated mesh.
void prepareForDump() override
Prepares data for dumping.
void checkValidConnectivity() override
Verification of the validity of internal structures concerning connectivity.
ItemVectorView view(Int32ConstArrayView local_ids) override
View on the entities.
void notifyItemsOwnerChanged() override
Notifies that the entities specific to the family's subdomain have been modified.
void readFromDump() override
Reads data from a dump.
void eachItem(const Lambda &lambda)
Template function to iterate over the instance's entities.
Information for exchanging entities of a given family and their characteristics.
void readAndAllocItems() override
After receiving messages, reads and creates the transferred entities.
void readVariables() override
After receiving messages, reads the variable values.
void removeSentItems() override
Deletes the sent entities.
void computeExchangeItems() override
Determines the list of entities to exchange.
void processExchange() override
Sends the exchange messages.
bool computeExchangeInfos() override
Determines the necessary information for the exchanges.
void prepareToSend() override
Prepares the sending structures.
void readGroups() override
After receiving messages, reads the groups.
Integer nbItem() const override
Number of entities.
String name() const override
Family name.
void endUpdate() override
Notifies the end of modification of the entity list.
bool getEnableGhostItems() const override
Retrieves the flag to manage ghost particles for the family.
ItemVectorViewT< Cell > CellVectorView
View over a vector of cells.
Definition ItemTypes.h:305
ItemVectorViewT< Particle > ParticleVectorView
View over a vector of particles.
Definition ItemTypes.h:310
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
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
@ IK_Particle
Particle mesh entity.
InternalConnectivityPolicy
Connectivity usage policy.
Definition ItemTypes.h:517
@ Legacy
Historical connectivities.
Definition ItemTypes.h:525