Arcane  4.1.11.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ExtraGhostParticlesBuilder.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/* ExtraGhostParticlesBuilder.cc (C) 2000-2024 */
9/* */
10/* Construction of extra ghost meshes. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/ExtraGhostParticlesBuilder.h"
15#include "arcane/mesh/DynamicMesh.h"
16
17#include "arcane/utils/ScopedPtr.h"
18
19#include "arcane/core/IExtraGhostParticlesBuilder.h"
20#include "arcane/core/IParallelExchanger.h"
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/ISerializeMessage.h"
23#include "arcane/core/SerializeBuffer.h"
24#include "arcane/core/ParallelMngUtils.h"
25
26#include "arcane/mesh/ParticleFamily.h"
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane::mesh
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37ExtraGhostParticlesBuilder::
38ExtraGhostParticlesBuilder(DynamicMesh* mesh)
39: TraceAccessor(mesh->traceMng())
40, m_mesh(mesh)
41{
42}
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47void ExtraGhostParticlesBuilder::
48addExtraGhostParticlesBuilder(IExtraGhostParticlesBuilder* builder)
49{
50 if (m_builders.contains(builder))
51 ARCANE_FATAL("Instance {0} is already registered", builder);
52 m_builders.add(builder);
53}
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
57
58void ExtraGhostParticlesBuilder::
59removeExtraGhostParticlesBuilder(IExtraGhostParticlesBuilder* builder)
60{
61 auto iter_begin = m_builders.begin();
62 auto iter_end = m_builders.end();
63 auto x = std::find(iter_begin, iter_end, builder);
64 if (x == iter_end)
65 ARCANE_FATAL("Instance {0} is not registered", builder);
66 m_builders.remove(x - iter_begin);
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72bool ExtraGhostParticlesBuilder::
73hasBuilder() const
74{
75 return !m_builders.empty();
76}
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80
81void ExtraGhostParticlesBuilder::
82computeExtraGhostParticles()
83{
84 const size_t nb_builder = m_builders.size();
85
86 if (nb_builder == 0)
87 return;
88
89 info() << "Compute extra ghost particles";
90
91 for (IExtraGhostParticlesBuilder* v : m_builders) {
92 // Calculate extra particles to send
93 v->computeExtraParticlesToSend();
94 }
95
96 for (IItemFamilyCollection::Enumerator i(m_mesh->itemFamilies()); ++i;) {
97 IItemFamily* family = *i;
98 if (family->itemKind() != IK_Particle)
99 continue;
100 ParticleFamily* particle_family = ARCANE_CHECK_POINTER(dynamic_cast<ParticleFamily*>(family));
101 if (particle_family && particle_family->getEnableGhostItems() == true) {
102 _computeForFamily(particle_family);
103 }
104 }
105}
106
107/*---------------------------------------------------------------------------*/
108/*---------------------------------------------------------------------------*/
109
110void ExtraGhostParticlesBuilder::
111_computeForFamily(ParticleFamily* particle_family)
112{
113 IParallelMng* pm = particle_family->itemFamily()->parallelMng();
114 const Int32 nsd = pm->commSize();
115
116 auto exchanger{ ParallelMngUtils::createExchangerRef(pm) };
117
118 // Construction of entities to send
119 UniqueArray<std::set<Integer>> to_sends(nsd);
120
121 // Initialization of the data exchanger
122 for (Integer isd = 0; isd < nsd; ++isd) {
123 std::set<Integer>& particle_set = to_sends[isd];
124 for (IExtraGhostParticlesBuilder* builder : m_builders) {
125 Int32ConstArrayView extra_particles = builder->extraParticlesToSend(particle_family->name(), isd);
126 // We sort the lids to send to avoid duplicates
127 for (Integer j = 0, size = extra_particles.size(); j < size; ++j)
128 particle_set.insert(extra_particles[j]);
129 }
130 if (!particle_set.empty())
131 exchanger->addSender(isd);
132 }
133 exchanger->initializeCommunicationsMessages();
134
135 ItemInternalList items_internal(particle_family->itemsInternal());
136 for (Integer i = 0, ns = exchanger->nbSender(); i < ns; ++i) {
137 ISerializeMessage* comm = exchanger->messageToSend(i);
138 const Int32 rank = comm->destination().value();
139 //ISerializer* s = comm->serializer();
140 const std::set<Integer>& particle_set = to_sends[rank];
141 Int32UniqueArray dest_items_local_id(particle_set.size());
142 std::copy(std::begin(particle_set), std::end(particle_set), std::begin(dest_items_local_id));
143 //particle_family->serializeParticles(s, items_to_send);
144
145 Int64 nb_item = particle_set.size();
146 Int64UniqueArray dest_items_unique_id(nb_item);
147 for (Integer z = 0; z < nb_item; ++z) {
148 ItemInternal* item = items_internal[dest_items_local_id[z]];
149 dest_items_unique_id[z] = item->uniqueId().asInt64();
150 }
151
152 ISerializer* isbuf = comm->serializer();
153 SerializeBuffer* sbuf = dynamic_cast<SerializeBuffer*>(isbuf);
154 if (!sbuf)
155 ARCANE_FATAL("buffer has to have type 'SerializeBuffer'");
156
157 // Saves the uids of the meshes where the particles are located
158 // It is possible that a particle does not belong to a mesh.
159 Int64UniqueArray particles_cell_uid(nb_item);
160 for (Integer z = 0; z < nb_item; ++z) {
161 Particle item(items_internal[dest_items_local_id[z]]);
162 bool has_cell = item.hasCell();
163 particles_cell_uid[z] = (has_cell) ? item.cell().uniqueId() : NULL_ITEM_UNIQUE_ID;
164 }
165
166 // Reserves memory for serialization
167 sbuf->setMode(ISerializer::ModeReserve);
168 sbuf->reserve(DT_Int64, 1); // For the number of particles
169 sbuf->reserveArray(dest_items_unique_id); // For the uniqueId() of the particles. NOTE: To be deleted
170 sbuf->reserveArray(particles_cell_uid); // For the uniqueId() of the meshes where the particles are located
171
172 sbuf->allocateBuffer();
173 sbuf->setMode(ISerializer::ModePut);
174
175 sbuf->putInt64(nb_item);
176 sbuf->putArray(dest_items_unique_id);
177 sbuf->putArray(particles_cell_uid);
178 }
179 exchanger->processExchange();
180
181 Int64UniqueArray particles_uid;
182 Int64UniqueArray cells_unique_id;
183 Int32UniqueArray cells_local_id;
184 Int32UniqueArray particles_owner;
185 IItemFamily* cell_family = m_mesh->cellFamily();
186 CellInfoListView internal_cells(cell_family);
187
188 // Reception of particles
189 for (Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
190 ISerializeMessage* sm = exchanger->messageToReceive(i);
191 ISerializer* sbuf = sm->serializer();
192 //particle_family->addParticles(s);
193
194 Int64 nb_item = sbuf->getInt64();
195 sbuf->getArray(particles_uid);
196 sbuf->getArray(cells_unique_id);
197 cells_local_id.resize(nb_item);
198 Int32UniqueArray particles_local_id(nb_item);
199
200 cell_family->itemsUniqueIdToLocalId(cells_local_id, cells_unique_id, true);
201 particles_owner.resize(nb_item);
202 for (Integer zz = 0; zz < nb_item; ++zz) {
203 Int32 cell_lid = cells_local_id[zz];
204 Cell c = internal_cells[cell_lid];
205 particles_owner[zz] = c.owner();
206 }
207
208 particle_family->addParticles2(particles_uid, particles_owner, particles_local_id);
209 particle_family->endUpdate();
210 // IMPORTANT: it must be done here because it can change via endUpdate()
211 ItemInternalList internal_particles(particle_family->itemsInternal());
212 for (Integer zz = 0; zz < nb_item; ++zz) {
213 Particle p = internal_particles[particles_local_id[zz]];
214 Int32 cell_lid = cells_local_id[zz];
215 if (cell_lid != NULL_ITEM_LOCAL_ID) {
216 Cell c = internal_cells[cell_lid];
217 particle_family->setParticleCell(p, c);
218 }
219 else
220 particle_family->setParticleCell(p, Cell());
221 }
222 }
223}
224
225/*---------------------------------------------------------------------------*/
226/*---------------------------------------------------------------------------*/
227
228} // End namespace Arcane::mesh
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Implementation of a mesh.
Definition DynamicMesh.h:98
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:339
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:482
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:341
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52