Arcane  v3.16.3.0
Documentation développeur
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"
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/*---------------------------------------------------------------------------*/
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();
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/*---------------------------------------------------------------------------*/
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
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/*---------------------------------------------------------------------------*/
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 fonctions pour gérer les synchronisations sur les accélérateurs.
Types et macros pour gérer les boucles sur les accélérateurs.
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.
Algorithme générique de partitionnement d'une liste.
Classe pour effectuer une réduction 'somme'.
Definition Reduce.h:750
File d'exécution pour un accélérateur.
SmallSpan< const T > smallSpan() const
Vue immutable sur ce tableau.
Vue sur une liste de mailles avec infos sur les milieux.
Maille arcane avec info matériaux et milieux.
__host__ __device__ CellEnvCellEnumerator subEnvItems() const
Enumérateur sur les mailles milieux de cette maille.
Vue sur un vecteur sur les entités d'un composant.
Index d'une entité constituant dans la liste des entités constituants.
Implémentation de ComponentItemVector.
void _computeNbPureAndImpureLegacy(SmallSpan< const Int32 > local_ids)
Calcul du nombre de mailles pures et impures sans API accélérateur.
__host__ __device__ CellLocalId globalCellId() const
localId() de la maille globale
__host__ __device__ bool null() const
Indique s'il s'agit de la maille nulle.
__host__ __device__ ConstituentItemIndex _constituentItemIndex() const
__host__ __device__ MatVarIndex _varIndex() const
Maille arcane d'un milieu.
Interface d'un composant (matériau ou milieu) d'un maillage.
virtual Int32 id() const =0
Identifiant du composant.
virtual bool isEnvironment() const =0
Vrai si le composant est un milieu.
virtual AllEnvCellVectorView view(const CellGroup &cells)=0
Vue sur les mailles milieux correspondant au groupe cells.
Représente un matériau d'une maille multi-matériau.
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.
Données d'une partie (pure ou partielle) d'un constituant.
Vue d'un tableau d'éléments de type T.
Definition Span.h:673
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:212
#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.
eExecutionPolicy
Politique d'exécution pour un Runner.
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.