Arcane  v4.1.1.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
ConstituentItemVectorImpl.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* ConstituentItemVectorImpl.cc (C) 2000-2025 */
9/* */
10/* Implémentation de 'IConstituentItemVectorImpl'. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/internal/ConstituentItemVectorImpl.h"
15
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/FatalErrorException.h"
18
19#include "arcane/core/materials/IMeshMaterialMng.h"
21#include "arcane/core/materials/internal/IMeshComponentInternal.h"
22#include "arcane/core/materials/internal/IMeshMaterialMngInternal.h"
23
24#include "arcane/accelerator/core/RunQueue.h"
25#include "arcane/accelerator/RunCommandLoop.h"
26#include "arcane/accelerator/Reduce.h"
27#include "arcane/accelerator/Partitioner.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::Materials
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39ConstituentItemVectorImpl::
40ConstituentItemVectorImpl(IMeshComponent* component)
41: m_material_mng(component->materialMng())
42, m_component(component)
43, m_matvar_indexes(platform::getDefaultDataAllocator())
44, m_items_local_id(platform::getDefaultDataAllocator())
45, m_part_data(std::make_unique<MeshComponentPartData>(component, String()))
46, m_recompute_part_data_functor(this, &ConstituentItemVectorImpl::_recomputePartData)
47{
48 Int32 level = -1;
49 if (component->isMaterial())
50 level = LEVEL_MATERIAL;
51 else if (component->isEnvironment())
52 level = LEVEL_ENVIRONMENT;
53 else
54 ARCANE_FATAL("Bad internal type of component");
55 m_component_shared_info = m_material_mng->_internalApi()->componentItemSharedInfo(level);
56 m_constituent_list = std::make_unique<ConstituentItemLocalIdList>(m_component_shared_info, String());
57 m_part_data->setRecomputeFunctor(&m_recompute_part_data_functor);
58}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63ConstituentItemVectorImpl::
64ConstituentItemVectorImpl(const ComponentItemVectorView& rhs)
65: ConstituentItemVectorImpl(rhs.component())
66{
67 RunQueue& queue = m_material_mng->_internalApi()->runQueue();
68 m_constituent_list->copy(rhs._constituentItemListView());
69 m_matvar_indexes.copy(rhs._matvarIndexes());
70 m_items_local_id.copy(rhs._internalLocalIds());
71 m_part_data->_setFromMatVarIndexes(rhs._matvarIndexes(), queue);
72}
73
74/*---------------------------------------------------------------------------*/
75/*---------------------------------------------------------------------------*/
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79/*!
80 * \brief Helper pour positionner les entités du vecteur.
81 */
83{
84 public:
85
86 explicit SetItemHelper(bool use_new_impl)
87 : m_use_new_impl(use_new_impl)
88 {}
89
90 public:
91
92 template <typename ConstituentGetterLambda>
93 void setItems(ConstituentItemVectorImpl* vector_impl,
94 ConstituentGetterLambda constituent_getter_lambda,
95 SmallSpan<const Int32> local_ids, RunQueue& queue);
96
97 private:
98
99 bool m_use_new_impl = true;
100};
101
102/*---------------------------------------------------------------------------*/
103/*---------------------------------------------------------------------------*/
104
105template <typename ConstituentGetterLambda> void
106ConstituentItemVectorImpl::SetItemHelper::
107setItems(ConstituentItemVectorImpl* vector_impl, ConstituentGetterLambda constituent_getter_lambda,
108 SmallSpan<const Int32> local_ids, RunQueue& queue)
109{
110 SmallSpan<ConstituentItemIndex> item_indexes = vector_impl->m_constituent_list->_mutableItemIndexList();
111 SmallSpan<MatVarIndex> matvar_indexes = vector_impl->m_matvar_indexes.smallSpan();
112 SmallSpan<Int32> items_local_id = vector_impl->m_items_local_id.smallSpan();
113 AllEnvCellVectorView all_env_cell_view = vector_impl->m_material_mng->view(local_ids);
114 const bool is_env = vector_impl->m_component->isEnvironment();
115 const Int32 component_id = vector_impl->m_component->id();
116
117 const Int32 nb_pure = vector_impl->m_nb_pure;
118
119 Int32 pure_index = 0;
120 Int32 impure_index = nb_pure;
121
122 const Int32 nb_id = local_ids.size();
123
124 // Pas besoin de conserver les informations pour les mailles pour lesquelles
125 // le constituant est absent.
126 auto setter_unselected = [=] ARCCORE_HOST_DEVICE(Int32, Int32) {
127 };
128 auto generic_setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index, ComponentCell cc) {
129 MatVarIndex idx = cc._varIndex();
130 ConstituentItemIndex cii = cc._constituentItemIndex();
131 item_indexes[index] = cii;
132 matvar_indexes[index] = idx;
133 items_local_id[index] = cc.globalCellId();
134 };
135
136 // Implémentation utilisant l'API accélérateur
137 if (m_use_new_impl) {
138 // Lambda pour sélectionner les mailles pures
139 auto select_pure = [=] ARCCORE_HOST_DEVICE(Int32 index) {
140 ComponentCell cc = constituent_getter_lambda(index);
141 if (cc.null())
142 return false;
143 return (cc._varIndex().arrayIndex() == 0);
144 };
145 // Lambda pour sélectionner les mailles impures
146 auto select_impure = [=] ARCCORE_HOST_DEVICE(Int32 index) {
147 ComponentCell cc = constituent_getter_lambda(index);
148 if (cc.null())
149 return false;
150 return (cc._varIndex().arrayIndex() != 0);
151 };
152 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 output_index) {
153 ComponentCell cc = constituent_getter_lambda(index);
154 if (!cc.null())
155 generic_setter_lambda(output_index, cc);
156 };
157 auto setter_pure = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 output_index) {
158 setter_lambda(index, output_index);
159 };
160 auto setter_impure = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 output_index) {
161 setter_lambda(index, output_index + nb_pure);
162 };
163 Arcane::Accelerator::GenericPartitioner generic_partitioner(queue);
164 generic_partitioner.applyWithIndex(nb_id, setter_pure, setter_impure, setter_unselected,
165 select_pure, select_impure, A_FUNCINFO);
166 //SmallSpan<const Int32> nb_parts = generic_partitioner.nbParts();
167 //std::cout << "NB_PART=" << nb_parts[0] << " " << nb_parts[1] << "\n";
168 }
169 else {
170 // Ancien mécanisme qui n'utilise pas l'API accélérateur
171 if (is_env) {
172 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
173 AllEnvCell all_env_cell = *iallenvcell;
174 for (EnvCell ec : all_env_cell.subEnvItems()) {
175 if (ec.componentId() == component_id) {
176 MatVarIndex idx = ec._varIndex();
177 ConstituentItemIndex cii = ec._constituentItemIndex();
178 Int32& base_index = (idx.arrayIndex() == 0) ? pure_index : impure_index;
179 item_indexes[base_index] = cii;
180 matvar_indexes[base_index] = idx;
181 items_local_id[base_index] = all_env_cell.globalCellId();
182 ++base_index;
183 }
184 }
185 }
186 }
187 else {
188 // Filtre les matériaux correspondants aux local_ids
189 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
190 AllEnvCell all_env_cell = *iallenvcell;
191 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
192 for (MatCell mc : env_cell.subMatItems()) {
193 if (mc.componentId() == component_id) {
194 MatVarIndex idx = mc._varIndex();
195 ConstituentItemIndex cii = mc._constituentItemIndex();
196 Int32& base_index = (idx.arrayIndex() == 0) ? pure_index : impure_index;
197 item_indexes[base_index] = cii;
198 matvar_indexes[base_index] = idx;
199 items_local_id[base_index] = all_env_cell.globalCellId();
200 ++base_index;
201 }
202 }
203 }
204 }
205 }
206 }
207}
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211/*!
212 * \brief Positionne les entités du vecteur.
213 *
214 * Les entités du vecteur seront les entités de numéro locaux localId() et
215 * qui appartiennent à notre matériau ou notre milieu.
216 */
217void ConstituentItemVectorImpl::
218_setItems(SmallSpan<const Int32> local_ids)
219{
220 const bool do_new_impl = m_material_mng->_internalApi()->isUseAcceleratorForConstituentItemVector();
221
222 Accelerator::eExecutionPolicy exec_policy = m_component->specificExecutionPolicy();
223 RunQueue queue = m_material_mng->_internalApi()->runQueue(exec_policy);
224
225 if (do_new_impl)
226 _computeNbPureAndImpure(local_ids, queue);
227 else
228 _computeNbPureAndImpureLegacy(local_ids);
229
230 const Int32 nb_pure = m_nb_pure;
231 const Int32 nb_impure = m_nb_impure;
232 const Int32 total_nb_pure_and_impure = nb_pure + nb_impure;
233
234 // Tableau qui contiendra les indices des mailles pures et partielles.
235 // La première partie de 0 à nb_pure contiendra la partie pure.
236 // La seconde partie de nb_pure à (nb_pure+nb_impure) contiendra les mailles partielles.
237 // A noter que (nb_pure + nb_impure) peut être différent de local_ids.size()
238 // si certaines mailles de \a local_ids n'ont pas le constituant.
239 m_constituent_list->resize(total_nb_pure_and_impure);
240
241 // TODO: Ne pas remettre à jour systématiquement les
242 // 'm_items_local_id' mais ne le faire qu'à la demande
243 // car ils ne sont pas utilisés souvent.
244
245 m_matvar_indexes.resize(total_nb_pure_and_impure);
246 m_items_local_id.resize(total_nb_pure_and_impure);
247
248 const bool is_env = m_component->isEnvironment();
249 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
250 const Int32 component_id = m_component->id();
251
252 // Lambda pour récupérer le milieu associé à la maille
253 auto env_component_getter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> ComponentCell {
254 AllEnvCell all_env_cell = all_env_cell_view[index];
255 for (EnvCell ec : all_env_cell.subEnvItems()) {
256 if (ec.componentId() == component_id)
257 return ec;
258 }
259 return {};
260 };
261
262 // Lambda pour récupérer le matériau associé à la maille
263 auto mat_component_getter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> ComponentCell {
264 AllEnvCell all_env_cell = all_env_cell_view[index];
265 for (EnvCell ec : all_env_cell.subEnvItems()) {
266 for (MatCell mc : ec.subMatItems())
267 if (mc.componentId() == component_id)
268 return mc;
269 }
270 return {};
271 };
272
273 {
274 SetItemHelper helper(do_new_impl);
275 if (is_env)
276 helper.setItems(this, env_component_getter_lambda, local_ids, queue);
277 else
278 helper.setItems(this, mat_component_getter_lambda, local_ids, queue);
279 }
280
281 // Mise à jour de MeshComponentPartData
282 const bool do_lazy_evaluation = true;
283 if (do_lazy_evaluation)
284 m_part_data->setNeedRecompute();
285 else
286 _recomputePartData();
287}
288
289/*---------------------------------------------------------------------------*/
290/*---------------------------------------------------------------------------*/
291
292void ConstituentItemVectorImpl::
293_computeNbPureAndImpure(SmallSpan<const Int32> local_ids, RunQueue& queue)
294{
295 IMeshComponent* component = m_component;
296 const bool is_env = component->isEnvironment();
297 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
298 const Int32 component_id = m_component->id();
299
300 auto command = makeCommand(queue);
301 Accelerator::ReducerSum2<Int32> nb_pure(command);
302 Accelerator::ReducerSum2<Int32> nb_impure(command);
303
304 // Calcule le nombre de mailles pures et partielles
305 if (is_env) {
306 command << RUNCOMMAND_MAT_ENUMERATE(AllEnvCell, all_env_cell, all_env_cell_view, nb_pure, nb_impure)
307 {
308 for (EnvCell ec : all_env_cell.subEnvItems()) {
309 if (ec.componentId() == component_id) {
310 MatVarIndex idx = ec._varIndex();
311 if (idx.arrayIndex() == 0)
312 nb_pure.combine(1);
313 else
314 nb_impure.combine(1);
315 }
316 }
317 };
318 }
319 else {
320 command << RUNCOMMAND_MAT_ENUMERATE(AllEnvCell, all_env_cell, all_env_cell_view, nb_pure, nb_impure)
321 {
322 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
323 for (MatCell mc : env_cell.subMatItems()) {
324 if (mc.componentId() == component_id) {
325 MatVarIndex idx = mc._varIndex();
326 if (idx.arrayIndex() == 0)
327 nb_pure.combine(1);
328 else
329 nb_impure.combine(1);
330 }
331 }
332 }
333 };
334 }
335
336 m_nb_pure = nb_pure.reducedValue();
337 m_nb_impure = nb_impure.reducedValue();
338}
339
340/*---------------------------------------------------------------------------*/
341/*---------------------------------------------------------------------------*/
342/*!
343 * \brief Calcul du nombre de mailles pures et impures sans API accélérateur.
344 */
345void ConstituentItemVectorImpl::
346_computeNbPureAndImpureLegacy(SmallSpan<const Int32> local_ids)
347{
348 IMeshComponent* component = m_component;
349 const bool is_env = component->isEnvironment();
350 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
351 const Int32 component_id = m_component->id();
352
353 Int32 nb_pure = 0;
354 Int32 nb_impure = 0;
355
356 // Calcule le nombre de mailles pures et partielles
357 if (is_env) {
358 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
359 AllEnvCell all_env_cell = *iallenvcell;
360 for (EnvCell ec : all_env_cell.subEnvItems()) {
361 if (ec.componentId() == component_id) {
362 MatVarIndex idx = ec._varIndex();
363 if (idx.arrayIndex() == 0)
364 ++nb_pure;
365 else
366 ++nb_impure;
367 }
368 }
369 }
370 }
371 else {
372 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
373 AllEnvCell all_env_cell = *iallenvcell;
374 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
375 for (MatCell mc : env_cell.subMatItems()) {
376 if (mc.componentId() == component_id) {
377 MatVarIndex idx = mc._varIndex();
378 if (idx.arrayIndex() == 0)
379 ++nb_pure;
380 else
381 ++nb_impure;
382 }
383 }
384 }
385 }
386 }
387
388 m_nb_pure = nb_pure;
389 m_nb_impure = nb_impure;
390}
391
392/*---------------------------------------------------------------------------*/
393/*---------------------------------------------------------------------------*/
394
395void ConstituentItemVectorImpl::
396_recomputePartData()
397{
398 // Mise à jour de MeshComponentPartData
399 auto mvi_pure_view = m_matvar_indexes.subView(0, m_nb_pure);
400 auto mvi_impure_view = m_matvar_indexes.subView(m_nb_pure, m_nb_impure);
401 m_part_data->_setFromMatVarIndexes(mvi_pure_view, mvi_impure_view);
402}
403
404/*---------------------------------------------------------------------------*/
405/*---------------------------------------------------------------------------*/
406
407ComponentItemVectorView ConstituentItemVectorImpl::
408_view() const
409{
410 return { m_component, m_matvar_indexes,
411 m_constituent_list->view(), m_items_local_id };
412}
413
414/*---------------------------------------------------------------------------*/
415/*---------------------------------------------------------------------------*/
416
417} // End namespace Arcane::Materials
418
419/*---------------------------------------------------------------------------*/
420/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour gérer les énumérations des matériaux et milieux sur les accélérateurs.
#define RUNCOMMAND_MAT_ENUMERATE(ConstituentItemNameType, iter_name, env_or_mat_container,...)
Macro pour itérer sur un matériau ou un milieu.
__host__ __device__ CellLocalId globalCellId() const
localId() de la maille globale
__host__ __device__ bool null() const
Indique s'il s'agit de la maille nulle.
Interface d'un composant (matériau ou milieu) d'un maillage.
Représente un index sur les variables matériaux et milieux.
constexpr __host__ __device__ Int32 arrayIndex() const
Retourne l'indice du tableau de valeur dans la liste des variables.
Vue d'un tableau d'éléments de type T.
Definition Span.h:801
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:325
#define ENUMERATE_ALLENVCELL(iname,...)
Macro pour itérer sur toutes les mailles AllEnvCell d'un groupe.
RunCommand makeCommand(const RunQueue &run_queue)
Créé une commande associée à la file run_queue.
Active toujours les traces dans les parties Arcane concernant les matériaux.
IMemoryAllocator * getDefaultDataAllocator()
Allocateur par défaut pour les données.
std::int32_t Int32
Type entier signé sur 32 bits.