Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ConstituentItemVectorImpl.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/* ConstituentItemVectorImpl.cc (C) 2000-2025 */
9/* */
10/* Implementation of '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
84{
85 public:
86
87 explicit SetItemHelper(bool use_new_impl)
88 : m_use_new_impl(use_new_impl)
89 {}
90
91 public:
92
93 template <typename ConstituentGetterLambda>
94 void setItems(ConstituentItemVectorImpl* vector_impl,
95 ConstituentGetterLambda constituent_getter_lambda,
96 SmallSpan<const Int32> local_ids, RunQueue& queue);
97
98 private:
99
100 bool m_use_new_impl = true;
101};
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
106template <typename ConstituentGetterLambda> void
107ConstituentItemVectorImpl::SetItemHelper::
108setItems(ConstituentItemVectorImpl* vector_impl, ConstituentGetterLambda constituent_getter_lambda,
109 SmallSpan<const Int32> local_ids, RunQueue& queue)
110{
111 SmallSpan<ConstituentItemIndex> item_indexes = vector_impl->m_constituent_list->_mutableItemIndexList();
112 SmallSpan<MatVarIndex> matvar_indexes = vector_impl->m_matvar_indexes.smallSpan();
113 SmallSpan<Int32> items_local_id = vector_impl->m_items_local_id.smallSpan();
114 AllEnvCellVectorView all_env_cell_view = vector_impl->m_material_mng->view(local_ids);
115 const bool is_env = vector_impl->m_component->isEnvironment();
116 const Int32 component_id = vector_impl->m_component->id();
117
118 const Int32 nb_pure = vector_impl->m_nb_pure;
119
120 Int32 pure_index = 0;
121 Int32 impure_index = nb_pure;
122
123 const Int32 nb_id = local_ids.size();
124
125 // No need to keep information for cells where
126 // the constituent is absent.
127 auto setter_unselected = [=] ARCCORE_HOST_DEVICE(Int32, Int32) {
128 };
129 auto generic_setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index, ComponentCell cc) {
130 MatVarIndex idx = cc._varIndex();
132 item_indexes[index] = cii;
133 matvar_indexes[index] = idx;
134 items_local_id[index] = cc.globalCellId();
135 };
136
137 // Implementation using the accelerator API
138 if (m_use_new_impl) {
139 // Lambda to select pure cells
140 auto select_pure = [=] ARCCORE_HOST_DEVICE(Int32 index) {
141 ComponentCell cc = constituent_getter_lambda(index);
142 if (cc.null())
143 return false;
144 return (cc._varIndex().arrayIndex() == 0);
145 };
146 // Lambda to select impure cells
147 auto select_impure = [=] ARCCORE_HOST_DEVICE(Int32 index) {
148 ComponentCell cc = constituent_getter_lambda(index);
149 if (cc.null())
150 return false;
151 return (cc._varIndex().arrayIndex() != 0);
152 };
153 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 output_index) {
154 ComponentCell cc = constituent_getter_lambda(index);
155 if (!cc.null())
156 generic_setter_lambda(output_index, cc);
157 };
158 auto setter_pure = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 output_index) {
159 setter_lambda(index, output_index);
160 };
161 auto setter_impure = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 output_index) {
162 setter_lambda(index, output_index + nb_pure);
163 };
164 Arcane::Accelerator::GenericPartitioner generic_partitioner(queue);
165 generic_partitioner.applyWithIndex(nb_id, setter_pure, setter_impure, setter_unselected,
166 select_pure, select_impure, A_FUNCINFO);
167 //SmallSpan<const Int32> nb_parts = generic_partitioner.nbParts();
168 //std::cout << "NB_PART=" << nb_parts[0] << " " << nb_parts[1] << "\n";
169 }
170 else {
171 // Old mechanism that does not use the accelerator API
172 if (is_env) {
173 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
174 AllEnvCell all_env_cell = *iallenvcell;
175 for (EnvCell ec : all_env_cell.subEnvItems()) {
176 if (ec.componentId() == component_id) {
177 MatVarIndex idx = ec._varIndex();
178 ConstituentItemIndex cii = ec._constituentItemIndex();
179 Int32& base_index = (idx.arrayIndex() == 0) ? pure_index : impure_index;
180 item_indexes[base_index] = cii;
181 matvar_indexes[base_index] = idx;
182 items_local_id[base_index] = all_env_cell.globalCellId();
183 ++base_index;
184 }
185 }
186 }
187 }
188 else {
189 // Filters materials corresponding to local_ids
190 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
191 AllEnvCell all_env_cell = *iallenvcell;
192 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
193 for (MatCell mc : env_cell.subMatItems()) {
194 if (mc.componentId() == component_id) {
195 MatVarIndex idx = mc._varIndex();
196 ConstituentItemIndex cii = mc._constituentItemIndex();
197 Int32& base_index = (idx.arrayIndex() == 0) ? pure_index : impure_index;
198 item_indexes[base_index] = cii;
199 matvar_indexes[base_index] = idx;
200 items_local_id[base_index] = all_env_cell.globalCellId();
201 ++base_index;
202 }
203 }
204 }
205 }
206 }
207 }
208}
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
219void ConstituentItemVectorImpl::
220_setItems(SmallSpan<const Int32> local_ids)
221{
222 const bool do_new_impl = m_material_mng->_internalApi()->isUseAcceleratorForConstituentItemVector();
223
224 Accelerator::eExecutionPolicy exec_policy = m_component->specificExecutionPolicy();
225 RunQueue queue = m_material_mng->_internalApi()->runQueue(exec_policy);
226
227 if (do_new_impl)
228 _computeNbPureAndImpure(local_ids, queue);
229 else
231
232 const Int32 nb_pure = m_nb_pure;
233 const Int32 nb_impure = m_nb_impure;
234 const Int32 total_nb_pure_and_impure = nb_pure + nb_impure;
235
236 // Array that will contain the indices of pure and impure cells.
237 // The first part from 0 to nb_pure will contain the pure part.
238 // The second part from nb_pure to (nb_pure+nb_impure) will contain the impure cells.
239 // Note that (nb_pure + nb_impure) may be different from local_ids.size()
240 // if some cells in local_ids do not have the constituent.
241 m_constituent_list->resize(total_nb_pure_and_impure);
242
243 // TODO: Do not systematically update // 'm_items_local_id' but only
244 // upon request // because they are not often used.
245
246 m_matvar_indexes.resize(total_nb_pure_and_impure);
247 m_items_local_id.resize(total_nb_pure_and_impure);
248
249 const bool is_env = m_component->isEnvironment();
250 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
251 const Int32 component_id = m_component->id();
252
253 // Lambda to retrieve the environment associated with the cell
254 auto env_component_getter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> ComponentCell {
255 AllEnvCell all_env_cell = all_env_cell_view[index];
256 for (EnvCell ec : all_env_cell.subEnvItems()) {
257 if (ec.componentId() == component_id)
258 return ec;
259 }
260 return {};
261 };
262
263 // Lambda to retrieve the material associated with the cell
264 auto mat_component_getter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> ComponentCell {
265 AllEnvCell all_env_cell = all_env_cell_view[index];
266 for (EnvCell ec : all_env_cell.subEnvItems()) {
267 for (MatCell mc : ec.subMatItems())
268 if (mc.componentId() == component_id)
269 return mc;
270 }
271 return {};
272 };
273
274 {
275 SetItemHelper helper(do_new_impl);
276 if (is_env)
277 helper.setItems(this, env_component_getter_lambda, local_ids, queue);
278 else
279 helper.setItems(this, mat_component_getter_lambda, local_ids, queue);
280 }
281
282 // Update MeshComponentPartData
283 const bool do_lazy_evaluation = true;
284 if (do_lazy_evaluation)
285 m_part_data->setNeedRecompute();
286 else
287 _recomputePartData();
288}
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
292
293void ConstituentItemVectorImpl::
294_computeNbPureAndImpure(SmallSpan<const Int32> local_ids, RunQueue& queue)
295{
296 IMeshComponent* component = m_component;
297 const bool is_env = component->isEnvironment();
298 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
299 const Int32 component_id = m_component->id();
300
301 auto command = makeCommand(queue);
302 Accelerator::ReducerSum2<Int32> nb_pure(command);
303 Accelerator::ReducerSum2<Int32> nb_impure(command);
304
305 // Calculates the number of pure and impure cells
306 if (is_env) {
307 command << RUNCOMMAND_MAT_ENUMERATE(AllEnvCell, all_env_cell, all_env_cell_view, nb_pure, nb_impure)
308 {
309 for (EnvCell ec : all_env_cell.subEnvItems()) {
310 if (ec.componentId() == component_id) {
311 MatVarIndex idx = ec._varIndex();
312 if (idx.arrayIndex() == 0)
313 nb_pure.combine(1);
314 else
315 nb_impure.combine(1);
316 }
317 }
318 };
319 }
320 else {
321 command << RUNCOMMAND_MAT_ENUMERATE(AllEnvCell, all_env_cell, all_env_cell_view, nb_pure, nb_impure)
322 {
323 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
324 for (MatCell mc : env_cell.subMatItems()) {
325 if (mc.componentId() == component_id) {
326 MatVarIndex idx = mc._varIndex();
327 if (idx.arrayIndex() == 0)
328 nb_pure.combine(1);
329 else
330 nb_impure.combine(1);
331 }
332 }
333 }
334 };
335 }
336
337 m_nb_pure = nb_pure.reducedValue();
338 m_nb_impure = nb_impure.reducedValue();
339}
340
341/*---------------------------------------------------------------------------*/
342/*---------------------------------------------------------------------------*/
343
347void ConstituentItemVectorImpl::
348_computeNbPureAndImpureLegacy(SmallSpan<const Int32> local_ids)
349{
350 IMeshComponent* component = m_component;
351 const bool is_env = component->isEnvironment();
352 AllEnvCellVectorView all_env_cell_view = m_material_mng->view(local_ids);
353 const Int32 component_id = m_component->id();
354
355 Int32 nb_pure = 0;
356 Int32 nb_impure = 0;
357
358 // Calculates the number of pure and impure cells
359 if (is_env) {
360 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
361 AllEnvCell all_env_cell = *iallenvcell;
362 for (EnvCell ec : all_env_cell.subEnvItems()) {
363 if (ec.componentId() == component_id) {
364 MatVarIndex idx = ec._varIndex();
365 if (idx.arrayIndex() == 0)
366 ++nb_pure;
367 else
368 ++nb_impure;
369 }
370 }
371 }
372 }
373 else {
374 ENUMERATE_ALLENVCELL (iallenvcell, all_env_cell_view) {
375 AllEnvCell all_env_cell = *iallenvcell;
376 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
377 for (MatCell mc : env_cell.subMatItems()) {
378 if (mc.componentId() == component_id) {
379 MatVarIndex idx = mc._varIndex();
380 if (idx.arrayIndex() == 0)
381 ++nb_pure;
382 else
383 ++nb_impure;
384 }
385 }
386 }
387 }
388 }
389
390 m_nb_pure = nb_pure;
391 m_nb_impure = nb_impure;
392}
393
394/*---------------------------------------------------------------------------*/
395/*---------------------------------------------------------------------------*/
396
397void ConstituentItemVectorImpl::
398_recomputePartData()
399{
400 // Update MeshComponentPartData
401 auto mvi_pure_view = m_matvar_indexes.subView(0, m_nb_pure);
402 auto mvi_impure_view = m_matvar_indexes.subView(m_nb_pure, m_nb_impure);
403 m_part_data->_setFromMatVarIndexes(mvi_pure_view, mvi_impure_view);
404}
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
409ComponentItemVectorView ConstituentItemVectorImpl::
410_view() const
411{
412 return { m_component, m_matvar_indexes,
413 m_constituent_list->view(), m_items_local_id };
414}
415
416/*---------------------------------------------------------------------------*/
417/*---------------------------------------------------------------------------*/
418
419} // End namespace Arcane::Materials
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros to manage enumerations of materials and media on accelerators.
#define RUNCOMMAND_MAT_ENUMERATE(ConstituentItemNameType, iter_name, env_or_mat_container,...)
Macro for iterating over a material or an environment.
SmallSpan< const T > smallSpan() const
Immutable view of this array.
View over a list of cells with environment information.
Arcane cell with material and environment information.
__host__ __device__ CellEnvCellEnumerator subEnvItems() const
Enumerator over the environment cells of this cell.
View over a vector of entities of a component.
Index of a constituent entity in the list of constituent entities.
void _computeNbPureAndImpureLegacy(SmallSpan< const Int32 > local_ids)
Calculates the number of pure and impure cells without the accelerator API.
__host__ __device__ CellLocalId globalCellId() const
localId() of the global cell
__host__ __device__ bool null() const
Indicates if it is the null cell.
__host__ __device__ ConstituentItemIndex _constituentItemIndex() const
__host__ __device__ MatVarIndex _varIndex() const
Arcane cell of an environment.
Interface of a component (material or environment) of a mesh.
virtual Int32 id() const =0
Component identifier.
virtual bool isEnvironment() const =0
True if the component is an environment.
virtual AllEnvCellVectorView view(const CellGroup &cells)=0
View of environment cells corresponding to the group cells.
Represents a material in a multi-material cell.
Represents an index on material and environment variables.
constexpr __host__ __device__ Int32 arrayIndex() const
Returns the index of the value array in the list of variables.
Data of a part (pure or partial) of a constituent.
View of an array of elements of type T.
Definition Span.h:805
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
Definition Span.h:327
#define ENUMERATE_ALLENVCELL(iname,...)
Macro to iterate over all AllEnvCell cells of a group.
RunCommand makeCommand(const RunQueue &run_queue)
Creates a command associated with the queue run_queue.
eExecutionPolicy
Execution policy for a Runner.
Always enables tracing in Arcane parts concerning materials.
IMemoryAllocator * getDefaultDataAllocator()
Default allocator for data.
std::int32_t Int32
Signed integer type of 32 bits.