Arcane  v3.14.10.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-2024 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-2024 */
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/*---------------------------------------------------------------------------*/
79/*!
80 * \brief Helper pour positionner les entités du vecteur.
81 */
83{
84 public:
85
86 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 RunQueue queue = m_material_mng->_internalApi()->runQueue();
221
222 _computeNbPureAndImpure(local_ids, queue);
223
224 const Int32 nb_pure = m_nb_pure;
225 const Int32 nb_impure = m_nb_impure;
226 const Int32 total_nb_pure_and_impure = nb_pure + nb_impure;
227
228 // Tableau qui contiendra les indices des mailles pures et partielles.
229 // La première partie de 0 à nb_pure contiendra la partie pure.
230 // La seconde partie de nb_pure à (nb_pure+nb_impure) contiendra les mailles partielles
231 // A noter que (nb_pure + nb_impure) peut être différent de local_ids.size()
232 // si certaines mailles de \a local_ids n'ont pas le constituant.
233 m_constituent_list->resize(total_nb_pure_and_impure);
234
235 // TODO: Ne pas remettre à jour systématiquement les
236 // 'm_items_local_id' mais ne le faire qu'à la demande
237 // car ils ne sont pas utilisés souvent.
238
239 m_matvar_indexes.resize(total_nb_pure_and_impure);
240 m_items_local_id.resize(total_nb_pure_and_impure);
241
242 const bool is_env = m_component->isEnvironment();
243 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
244 const Int32 component_id = m_component->id();
245
246 // Lambda pour récupérer le milieu associé à la maille
247 auto env_component_getter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> ComponentCell {
248 AllEnvCell all_env_cell = all_env_cell_view[index];
249 for (EnvCell ec : all_env_cell.subEnvItems()) {
250 if (ec.componentId() == component_id)
251 return ec;
252 }
253 return {};
254 };
255
256 // Lambda pour récupérer le matériau associé à la maille
257 auto mat_component_getter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> ComponentCell {
258 AllEnvCell all_env_cell = all_env_cell_view[index];
259 for (EnvCell ec : all_env_cell.subEnvItems()) {
260 for (MatCell mc : ec.subMatItems())
261 if (mc.componentId() == component_id)
262 return mc;
263 }
264 return {};
265 };
266
267 {
268 const bool do_new = m_material_mng->_internalApi()->isUseAcceleratorForConstituentItemVector();
269 SetItemHelper helper(do_new);
270 if (is_env)
271 helper.setItems(this, env_component_getter_lambda, local_ids, queue);
272 else
273 helper.setItems(this, mat_component_getter_lambda, local_ids, queue);
274 }
275
276 // Mise à jour de MeshComponentPartData
277 const bool do_lazy_evaluation = true;
278 if (do_lazy_evaluation)
279 m_part_data->setNeedRecompute();
280 else
281 _recomputePartData();
282}
283
284/*---------------------------------------------------------------------------*/
285/*---------------------------------------------------------------------------*/
286
287void ConstituentItemVectorImpl::
288_computeNbPureAndImpure(SmallSpan<const Int32> local_ids, RunQueue& queue)
289{
290 IMeshComponent* component = m_component;
291 const bool is_env = component->isEnvironment();
292 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
293 const Int32 component_id = m_component->id();
294
295 auto command = makeCommand(queue);
296 Accelerator::ReducerSum2<Int32> nb_pure(command);
297 Accelerator::ReducerSum2<Int32> nb_impure(command);
298
299 // Calcule le nombre de mailles pures et partielles
300 if (is_env) {
301 command << RUNCOMMAND_MAT_ENUMERATE(AllEnvCell, all_env_cell, all_env_cell_view, nb_pure, nb_impure)
302 {
303 for (EnvCell ec : all_env_cell.subEnvItems()) {
304 if (ec.componentId() == component_id) {
305 MatVarIndex idx = ec._varIndex();
306 if (idx.arrayIndex() == 0)
307 nb_pure.combine(1);
308 else
309 nb_impure.combine(1);
310 }
311 }
312 };
313 }
314 else {
315 command << RUNCOMMAND_MAT_ENUMERATE(AllEnvCell, all_env_cell, all_env_cell_view, nb_pure, nb_impure)
316 {
317 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
318 for (MatCell mc : env_cell.subMatItems()) {
319 if (mc.componentId() == component_id) {
320 MatVarIndex idx = mc._varIndex();
321 if (idx.arrayIndex() == 0)
322 nb_pure.combine(1);
323 else
324 nb_impure.combine(1);
325 }
326 }
327 }
328 };
329 }
330
331 m_nb_pure = nb_pure.reducedValue();
332 m_nb_impure = nb_impure.reducedValue();
333}
334
335/*---------------------------------------------------------------------------*/
336/*---------------------------------------------------------------------------*/
337
338void ConstituentItemVectorImpl::
339_recomputePartData()
340{
341 // Mise à jour de MeshComponentPartData
342 auto mvi_pure_view = m_matvar_indexes.subView(0, m_nb_pure);
343 auto mvi_impure_view = m_matvar_indexes.subView(m_nb_pure, m_nb_impure);
344 m_part_data->_setFromMatVarIndexes(mvi_pure_view, mvi_impure_view);
345}
346
347/*---------------------------------------------------------------------------*/
348/*---------------------------------------------------------------------------*/
349
350ComponentItemVectorView ConstituentItemVectorImpl::
351_view() const
352{
353 return { m_component, m_matvar_indexes,
354 m_constituent_list->view(), m_items_local_id };
355}
356
357/*---------------------------------------------------------------------------*/
358/*---------------------------------------------------------------------------*/
359
360} // End namespace Arcane::Materials
361
362/*---------------------------------------------------------------------------*/
363/*---------------------------------------------------------------------------*/
#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(MatItemNameType, iter_name, env_or_mat_vector,...)
Macro pour itérer sur un matériau ou un milieu.
Algorithme générique de partitionnement d'une liste.
File d'exécution pour un accélérateur.
Représente un composant d'une maille multi-matériau.
__host__ __device__ CellLocalId globalCellId() const
localId() de la maille globale
__host__ __device__ bool null() const
Indique s'il s'agit de la maille nulle.
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:670
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:209
#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.