14#include "arcane/materials/internal/IncrementalComponentModifier.h"
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FunctorUtils.h"
18#include "arcane/utils/ValueConvert.h"
20#include "arcane/core/IItemFamily.h"
21#include "arcane/core/materials/IMeshMaterialVariable.h"
23#include "arcane/materials/internal/MeshMaterialMng.h"
24#include "arcane/materials/internal/ConstituentConnectivityList.h"
25#include "arcane/materials/internal/AllEnvData.h"
27#include "arcane/accelerator/core/ProfileRegion.h"
38IncrementalComponentModifier::
39IncrementalComponentModifier(AllEnvData* all_env_data,
const RunQueue& queue)
40: TraceAccessor(all_env_data->traceMng())
41, m_all_env_data(all_env_data)
42, m_material_mng(all_env_data->m_material_mng)
43, m_work_info(queue.allocationOptions(), queue.memoryRessource())
49 if (
auto v = Convert::Type<Int32>::tryParseFromEnvironment(
"ARCANE_USE_GENERIC_COPY_BETWEEN_PURE_AND_PARTIAL",
true)) {
50 m_use_generic_copy_between_pure_and_partial = v.value();
55 if (queue.isAcceleratorPolicy())
56 m_use_generic_copy_between_pure_and_partial = 2;
63void IncrementalComponentModifier::
64initialize(
bool is_debug)
66 m_is_debug = is_debug;
67 Int32 max_local_id = m_material_mng->mesh()->cellFamily()->maxLocalId();
68 Int32 nb_mat = m_material_mng->materials().size();
69 Int32 nb_env = m_material_mng->environments().size();
70 m_work_info.initialize(max_local_id, nb_mat, nb_env, m_queue);
71 m_work_info.is_verbose = is_debug || (traceMng()->verbosityLevel() >= 5);
77void IncrementalComponentModifier::
96void IncrementalComponentModifier::
97_switchCellsForMaterials(
const MeshMaterial* modified_mat,
98 SmallSpan<const Int32> ids)
100 const bool is_add = m_work_info.isAdd();
101 const bool is_device = m_queue.isAcceleratorPolicy();
102 SmallSpan<const bool> is_materials_modified = m_work_info.m_is_materials_modified.view(
false);
104 for (MeshEnvironment* true_env : m_material_mng->trueEnvironments()) {
105 for (MeshMaterial* mat : true_env->trueMaterials()) {
107 if (mat == modified_mat)
110 if (!is_materials_modified[mat->id()])
114 m_work_info.pure_local_ids.clearHost();
115 m_work_info.partial_indexes.clearHost();
118 MeshMaterialVariableIndexer* indexer = mat->variableIndexer();
120 info(4) <<
"MatTransformCells is_add?=" << is_add <<
" indexer=" << indexer->name()
121 <<
" mat_id=" << mat->id();
123 Int32 nb_transformed = _computeCellsToTransformForMaterial(mat, ids);
124 info(4) <<
"nb_transformed=" << nb_transformed;
125 if (nb_transformed == 0)
127 indexer->transformCells(m_work_info, m_queue,
false);
128 _resetTransformedCells(ids);
130 auto pure_local_ids = m_work_info.pure_local_ids.view(is_device);
131 auto partial_indexes = m_work_info.partial_indexes.view(is_device);
133 Int32 nb_pure = pure_local_ids.size();
134 Int32 nb_partial = partial_indexes.size();
135 info(4) <<
"NB_MAT_TRANSFORM pure=" << nb_pure
136 <<
" partial=" << nb_partial <<
" name=" << mat->name()
137 <<
" is_device?=" << is_device
138 <<
" is_modified?=" << is_materials_modified[mat->id()];
140 CopyBetweenPartialAndGlobalArgs args(indexer->index(), pure_local_ids,
142 m_do_copy_between_partial_and_pure,
145 _copyBetweenPartialsAndGlobals(args);
164void IncrementalComponentModifier::
165_switchCellsForEnvironments(
const IMeshEnvironment* modified_env,
166 SmallSpan<const Int32> ids)
168 const bool is_add = m_work_info.isAdd();
169 const bool is_device = m_queue.isAcceleratorPolicy();
170 SmallSpan<const bool> is_environments_modified = m_work_info.m_is_environments_modified.view(
false);
176 const bool is_copy = is_add || !(m_material_mng->isUseMaterialValueWhenRemovingPartialValue());
178 Int32 nb_transformed = _computeCellsToTransformForEnvironments(ids);
179 info(4) <<
"Compute Cells for environments nb_transformed=" << nb_transformed;
180 if (nb_transformed == 0)
183 for (
const MeshEnvironment* env : m_material_mng->trueEnvironments()) {
185 if (env == modified_env)
188 if (env->isMonoMaterial())
191 const Int32 env_id = env->id();
193 if (!is_environments_modified[env_id])
197 m_work_info.pure_local_ids.clearHost();
198 m_work_info.partial_indexes.clearHost();
201 MeshMaterialVariableIndexer* indexer = env->variableIndexer();
203 info(4) <<
"EnvTransformCells is_add?=" << is_add
204 <<
" env_id=" << env_id
205 <<
" indexer=" << indexer->name() <<
" nb_item=" << ids.size();
207 indexer->transformCells(m_work_info, m_queue,
true);
209 SmallSpan<const Int32> pure_local_ids = m_work_info.pure_local_ids.view(is_device);
210 SmallSpan<const Int32> partial_indexes = m_work_info.partial_indexes.view(is_device);
211 const Int32 nb_pure = pure_local_ids.size();
213 info(4) <<
"NB_ENV_TRANSFORM nb_pure=" << nb_pure <<
" name=" << env->name()
214 <<
" is_modified=" << is_environments_modified[env_id];
217 CopyBetweenPartialAndGlobalArgs copy_args(indexer->index(), pure_local_ids,
219 m_do_copy_between_partial_and_pure, is_add,
221 _copyBetweenPartialsAndGlobals(copy_args);
225 _resetTransformedCells(ids);
233Int32 IncrementalComponentModifier::
234_computeCellsToTransformForMaterial(
const MeshMaterial* mat, SmallSpan<const Int32> ids)
236 const MeshEnvironment* env = mat->trueEnvironment();
237 const Int16 env_id = env->componentId();
238 bool is_add = m_work_info.isAdd();
240 ConstituentConnectivityList* connectivity = m_all_env_data->componentConnectivityList();
241 SmallSpan<bool> transformed_cells = m_work_info.transformedCells();
242 return connectivity->fillCellsToTransform(ids, env_id, transformed_cells, is_add, m_queue);
260void IncrementalComponentModifier::
261_removeItemsFromEnvironment(MeshEnvironment* env, MeshMaterial* mat,
262 SmallSpan<const Int32> local_ids,
bool update_env_indexer)
264 info(4) <<
"MeshEnvironment::removeItemsDirect mat=" << mat->name();
266 Int32 nb_to_remove = local_ids.size();
269 env->addToTotalNbCellMat(-nb_to_remove);
271 mat->variableIndexer()->endUpdateRemove(m_work_info, nb_to_remove, m_queue);
273 if (update_env_indexer) {
278 env->variableIndexer()->endUpdateRemove(m_work_info, nb_to_remove, m_queue);
292void IncrementalComponentModifier::
293_addItemsToEnvironment(MeshEnvironment* env, MeshMaterial* mat,
294 SmallSpan<const Int32> local_ids,
bool update_env_indexer)
296 info(4) <<
"MeshEnvironment::addItemsDirect"
297 <<
" mat=" << mat->name();
299 MeshMaterialVariableIndexer* var_indexer = mat->variableIndexer();
300 const Int32 nb_to_add = local_ids.size();
303 env->addToTotalNbCellMat(nb_to_add);
305 const Int16 env_id = env->componentId();
306 m_work_info.m_cells_is_partial.resize(nb_to_add);
307 ConstituentConnectivityList* connectivity = m_all_env_data->componentConnectivityList();
308 connectivity->fillCellsIsPartial(local_ids, env_id, m_work_info.m_cells_is_partial.to1DSmallSpan(), m_queue);
310 _addItemsToIndexer(var_indexer, local_ids);
312 if (update_env_indexer) {
317 _addItemsToIndexer(env->variableIndexer(), local_ids);
324void IncrementalComponentModifier::
325_addItemsToIndexer(MeshMaterialVariableIndexer* var_indexer,
326 SmallSpan<const Int32> local_ids)
329 ComponentItemListBuilder& list_builder = m_work_info.list_builder;
330 list_builder.setIndexer(var_indexer);
332 const Int32 nb_id = local_ids.size();
333 list_builder.preAllocate(nb_id);
335 _computeItemsToAdd(list_builder, local_ids);
337 if (traceMng()->verbosityLevel() >= 5)
338 info() <<
"ADD_MATITEM_TO_INDEXER component=" << var_indexer->name()
339 <<
" nb_pure=" << list_builder.pureIndexes().size()
340 <<
" nb_partial=" << list_builder.partialIndexes().size()
341 <<
"\n pure=(" << list_builder.pureIndexes() <<
")"
342 <<
"\n partial=(" << list_builder.partialIndexes() <<
")";
347 var_indexer->endUpdateAdd(list_builder, m_queue);
350 _resizeVariablesIndexer(var_indexer->index());
354 if (m_do_init_new_items) {
355 IMeshMaterialMng* mm = m_material_mng;
356 bool init_with_zero = mm->isDataInitialisationWithZero();
358 Accelerator::ProfileRegion ps(m_queue,
"InitializeNewItems", 0xFFFF00);
360 SmallSpan<Int32> partial_indexes = list_builder.partialIndexes();
361 if (init_with_zero) {
362 RunQueue::ScopedAsync sc(&m_queue);
363 InitializeWithZeroArgs init_args(var_indexer->index(), partial_indexes, m_queue);
365 bool do_one_command = (m_use_generic_copy_between_pure_and_partial == 2);
366 UniqueArray<CopyBetweenDataInfo>& copy_data = m_work_info.m_host_variables_copy_data;
367 if (do_one_command) {
369 copy_data.reserve(m_material_mng->nbVariable());
370 init_args.m_copy_data = ©_data;
373 auto func_zero = [&](IMeshMaterialVariable* mv) {
374 mv->_internalApi()->initializeNewItemsWithZero(init_args);
376 functor::apply(mm, &IMeshMaterialMng::visitVariables, func_zero);
379 MDSpan<CopyBetweenDataInfo, MDDim1> x(copy_data.data(), MDIndex<1>(copy_data.size()));
380 m_work_info.m_variables_copy_data.copy(x, &m_queue);
381 _applyInitializeWithZero(init_args);
386 SmallSpan<Int32> partial_local_ids = list_builder.partialLocalIds();
388 CopyBetweenPartialAndGlobalArgs args(var_indexer->index(), partial_local_ids,
389 partial_indexes,
true,
true, m_queue);
390 _copyBetweenPartialsAndGlobals(args);
400void IncrementalComponentModifier::
401_resizeVariablesIndexer(Int32 var_index)
403 RunQueue& queue = m_material_mng->_internalApi()->runQueue();
404 RunQueue::ScopedAsync sc(&m_queue);
405 Accelerator::ProfileRegion ps(queue,
"ResizeVariableIndexer", 0xFF00FF);
406 ResizeVariableIndexerArgs resize_args(var_index, queue);
410 bool do_one_command = (m_use_generic_copy_between_pure_and_partial == 2);
411 UniqueArray<CopyBetweenDataInfo>& copy_data = m_work_info.m_host_variables_copy_data;
412 if (do_one_command) {
414 copy_data.reserve(m_material_mng->nbVariable());
415 resize_args.m_copy_data = ©_data;
418 auto func1 = [&](IMeshMaterialVariable* mv) {
419 auto* mvi = mv->_internalApi();
420 mvi->resizeForIndexer(resize_args);
422 functor::apply(m_material_mng, &MeshMaterialMng::visitVariables, func1);
424 if (do_one_command) {
426 MDSpan<CopyBetweenDataInfo, MDDim1> x(copy_data.data(), MDIndex<1>(copy_data.size()));
427 m_work_info.m_variables_copy_data.copy(x, &queue);
428 _applyCopyVariableViews(queue);
443void IncrementalComponentModifier::
444_copyBetweenPartialsAndGlobals(
const CopyBetweenPartialAndGlobalArgs& args)
446 if (args.m_local_ids.empty())
448 const bool do_copy = args.m_do_copy_between_partial_and_pure;
449 const bool is_add_operation = args.m_is_global_to_partial;
450 RunQueue queue(args.m_queue);
451 RunQueue::ScopedAsync sc(&queue);
457 Accelerator::RunQueuePool& queue_pool = m_material_mng->_internalApi()->asyncRunQueuePool();
460 if (is_add_operation) {
461 _resizeVariablesIndexer(args.m_var_index);
465 bool do_one_command = (m_use_generic_copy_between_pure_and_partial == 2);
466 UniqueArray<CopyBetweenDataInfo>& copy_data = m_work_info.m_host_variables_copy_data;
468 copy_data.reserve(m_material_mng->nbVariable());
471 CopyBetweenPartialAndGlobalArgs args2(args);
472 args2.m_use_generic_copy = (m_use_generic_copy_between_pure_and_partial >= 1);
474 args2.m_copy_data = ©_data;
475 auto func2 = [&](IMeshMaterialVariable* mv) {
476 auto* mvi = mv->_internalApi();
478 args2.m_queue = queue_pool[index];
479 mvi->copyBetweenPartialAndGlobal(args2);
482 functor::apply(m_material_mng, &MeshMaterialMng::visitVariables, func2);
483 if (do_one_command) {
485 MDSpan<CopyBetweenDataInfo, MDDim1> x(copy_data.data(), MDIndex<1>(copy_data.size()));
486 m_work_info.m_variables_copy_data.copy(x, &queue);
487 _applyCopyBetweenPartialsAndGlobals(args2, queue);
490 queue_pool.barrier();
Active toujours les traces dans les parties Arcane concernant les matériaux.