Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
MeshMaterialModifierImpl.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/* MeshMaterialModifierImpl.cc (C) 2000-2024 */
9/* */
10/* Implementation of material and environment modification. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/NotSupportedException.h"
15#include "arcane/utils/PlatformUtils.h"
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/ValueConvert.h"
18
19#include "arcane/core/IItemFamily.h"
20#include "arcane/core/IData.h"
21#include "arcane/core/materials/internal/IMeshComponentInternal.h"
22
23#include "arcane/accelerator/core/ProfileRegion.h"
24
25#include "arcane/materials/IMeshMaterial.h"
26#include "arcane/materials/IMeshMaterialVariable.h"
27#include "arcane/materials/MeshMaterialBackup.h"
28#include "arcane/materials/internal/MeshMaterialMng.h"
29#include "arcane/materials/internal/AllEnvData.h"
30#include "arcane/materials/internal/MeshMaterialModifierImpl.h"
31#include "arcane/materials/internal/MaterialModifierOperation.h"
32#include "arcane/materials/internal/IncrementalComponentModifier.h"
33#include "arcane/materials/internal/ConstituentListPrinter.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane::Materials
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44MeshMaterialModifierImpl::OperationList::
45~OperationList()
46{
47 clear();
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53void MeshMaterialModifierImpl::OperationList::
54add(Operation* o)
55{
56 m_operations.add(o);
57}
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62void MeshMaterialModifierImpl::OperationList::
63clear()
64{
65 for (Operation* o : m_operations)
66 delete o;
67 m_operations.clear();
68}
69
70/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
75
76MeshMaterialModifierImpl::
77MeshMaterialModifierImpl(MeshMaterialMng* mm)
78: TraceAccessor(mm->traceMng())
79, m_material_mng(mm)
80, m_queue(m_material_mng->runQueue())
81{
82 _setLocalVerboseLevel(4);
83 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_DEBUG_MATERIAL_MODIFIER", true)) {
84 Int32 value = v.value();
85 if (value > 0) {
86 _setLocalVerboseLevel(3);
87 m_is_debug = true;
88 }
89 if (value > 1)
90 m_print_component_list = true;
91 }
92}
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
97/*---------------------------------------------------------------------------*/
98/*---------------------------------------------------------------------------*/
99
100void MeshMaterialModifierImpl::
101initOptimizationFlags()
102{
103 int opt_flag_value = m_material_mng->modificationFlags();
104
105 m_allow_optimization = false;
106
107 info() << "OptimizationFlag = " << opt_flag_value;
108
109 if (opt_flag_value != 0) {
110 info() << "Using optimization !";
111 m_allow_optimization = true;
112 }
113
114 m_allow_optimize_multiple_operation = (opt_flag_value & (int)eModificationFlags::OptimizeMultiAddRemove) != 0;
115 m_allow_optimize_multiple_material = (opt_flag_value & (int)eModificationFlags::OptimizeMultiMaterialPerEnvironment) != 0;
116 m_use_incremental_recompute = true;
117 if (m_use_incremental_recompute) {
118 m_allow_optimize_multiple_operation = true;
119 }
120
121 info() << "MeshMaterialModifier::optimization:"
122 << " allow?=" << m_allow_optimization
123 << " allow_multiple?=" << m_allow_optimize_multiple_operation
124 << " allow_multiple_mat?=" << m_allow_optimize_multiple_material
125 << " use_incremental_recompute?=" << m_use_incremental_recompute;
126}
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
130
131void MeshMaterialModifierImpl::
132addCells(IMeshMaterial* mat, SmallSpan<const Int32> ids)
133{
134 if (ids.empty())
135 return;
136 m_operations.add(Operation::createAdd(mat, ids));
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
142void MeshMaterialModifierImpl::
143removeCells(IMeshMaterial* mat, SmallSpan<const Int32> ids)
144{
145 if (ids.empty())
146 return;
147 m_operations.add(Operation::createRemove(mat, ids));
148}
149
150/*---------------------------------------------------------------------------*/
151/*---------------------------------------------------------------------------*/
152
153void MeshMaterialModifierImpl::
154_addCellsToGroupDirect(IMeshMaterial* mat, SmallSpan<const Int32> ids)
155{
156 CellGroup cells = mat->cells();
157 info(4) << "ADD_CELLS_TO_MATERIAL: mat=" << mat->name()
158 << " nb_item=" << ids.size();
159 cells.addItems(ids.smallView());
160}
161
162/*---------------------------------------------------------------------------*/
163/*---------------------------------------------------------------------------*/
164
165void MeshMaterialModifierImpl::
166_removeCellsToGroupDirect(IMeshMaterial* mat, SmallSpan<const Int32> ids)
167{
168 CellGroup cells = mat->cells();
169 info(4) << "REMOVE_CELLS_TO_MATERIAL: mat=" << mat->name()
170 << " nb_item=" << ids.size();
171 cells.removeItems(ids.smallView());
172}
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
176
177bool MeshMaterialModifierImpl::
178_checkMayOptimize()
179{
180 Integer nb_operation = m_operations.values().size();
181 if (nb_operation > 1 && !m_allow_optimize_multiple_operation)
182 return false;
183 for (Integer i = 0; i < nb_operation; ++i) {
184 Operation* op = m_operations.values()[i];
185 IMeshMaterial* mat = op->material();
186 if (mat->environment()->nbMaterial() != 1 && !m_allow_optimize_multiple_material) {
187 linfo() << "_checkMayOptimize(): not allowing optimization because environment has several material";
188 return false;
189 }
190 }
191 return true;
192}
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
196
197/*!
198 * \brief Applies the recorded operations.
199 */
200void MeshMaterialModifierImpl::
201endUpdate()
202{
203 ConstituentListPrinter list_printer(m_material_mng);
204 if (m_print_component_list) {
205 info() << "MeshMaterialModifierImpl::endUpdate(): BEGIN"
206 << " modification_id=" << m_modification_id;
207 list_printer.print();
208 }
209 _endUpdate();
210 if (m_print_component_list) {
211 info() << "MeshMaterialModifierImpl::endUpdate(): END"
212 << " modification_id=" << m_modification_id;
213 list_printer.print();
214 }
215 ++m_modification_id;
216}
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
220
221void MeshMaterialModifierImpl::
222_endUpdate()
223{
224 Accelerator::ProfileRegion ps(m_queue, "ConstituentsEndUpdate", 0x97599A);
225
226 bool is_keep_value = m_material_mng->isKeepValuesAfterChange();
227 Integer nb_operation = m_operations.values().size();
228
229 linfo() << "END_UPDATE_MAT_Begin keep=" << is_keep_value
230 << " nb_operation=" << nb_operation;
231
232 m_material_mng->incrementTimestamp();
233
234 MeshMaterialBackup backup(m_material_mng, false);
235
236 bool no_optimization_done = true;
237
238 ++nb_update;
239 AllEnvData* all_env_data = m_material_mng->allEnvData();
240
241 bool is_display = traceMng()->verbosityLevel() >= _localVerboseLevel();
242
243 for (Integer i = 0; i < nb_operation; ++i) {
244 const Operation* op = m_operations.values()[i];
245 IMeshMaterial* mat = op->material();
246 const IMeshComponentInternal* mci = mat->_internalApi();
247
248 // Only calls the method if display will be performed to avoid
249 // copying 'op->ids()' to the host.
250 if (is_display)
251 linfo() << "MODIFIER_CELLS_TO_MATERIAL: mat=" << mat->name()
252 << " is_add=" << op->isAdd()
253 << " mat_index=" << mci->variableIndexer()->index()
254 << " op_index=" << i
255 << " ids=" << op->ids();
256 }
257
258 bool is_optimization_active = m_allow_optimization;
259 if (is_optimization_active)
260 is_optimization_active = _checkMayOptimize();
261 linfo() << "Check optimize ? = " << is_optimization_active;
262
263 // Work table used during incremental modifications
264 if (!m_incremental_modifier) {
265 linfo() << "Creating IncrementalComponentModifier";
266 m_incremental_modifier = std::make_unique<IncrementalComponentModifier>(all_env_data, m_queue);
267 }
268 if (is_optimization_active && m_use_incremental_recompute) {
269 m_incremental_modifier->initialize(m_is_debug);
270 m_incremental_modifier->setDoCopyBetweenPartialAndPure(m_do_copy_between_partial_and_pure);
271 m_incremental_modifier->setDoInitNewItems(m_do_init_new_items);
272 }
273
274 if (is_optimization_active) {
275 for (Operation* op : m_operations.values()) {
276 const IMeshMaterial* mat = op->material();
277
278 if (op->isAdd()) {
279 linfo() << "ONLY_ONE_ADD: using optimization mat=" << mat->name();
280 ++nb_optimize_add;
281 }
282 else {
283 linfo() << "ONLY_ONE_REMOVE: using optimization mat=" << mat->name();
284 ++nb_optimize_remove;
285 }
286
287 m_incremental_modifier->m_work_info.setCurrentOperation(op);
288
289 // Checks in the case of cells to be added if they are not already
290 // in the material and in the case of cells to be removed if they are.
291 if (arcaneIsCheck())
292 op->filterIds();
293
294 m_incremental_modifier->apply(op);
295 }
296 no_optimization_done = false;
297 }
298
299 if (no_optimization_done) {
300 if (is_keep_value) {
301 ++nb_save_restore;
302 backup.saveValues();
303 }
304
305 _applyOperationsNoOptimize();
306 _updateEnvironmentsNoOptimize();
307
308 all_env_data->forceRecompute(true);
309
310 if (is_keep_value) {
311 backup.restoreValues();
312 }
313 }
314 else {
315 m_incremental_modifier->finalize();
316 all_env_data->recomputeIncremental();
317 }
318
319 if (!m_is_keep_work_buffer)
320 m_incremental_modifier = nullptr;
321
322 linfo() << "END_UPDATE_MAT End";
323}
324
325/*---------------------------------------------------------------------------*/
326/*---------------------------------------------------------------------------*/
327
328void MeshMaterialModifierImpl::
329_applyOperationsNoOptimize()
330{
331 for (Operation* o : m_operations.values()) {
332 IMeshMaterial* mat = o->material();
333 if (o->isAdd())
334 _addCellsToGroupDirect(mat, o->ids());
335 else
336 _removeCellsToGroupDirect(mat, o->ids());
337 }
338 m_operations.clear();
339}
340
341/*---------------------------------------------------------------------------*/
342/*---------------------------------------------------------------------------*/
343
344void MeshMaterialModifierImpl::
345_updateEnvironmentsNoOptimize()
346{
347 ConstArrayView<IMeshEnvironment*> envs = m_material_mng->environments();
348 Int32UniqueArray cells_to_add;
349 Int32UniqueArray cells_to_remove;
350 info(4) << "CHECK ENVIRONMENTS";
351
352 // Checks if cells need to be added or removed from an environment
353 // based on those that were added or removed in the
354 // materials.
355 for (IMeshEnvironment* env : envs) {
356
357 // For environments containing only one material, there is nothing
358 // to do because the material group is the same as the environment group
359 if (env->nbMaterial() == 1)
360 continue;
361
362 CellGroup env_cells = env->cells();
363 info(4) << "CHECK ENV name=" << env->name() << " nb_cell=" << env_cells.size();
364 Integer max_id = env_cells.itemFamily()->maxLocalId();
365 Int32UniqueArray cells_marker(max_id, -1);
366 ENUMERATE_CELL (icell, env_cells) {
367 cells_marker[icell.itemLocalId()] = 0;
368 }
369 cells_to_add.clear();
370 cells_to_remove.clear();
371 ConstArrayView<IMeshMaterial*> env_materials = env->materials();
372 for (IMeshMaterial* mat : env_materials) {
373 ENUMERATE_CELL (icell, mat->cells()) {
374 Int32 mark = cells_marker[icell.itemLocalId()];
375 if (mark == (-1)) {
376 //mark = 0;
377 // Cell to add.
378 cells_to_add.add(icell.itemLocalId());
379 }
380 //++mark;
381 cells_marker[icell.itemLocalId()] = 1;
382 }
383 }
384
385 ENUMERATE_CELL (icell, env_cells) {
386 Int32 mark = cells_marker[icell.itemLocalId()];
387 if (mark == 0)
388 cells_to_remove.add(icell.itemLocalId());
389 }
390 if (!cells_to_add.empty()) {
391 info(4) << "ADD_CELLS to env " << env->name() << " n=" << cells_to_add.size();
392 env_cells.addItems(cells_to_add);
393 }
394 if (!cells_to_remove.empty()) {
395 info(4) << "REMOVE_CELLS to env " << env->name() << " n=" << cells_to_remove.size();
396 env_cells.removeItems(cells_to_remove);
397 }
398 }
399}
400
401/*---------------------------------------------------------------------------*/
402/*---------------------------------------------------------------------------*/
403
404void MeshMaterialModifierImpl::
405reset()
406{
407 m_do_copy_between_partial_and_pure = true;
408 m_do_init_new_items = true;
409 m_is_keep_work_buffer = true;
410}
411
412/*---------------------------------------------------------------------------*/
413/*---------------------------------------------------------------------------*/
414
415void MeshMaterialModifierImpl::
416beginUpdate()
417{
418 m_material_mng->info(4) << "BEGIN_UPDATE_MAT";
419 m_operations.clear();
420}
421
422/*---------------------------------------------------------------------------*/
423/*---------------------------------------------------------------------------*/
424
425void MeshMaterialModifierImpl::
426dumpStats()
427{
428 info() << "MeshMaterialModifierImpl statistics mesh=" << m_material_mng->mesh()->name();
429
430 info() << " Nb update : " << nb_update;
431 info() << " Nb save/restore : " << nb_save_restore;
432 info() << " Nb optimized add : " << nb_optimize_add;
433 info() << " Nb optimized remove : " << nb_optimize_remove;
434}
435
436/*---------------------------------------------------------------------------*/
437/*---------------------------------------------------------------------------*/
438
439} // End namespace Arcane::Materials
440
441/*---------------------------------------------------------------------------*/
442/*---------------------------------------------------------------------------*/
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
void clear()
Removes the elements from the array.
const String & name() const
Group name.
Definition ItemGroup.h:81
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
Always enables tracing in Arcane parts concerning materials.
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
Int32 Integer
Type representing an integer.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341