Arcane  4.2.1.0
User documentation
Loading...
Searching...
No Matches
MeshMaterialMng.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/* MeshMaterialMng.cc (C) 2000-2026 */
9/* */
10/* Material and mesh environment manager. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/internal/MeshMaterialMng.h"
15
16#include "arcane/utils/TraceAccessor.h"
17#include "arcane/utils/NotImplementedException.h"
18#include "arcane/utils/AutoDestroyUserData.h"
19#include "arcane/utils/IUserDataList.h"
20#include "arcane/utils/OStringStream.h"
21#include "arcane/utils/PlatformUtils.h"
22#include "arcane/utils/ValueConvert.h"
23#include "arcane/utils/CheckedConvert.h"
25
26#include "arcane/core/IMesh.h"
27#include "arcane/core/IItemFamily.h"
28#include "arcane/core/VariableTypes.h"
29#include "arcane/core/ItemPrinter.h"
30#include "arcane/core/IVariableMng.h"
31#include "arcane/core/Properties.h"
32#include "arcane/core/ObserverPool.h"
33#include "arcane/core/materials/IMeshMaterialVariableFactoryMng.h"
34#include "arcane/core/materials/IMeshMaterialVariable.h"
36#include "arcane/core/materials/internal/IMeshMaterialVariableInternal.h"
37#include "arcane/core/internal/IVariableMngInternal.h"
38
39#include "arcane/accelerator/core/IAcceleratorMng.h"
40
41#include "arcane/materials/MeshMaterialInfo.h"
42#include "arcane/materials/MeshEnvironmentBuildInfo.h"
43#include "arcane/materials/CellToAllEnvCellConverter.h"
44#include "arcane/materials/MeshMaterialExchangeMng.h"
45#include "arcane/materials/EnumeratorTracer.h"
46#include "arcane/materials/MeshMaterialVariableFactoryRegisterer.h"
47#include "arcane/materials/internal/AllEnvData.h"
48#include "arcane/materials/internal/MeshMaterialModifierImpl.h"
49#include "arcane/materials/internal/MeshMaterialSynchronizer.h"
50#include "arcane/materials/internal/MeshMaterialVariableSynchronizer.h"
51#include "arcane/materials/internal/ConstituentConnectivityList.h"
52#include "arcane/materials/internal/AllCellToAllEnvCellContainer.h"
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
57/*!
58 * \file MaterialsGlobal.h
59 *
60 * Global declarations for materials.
61 */
62
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
65
66/*
67 * TODO:
68 * - Verify that only one instance of MeshModifier is created.
69 * - For example, check in synchronizeMaterialsInCells()
70 * that the mesh is not being modified.
71 */
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
75
76namespace Arcane::Materials
77{
78
80arcaneCreateMeshMaterialVariableFactoryMng(IMeshMaterialMng* mm);
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
84
85namespace
86{
88 arcaneCreateMeshMaterialMng(const MeshHandle& mesh_handle, const String& name)
89 {
90 MeshMaterialMng* mmm = new MeshMaterialMng(mesh_handle, name);
91 //std::cout << "CREATE MESH_MATERIAL_MNG mesh_name=" << mesh_handle.meshName()
92 // << " ref=" << mesh_handle.reference() << " this=" << mmm << "\n";
93 mmm->build();
94 return mmm;
95 }
96} // namespace
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101MeshMaterialMng::RunnerInfo::
102RunnerInfo(Runner& runner)
103: m_runner(runner)
104, m_run_queue(makeQueue(m_runner))
105, m_sequential_runner(Accelerator::eExecutionPolicy::Sequential)
106, m_sequential_run_queue(makeQueue(m_sequential_runner))
107, m_multi_thread_runner(Accelerator::eExecutionPolicy::Thread)
108, m_multi_thread_run_queue(makeQueue(m_multi_thread_runner))
109{
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115void MeshMaterialMng::RunnerInfo::
116initializeAsyncPool(Int32 nb_queue)
117{
118 // If an accelerator policy is used, create asynchronous RunQueues
119 // for independent operations. This will allow several to be executed
120 // at the same time.
121 bool is_accelerator = isAcceleratorPolicy(m_runner.executionPolicy());
122 m_async_queue_pool.initialize(m_runner, nb_queue);
123 if (is_accelerator)
124 m_async_queue_pool.setAsync(true);
125}
126
127/*---------------------------------------------------------------------------*/
128/*---------------------------------------------------------------------------*/
129
130RunQueue MeshMaterialMng::RunnerInfo::
131runQueue(Accelerator::eExecutionPolicy policy) const
132{
133 if (policy == Accelerator::eExecutionPolicy::None)
134 return m_run_queue;
135 if (policy == Accelerator::eExecutionPolicy::Sequential)
136 return m_sequential_run_queue;
137 if (policy == Accelerator::eExecutionPolicy::Thread)
138 return m_multi_thread_run_queue;
139 ARCANE_FATAL("Invalid value '{0}' for execution policy. Valid values are None, Sequential or Thread", policy);
140}
141
142/*---------------------------------------------------------------------------*/
143/*---------------------------------------------------------------------------*/
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
148MeshMaterialMng::
149MeshMaterialMng(const MeshHandle& mesh_handle, const String& name)
150// TODO: use the mesh's ITraceMng. Do it during init
151: TraceAccessor(mesh_handle.traceMng())
152, m_mesh_handle(mesh_handle)
153, m_internal_api(std::make_unique<InternalApi>(this))
154, m_variable_mng(mesh_handle.variableMng())
155, m_name(name)
156, m_indexed_selection_identity(MemoryUtils::getDefaultDataAllocator())
157{
158 m_all_env_data = std::make_unique<AllEnvData>(this);
159 m_exchange_mng = std::make_unique<MeshMaterialExchangeMng>(this);
160 m_variable_factory_mng = arcaneCreateMeshMaterialVariableFactoryMng(this);
161 m_observer_pool = std::make_unique<ObserverPool>();
162 m_observer_pool->addObserver(this, &MeshMaterialMng::_onMeshDestroyed, mesh_handle.onDestroyObservable());
163
164 String s = platform::getEnvironmentVariable("ARCANE_ALLENVCELL_FOR_RUNCOMMAND");
165 if (!s.null())
166 m_is_use_accelerator_envcell_container = true;
167 m_mms = new MeshMaterialSynchronizer(this);
168}
169
170/*---------------------------------------------------------------------------*/
171/*---------------------------------------------------------------------------*/
172
173MeshMaterialMng::
174~MeshMaterialMng()
175{
176 //std::cout << "DESTROY MESH MATERIAL MNG this=" << this << '\n';
177 _dumpStats();
178
179 delete m_mms;
180 delete m_variable_factory_mng;
181 m_exchange_mng.reset();
182 m_all_cells_env_only_synchronizer.reset();
183 m_all_cells_mat_env_synchronizer.reset();
184 m_all_env_data.reset();
185 m_properties.reset();
186
187 for (MeshMaterial* m : m_true_materials)
188 delete m;
189 m_true_materials.clear();
190
191 for (MeshEnvironment* e : m_true_environments)
192 delete e;
193 m_true_environments.clear();
194
195 for (IMeshBlock* b : m_true_blocks)
196 delete b;
197
198 for (MeshMaterialInfo* mmi : m_materials_info)
199 delete mmi;
200
201 for (MeshMaterialVariableIndexer* mvi : m_variables_indexer_to_destroy)
202 delete mvi;
203
204 m_modifier.reset();
205 m_internal_api.reset();
206
207 m_accelerator_envcell_container.reset();
208
209 // Destroy the Runner at the end to ensure there are no more
210 // references to it in other instances.
211 m_runner_info.reset();
212}
213
214/*---------------------------------------------------------------------------*/
215/*---------------------------------------------------------------------------*/
216
217/*---------------------------------------------------------------------------*/
218/*---------------------------------------------------------------------------*/
219
220void MeshMaterialMng::
221build()
222{
223 // Register variable factories
224 {
225 auto* x = MeshMaterialVariableFactoryRegisterer::firstRegisterer();
226 while (x) {
227 m_variable_factory_mng->registerFactory(x->createFactory());
228 x = x->nextRegisterer();
229 }
230 }
231
232 // Indicate whether the accelerator API is used for calculating
233 // ConstituentItemVectorImpl entities
234 {
235 bool force_enable = false;
236 if (const auto v = Convert::Type<Real>::tryParseFromEnvironment("ARCANE_MATERIALMNG_USE_ACCELERATOR_FOR_CONSTITUENTITEMVECTOR", true)) {
237 m_is_use_accelerator_for_constituent_item_vector = (v.value() != 0);
238 force_enable = m_is_use_accelerator_for_constituent_item_vector;
239 }
240 // Do not activate the use of RunQueue for calculating
241 // 'ComponentItemVector' if multi-threading is active. Currently,
242 // using the same RunQueue is not multi-threaded (and therefore
243 // ComponentItemVector cannot be created concurrently)
244 if (!force_enable && TaskFactory::isActive())
245 m_is_use_accelerator_for_constituent_item_vector = false;
246 info() << "Use accelerator API for 'ConstituentItemVectorImpl' = " << m_is_use_accelerator_for_constituent_item_vector;
247 }
248
249 // Position the default runner
250 {
251 IAcceleratorMng* acc_mng = m_variable_mng->_internalApi()->acceleratorMng();
252 Runner runner;
253 if (acc_mng) {
254 Runner* default_runner = acc_mng->defaultRunner();
255 // Indicate whether the accelerator queue is activated
256 bool use_accelerator_runner = true;
257 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_MATERIALMNG_USE_QUEUE", true))
258 use_accelerator_runner = (v.value() != 0);
259 if (use_accelerator_runner && default_runner)
260 runner = *default_runner;
261 }
262 // If no runner is registered, use a sequential runner.
263 if (!runner.isInitialized())
264 runner.initialize(Accelerator::eExecutionPolicy::Sequential);
265 m_runner_info = std::make_unique<RunnerInfo>(runner);
266 Int32 nb_queue = isAcceleratorPolicy(runner.executionPolicy()) ? 8 : 1;
267 info() << "Use runner '" << this->runner().executionPolicy() << "' for MeshMaterialMng name=" << name()
268 << " async_queue_size=" << nb_queue;
269 m_runner_info->initializeAsyncPool(nb_queue);
270
271 // In release mode and if an accelerator is used, allocate by
272 // default on the accelerator. This is important especially for
273 // temporary arrays.
274 // In 'check' mode, unified memory must be left because tests are done
275 // on the CPU.
276 RunQueue& q = runQueue();
277 if (!arcaneIsCheck() && q.isAcceleratorPolicy())
278 q.setMemoryRessource(eMemoryRessource::Device);
279 }
280
281 // Choice of optimizations.
282 {
283 int default_flags = 0;
284
285 // Do not set these flags by default yet because it does not work
286 // for all codes
287 // default_flags = (int)eModificationFlags::GenericOptimize | (int)eModificationFlags::OptimizeMultiAddRemove;
288
289 int opt_flag_value = 0;
290 String env_name = "ARCANE_MATERIAL_MODIFICATION_FLAGS";
291 String opt_flag_str = platform::getEnvironmentVariable(env_name);
292 if (!opt_flag_str.null()) {
293 if (builtInGetValue(opt_flag_value, opt_flag_str)) {
294 pwarning() << "Invalid value '" << opt_flag_str
295 << " 'for environment variable '" << env_name
296 << "'";
297 opt_flag_value = default_flags;
298 }
299 }
300 else {
301 opt_flag_value = default_flags;
302 }
303 m_modification_flags = opt_flag_value;
304 }
305
306 // Choice of synchronization implementation version
307 {
308 String env_name = "ARCANE_MATSYNCHRONIZE_VERSION";
309 String env_value = platform::getEnvironmentVariable(env_name);
310 info() << "ENV_VALUE=" << env_value;
311 Integer version = m_synchronize_variable_version;
312 if (!env_value.null()) {
313 if (builtInGetValue(version, env_value)) {
314 pwarning() << "Invalid value '" << env_value
315 << " 'for environment variable '" << env_name
316 << "'";
317 }
318 else
319 m_synchronize_variable_version = version;
320 }
321 info() << "Set material variable synchronize version to "
322 << "'" << m_synchronize_variable_version << "'";
323 }
324
325 // Choice of compression service
326 {
327 String env_name = "ARCANE_MATERIAL_DATA_COMPRESSOR_NAME";
328 String env_value = platform::getEnvironmentVariable(env_name);
329 if (!env_value.null()) {
330 info() << "Use service '" << env_value << "' for material data compression";
331 m_data_compressor_service_name = env_value;
332 }
333 }
334
335 // Choice of additional capacity ratio
336 {
337 if (auto v = Convert::Type<Real>::tryParseFromEnvironment("ARCANE_MATERIALMNG_ADDITIONAL_CAPACITY_RATIO", true)) {
338 if (v >= 0.0) {
339 m_additional_capacity_ratio = v.value();
340 info() << "Set additional capacity ratio to " << m_additional_capacity_ratio;
341 }
342 }
343 }
344
345 m_exchange_mng->build();
346 // If enumerator traces on entities are active, activate those
347 // on materials.
348 // TODO: make this code thread-safe in case of using IParallelMng via threads
349 // and call it only once.
350 IItemEnumeratorTracer* item_tracer = IItemEnumeratorTracer::singleton();
351 if (item_tracer) {
352 info() << "Adding material enumerator tracing";
353 EnumeratorTracer::_setSingleton(new EnumeratorTracer(traceMng(), item_tracer->perfCounterRef()));
354 }
355}
356
357/*---------------------------------------------------------------------------*/
358/*---------------------------------------------------------------------------*/
359
360void MeshMaterialMng::
361_addVariableIndexer(MeshMaterialVariableIndexer* var_idx)
362{
363 var_idx->setIndex(m_variables_indexer.size());
364 m_variables_indexer.add(var_idx);
365}
366
367/*---------------------------------------------------------------------------*/
368/*---------------------------------------------------------------------------*/
369
370/*!
371 * \brief Creation of a material.
372 *
373 * Creates a material named \a name, in environment \a env, with
374 * info \a infos.
375 */
376MeshMaterial* MeshMaterialMng::
377_createMaterial(MeshEnvironment* env, MeshMaterialInfo* infos, const String& name)
378{
379 _checkEndCreate();
380 if (infos->materialMng() != this)
381 ARCANE_FATAL("Invalid materialMng() for material info");
382 if (env->materialMng() != this)
383 ARCANE_FATAL("Invalid materialMng() for environment");
384 Integer var_index = m_variables_indexer.size();
385 Int16 mat_id = CheckedConvert::toInt16(m_materials.size());
386 MeshMaterial* mat = new MeshMaterial(infos, env, name, mat_id);
387 info() << "Create material name=" << name << "mat_id=" << mat_id << " var_index=" << var_index;
388 mat->build();
389 m_materials.add(mat);
390 m_materials_as_components.add(mat);
391 m_true_materials.add(mat);
392
393 _addVariableIndexer(mat->variableIndexer());
394 return mat;
395}
396
397/*---------------------------------------------------------------------------*/
398/*---------------------------------------------------------------------------*/
399
400MeshMaterialInfo* MeshMaterialMng::
401registerMaterialInfo(const String& name)
402{
403 _checkEndCreate();
404 // Check that the material is not already registered.
405 MeshMaterialInfo* old_mmi = _findMaterialInfo(name);
406 if (old_mmi)
407 ARCANE_FATAL("A material named '{0}' is already registered", name);
408
409 MeshMaterialInfo* mmi = new MeshMaterialInfo(this, name);
410 m_materials_info.add(mmi);
411 return mmi;
412}
413
414/*---------------------------------------------------------------------------*/
415/*---------------------------------------------------------------------------*/
416
417/*!
418 * \brief Creation of an environment.
419 *
420 * The environment info is provided by the structure \a infos.
421 * Along with the environment, all constituent materials are created.
422 */
423IMeshEnvironment* MeshMaterialMng::
424createEnvironment(const MeshEnvironmentBuildInfo& infos)
425{
426 _checkEndCreate();
427 Int16 env_index = CheckedConvert::toInt16(m_environments.size());
428 // Check that an environment with the same name does not exist.
429 const String& env_name = infos.name();
430 MeshEnvironment* old_me = _findEnvironment(env_name);
431 if (old_me)
432 ARCANE_FATAL("An environment named '{0}' is already registered", env_name);
433
434 info() << "Creating environment name=" << env_name << " index=" << env_index;
435 // Create the environment
436 MeshEnvironment* me = new MeshEnvironment(this, env_name, env_index);
437 me->build();
438 m_true_environments.add(me);
439 m_environments.add(me);
440 m_environments_as_components.add(me);
441
442 // Create and add the materials
443 Integer nb_mat = infos.materials().size();
444 ConstArrayView<MeshEnvironmentBuildInfo::MatInfo> mat_build_infos = infos.materials();
445 for (Integer i = 0; i < nb_mat; ++i) {
446 const MeshEnvironmentBuildInfo::MatInfo& buildinfo = mat_build_infos[i];
447 const String& mat_name = buildinfo.m_name;
448 String new_mat_name = env_name + "_" + mat_name;
449 MeshMaterialInfo* mat_info = _findMaterialInfo(mat_name);
450 if (!mat_info) {
451 ARCANE_FATAL("No material named '{0}' is defined", mat_name);
452 }
453 MeshMaterial* mm = _createMaterial(me, mat_info, new_mat_name);
454 me->addMaterial(mm);
455 mat_info->_addEnvironment(env_name);
456 }
457 // If the environment contains multiple materials, it must be allocated
458 // with partial values. Otherwise, its partial values are those
459 // of its unique material.
460 {
461 MeshMaterialVariableIndexer* var_idx = nullptr;
462 if (nb_mat == 1) {
463 var_idx = me->materials()[0]->_internalApi()->variableIndexer();
464 }
465 else {
466 var_idx = new MeshMaterialVariableIndexer(traceMng(), me->name());
467 _addVariableIndexer(var_idx);
468 m_variables_indexer_to_destroy.add(var_idx);
469 }
470 me->setVariableIndexer(var_idx);
471 }
472 return me;
473}
474
475/*---------------------------------------------------------------------------*/
476/*---------------------------------------------------------------------------*/
477
478IMeshBlock* MeshMaterialMng::
479createBlock(const MeshBlockBuildInfo& infos)
480{
481 _checkEndCreate();
482
483 Int32 block_index = m_blocks.size();
484 // Checks that a block with the same name does not exist.
485 const String& name = infos.name();
486 const MeshBlock* old_mb = _findBlock(name);
487 if (old_mb)
488 ARCANE_FATAL("Un bloc de nom '{0}' est déjà enregistré", name);
489
490 info() << "Creating block name=" << name << " index=" << block_index
491 << " nb_env=" << infos.environments().size();
492 Integer nb_env = infos.environments().size();
493 for (Integer i = 0; i < nb_env; ++i)
494 info() << " Adding environment name=" << infos.environments()[i]->name() << " to block";
495
496 // Create the block
497 MeshBlock* mb = new MeshBlock(this, block_index, infos);
498 mb->build();
499 m_true_blocks.add(mb);
500 m_blocks.add(mb);
501
502 return mb;
503}
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
508void MeshMaterialMng::
509addEnvironmentToBlock(IMeshBlock* block, IMeshEnvironment* env)
510{
511 MeshBlock* mb = ARCANE_CHECK_POINTER(dynamic_cast<MeshBlock*>(block));
512 mb->addEnvironment(env);
513}
514
515/*---------------------------------------------------------------------------*/
516/*---------------------------------------------------------------------------*/
517
518void MeshMaterialMng::
519removeEnvironmentToBlock(IMeshBlock* block, IMeshEnvironment* env)
520{
521 MeshBlock* mb = ARCANE_CHECK_POINTER(dynamic_cast<MeshBlock*>(block));
522 mb->removeEnvironment(env);
523}
524
525/*---------------------------------------------------------------------------*/
526/*---------------------------------------------------------------------------*/
527
528void MeshMaterialMng::
529endCreate(bool is_continue)
530{
531 if (m_is_end_create)
532 return;
533
534 _saveInfosInProperties();
535
536 info() << "END CREATE MATERIAL_MNG is_continue=" << is_continue;
537
538 m_modifier = std::make_unique<MeshMaterialModifierImpl>(this);
539 m_modifier->initOptimizationFlags();
540
541 m_all_env_data->endCreate(is_continue);
542
543 auto synchronizer = mesh()->cellFamily()->allItemsSynchronizer();
544 m_all_cells_mat_env_synchronizer = std::make_unique<MeshMaterialVariableSynchronizer>(this, synchronizer, MatVarSpace::MaterialAndEnvironment);
545 m_all_cells_env_only_synchronizer = std::make_unique<MeshMaterialVariableSynchronizer>(this, synchronizer, MatVarSpace::Environment);
546
547 // Determines the list of all components.
548 {
549 Integer nb_component = m_environments_as_components.size() + m_materials_as_components.size();
550 m_components.reserve(nb_component);
551 m_components.addRange(m_environments_as_components);
552 m_components.addRange(m_materials_as_components);
553 }
554
555 // It is necessary to build and initialize the variables that were
556 // created before this allocation.
557 for (const auto& i : m_full_name_variable_map) {
558 IMeshMaterialVariable* mv = i.second;
559 info(4) << "BUILD FROM MANAGER name=" << mv->name() << " this=" << this;
560 mv->buildFromManager(is_continue);
561 }
562 if (is_continue)
563 _endUpdate();
564 m_is_end_create = true;
565
566 // Checks that the environments are valid.
567 // NOTE: we cannot always call checkValid()
568 // (especially at startup) because the entity groups exist,
569 // but the associated material info are not
570 // necessarily created yet.
571 // (It will be necessary to check if this is due to compatible mode or not).
572 for (IMeshEnvironment* env : m_environments) {
573 env->checkValid();
574 }
575
576 // Now that everything is created, it is valid to register the mechanisms
577 // of exchange.
578 m_exchange_mng->registerFactory();
579}
580
581/*---------------------------------------------------------------------------*/
582/*---------------------------------------------------------------------------*/
583
584void MeshMaterialMng::
585setModificationFlags(int v)
586{
587 _checkEndCreate();
588 m_modification_flags = v;
589 info() << "Setting ModificationFlags to v=" << v;
590}
591
592/*---------------------------------------------------------------------------*/
593/*---------------------------------------------------------------------------*/
594
595void MeshMaterialMng::
596setAllocateScalarEnvironmentVariableAsMaterial(bool v)
597{
598 _checkEndCreate();
599 m_is_allocate_scalar_environment_variable_as_material = v;
600 info() << "Setting AllocateScalarEnvironmentVariableAsMaterial to v=" << v;
601}
602
603/*---------------------------------------------------------------------------*/
604/*---------------------------------------------------------------------------*/
605
606void MeshMaterialMng::
607setDataCompressorServiceName(const String& name)
608{
609 m_data_compressor_service_name = name;
610}
611
612/*---------------------------------------------------------------------------*/
613/*---------------------------------------------------------------------------*/
614
615MeshMaterialModifierImpl* MeshMaterialMng::
616_modifier()
617{
618 return m_modifier.get();
619}
620
621/*---------------------------------------------------------------------------*/
622/*---------------------------------------------------------------------------*/
623
624MeshMaterialInfo* MeshMaterialMng::
625_findMaterialInfo(const String& name)
626{
627 for (MeshMaterialInfo* mmi : m_materials_info)
628 if (mmi->name() == name)
629 return mmi;
630 return nullptr;
631}
632
633/*---------------------------------------------------------------------------*/
634/*---------------------------------------------------------------------------*/
635
636IMeshEnvironment* MeshMaterialMng::
637findEnvironment(const String& name, bool throw_exception)
638{
639 IMeshEnvironment* env = _findEnvironment(name);
640 if (env)
641 return env;
642 if (throw_exception)
643 ARCANE_FATAL("No environment named '{0}'", name);
644 return nullptr;
645}
646
647/*---------------------------------------------------------------------------*/
648/*---------------------------------------------------------------------------*/
649
650MeshEnvironment* MeshMaterialMng::
651_findEnvironment(const String& name)
652{
653 for (MeshEnvironment* env : m_true_environments)
654 if (env->name() == name)
655 return env;
656 return nullptr;
657}
658
659/*---------------------------------------------------------------------------*/
660/*---------------------------------------------------------------------------*/
661
662IMeshBlock* MeshMaterialMng::
663findBlock(const String& name, bool throw_exception)
664{
665 IMeshBlock* block = _findBlock(name);
666 if (block)
667 return block;
668 if (throw_exception)
669 ARCANE_FATAL("No block named '{0}'", name);
670 return nullptr;
671}
672
673/*---------------------------------------------------------------------------*/
674/*---------------------------------------------------------------------------*/
675
676MeshBlock* MeshMaterialMng::
677_findBlock(const String& name)
678{
679 for (MeshBlock* b : m_true_blocks)
680 if (b->name() == name)
681 return b;
682 return nullptr;
683}
684
685/*---------------------------------------------------------------------------*/
686/*---------------------------------------------------------------------------*/
687
688void MeshMaterialMng::
689forceRecompute()
690{
691 _endUpdate();
692}
693
694/*---------------------------------------------------------------------------*/
695/*---------------------------------------------------------------------------*/
696
697/*!
698 * \brief Updates the structures following a modification of material or
699 * environment cells.
700 */
701void MeshMaterialMng::
702_endUpdate()
703{
704 m_all_env_data->forceRecompute(true);
705}
706
707/*---------------------------------------------------------------------------*/
708/*---------------------------------------------------------------------------*/
709
710/*!
711 * \brief Updates the variable references.
712 *
713 * This must be done when the number of elements per material or environment
714 * changes because the arrays containing the associated variables may be
715 * modified during the operation.
716 */
717void MeshMaterialMng::
718syncVariablesReferences(bool check_resize)
719{
720 for (const auto& i : m_full_name_variable_map) {
721 IMeshMaterialVariable* mv = i.second;
722 info(4) << "SYNC REFERENCES FROM MANAGER name=" << mv->name();
723 mv->_internalApi()->syncReferences(check_resize);
724 }
725}
726
727/*---------------------------------------------------------------------------*/
728/*---------------------------------------------------------------------------*/
729
730void MeshMaterialMng::
731visitVariables(IFunctorWithArgumentT<IMeshMaterialVariable*>* functor)
732{
733 if (!functor)
734 return;
735 for (const auto& i : m_full_name_variable_map) {
736 IMeshMaterialVariable* mv = i.second;
737 functor->executeFunctor(mv);
738 }
739}
740
741/*---------------------------------------------------------------------------*/
742/*---------------------------------------------------------------------------*/
743
744void MeshMaterialMng::
745checkValid()
746{
747 const IItemFamily* cell_family = mesh()->cellFamily();
748 ItemGroup all_cells = cell_family->allItems();
749 ConstArrayView<Int16> nb_env_per_cell = m_all_env_data->componentConnectivityList()->cellsNbEnvironment();
750 ENUMERATE_ALLENVCELL (iallenvcell, view(all_cells.view().localIds())) {
751 AllEnvCell all_env_cell = *iallenvcell;
752 Integer cell_nb_env = all_env_cell.nbEnvironment();
753 Cell cell = all_env_cell.globalCell();
754 Int64 cell_uid = cell.uniqueId();
755 if (all_env_cell.level() != LEVEL_ALLENVIRONMENT)
756 ARCANE_FATAL("Bad level for all_env_item");
757
758 if (all_env_cell.globalCell() != cell)
759 ARCANE_FATAL("Bad corresponding globalCell() in all_env_item");
760 if (cell_nb_env != nb_env_per_cell[cell.localId()])
761 ARCANE_FATAL("Bad value for nb_env direct='{0}' var='{1}'",
762 cell_nb_env, nb_env_per_cell[cell.localId()]);
763 for (Integer z = 0; z < cell_nb_env; ++z) {
764 EnvCell ec = all_env_cell.cell(z);
765 Integer cell_nb_mat = ec.nbMaterial();
766 matimpl::ConstituentItemBase eii = ec.constituentItemBase();
767 if (all_env_cell.constituentItemBase() != eii._superItemBase())
768 ARCANE_FATAL("Bad corresponding allEnvItem() in env_item uid={0}", cell_uid);
769 if (eii.globalItemBase() != cell)
770 ARCANE_FATAL("Bad corresponding globalItem() in env_item");
771 if (eii.level() != LEVEL_ENVIRONMENT)
772 ARCANE_FATAL("Bad level '{0}' for in env_item", eii.level());
773 // If the cell is not pure, the environment variable cannot be equivalent to
774 // the global variable.
775 if (cell_nb_env > 1 && ec._varIndex().arrayIndex() == 0)
776 ARCANE_FATAL("Global index for a partial cell env_item={0}", ec);
777
778 for (Integer k = 0; k < cell_nb_mat; ++k) {
779 MatCell mc = ec.cell(k);
780 matimpl::ConstituentItemBase mci = mc.constituentItemBase();
781 if (eii != mci._superItemBase())
782 ARCANE_FATAL("Bad corresponding env_item in mat_item k={0} mc={1}", k, mc);
783 if (mci.globalItemBase() != cell)
784 ARCANE_FATAL("Bad corresponding globalItem() in mat_item");
785 if (mci.level() != LEVEL_MATERIAL)
786 ARCANE_FATAL("Bad level '{0}' for in mat_item", mci.level());
787 // If the cell is not pure, the material variable cannot be equivalent to
788 // the global variable.
789 if ((cell_nb_env > 1 || cell_nb_mat > 1) && mc._varIndex().arrayIndex() == 0) {
790 ARCANE_FATAL("Global index for a partial cell matitem={0} name={1} nb_mat={2} nb_env={3}",
791 mc, mc.material()->name(), cell_nb_mat, cell_nb_env);
792 }
793 }
794 }
795 }
796
797 for (IMeshEnvironment* env : m_environments) {
798 env->checkValid();
799 }
800}
801
802/*---------------------------------------------------------------------------*/
803/*---------------------------------------------------------------------------*/
804
805IMeshMaterialVariable* MeshMaterialMng::
806findVariable(const String& name)
807{
808 IMeshMaterialVariable* v = _findVariableFullyQualified(name);
809 if (v)
810 return v;
811
812 // Searches for the global variable named \a name
813 // and if found, takes its full name for
814 // the material variable.
815 const IVariable* global_var = m_variable_mng->findMeshVariable(mesh(), name);
816 if (global_var) {
817 v = _findVariableFullyQualified(global_var->fullName());
818 if (v)
819 return v;
820 }
821
822 return nullptr;
823}
824
825/*---------------------------------------------------------------------------*/
826/*---------------------------------------------------------------------------*/
827
828IMeshMaterialVariable* MeshMaterialMng::
829_findVariableFullyQualified(const String& name)
830{
831 auto i = m_full_name_variable_map.find(name);
832 if (i != m_full_name_variable_map.end())
833 return i->second;
834 return nullptr;
835}
836
837/*---------------------------------------------------------------------------*/
838/*---------------------------------------------------------------------------*/
839
840IMeshMaterialVariable* MeshMaterialMng::
841checkVariable(IVariable* global_var)
842{
843 auto i = m_var_to_mat_var_map.find(global_var);
844 if (i != m_var_to_mat_var_map.end())
845 return i->second;
846 return nullptr;
847}
848
849/*---------------------------------------------------------------------------*/
850/*---------------------------------------------------------------------------*/
851
852void MeshMaterialMng::
853fillWithUsedVariables(Array<IMeshMaterialVariable*>& variables)
854{
855 variables.clear();
856
857 // Uses the map based on variable names to ensure the same
858 // traversal order regardless of sub-domains.
859 for (const auto& i : m_full_name_variable_map) {
860 IMeshMaterialVariable* ivar = i.second;
861 if (ivar->globalVariable()->isUsed())
862 variables.add(ivar);
863 }
864}
865
866/*---------------------------------------------------------------------------*/
867/*---------------------------------------------------------------------------*/
868
869void MeshMaterialMng::
870_addVariable(IMeshMaterialVariable* var)
871{
872 //TODO: the lock m_variable_lock must be active.
873 IVariable* gvar = var->globalVariable();
874 info(4) << "MAT_ADD_VAR global_var=" << gvar << " var=" << var << " this=" << this;
875 m_var_to_mat_var_map.insert(std::make_pair(gvar, var));
876 m_full_name_variable_map.insert(std::make_pair(gvar->fullName(), var));
877}
878
879/*---------------------------------------------------------------------------*/
880/*---------------------------------------------------------------------------*/
881
882void MeshMaterialMng::
883_removeVariable(IMeshMaterialVariable* var)
884{
885 //TODO: the lock m_variable_lock must be active.
886 IVariable* gvar = var->globalVariable();
887 info(4) << "MAT:Remove variable global_var=" << gvar << " var=" << var;
888 m_var_to_mat_var_map.erase(gvar);
889 m_full_name_variable_map.erase(gvar->fullName());
890}
891
892/*---------------------------------------------------------------------------*/
893/*---------------------------------------------------------------------------*/
894
895void MeshMaterialMng::
896dumpInfos(std::ostream& o)
897{
898 Integer nb_mat = m_materials.size();
899 Integer nb_env = m_environments.size();
900 Integer nb_var_idx = m_variables_indexer.size();
901 o << "-- Infos sur les milieux et matériaux\n";
902 o << "-- Nb Materiaux: " << nb_mat << '\n';
903 o << "-- Nb Milieux: " << nb_env << '\n';
904 o << "-- Nb Variables partielles: " << nb_var_idx << '\n';
905
906 o << "-- Liste des matériaux\n";
907 for (IMeshMaterial* mat : m_materials) {
908 o << "-- Materiau name=" << mat->name() << '\n';
909 }
910
911 o << "-- Liste des milieux\n";
912 for (IMeshEnvironment* me : m_environments) {
913 ConstArrayView<IMeshMaterial*> env_materials = me->materials();
914 const MeshMaterialVariableIndexer* env_var_idx = me->_internalApi()->variableIndexer();
915 Integer nb_env_mat = env_materials.size();
916 o << "-- Milieu name=" << me->name()
917 << " nb_mat=" << nb_env_mat
918 << " nb_cell=" << me->cells().size()
919 << " var_idx = " << env_var_idx->index()
920 << " ids=" << env_var_idx->matvarIndexes()
921 << '\n';
922 for (IMeshMaterial* mm : env_materials) {
923 const MeshMaterialVariableIndexer* idx = mm->_internalApi()->variableIndexer();
924 o << "-- Materiau\n";
925 o << "-- name = " << mm->name() << "\n";
926 o << "-- nb_cell = " << mm->cells().size() << "\n";
927 o << "-- var_idx = " << idx->index() << "\n";
928 }
929 }
930}
931
932/*---------------------------------------------------------------------------*/
933/*---------------------------------------------------------------------------*/
934
935// TODO: merge dumpInfos2() and dumpInfo().
936void MeshMaterialMng::
937dumpInfos2(std::ostream& o)
938{
939 const ConstituentConnectivityList& constituent_list = *m_all_env_data->componentConnectivityList();
940 ConstArrayView<Int16> nb_env_per_cell = constituent_list.cellsNbEnvironment();
941 Integer nb_mat = m_materials.size();
942 Integer nb_env = m_environments.size();
943 Integer nb_var_idx = m_variables_indexer.size();
944 o << "-- Material and Environment infos: nb_env=" << nb_env
945 << " nb_mat=" << nb_mat << " timestamp=" << m_timestamp
946 << " nb_var_idx=" << nb_var_idx
947 << "\n";
948 Integer nb_cell = mesh()->allCells().size();
949 if (nb_cell != 0) {
950 Integer nb_pure_env = 0;
951 ENUMERATE_CELL (icell, mesh()->allCells()) {
952 if (nb_env_per_cell[icell.localId()] <= 1)
953 ++nb_pure_env;
954 }
955 o << " nb_cell=" << nb_cell << " nb_pure_env=" << nb_pure_env
956 << " nb_partial=" << (nb_cell - nb_pure_env)
957 << " percent=" << (100 * nb_pure_env) / nb_cell
958 << "\n";
959 }
960
961 o << "-- Liste des milieux\n";
962 for (MeshEnvironment* me : m_true_environments) {
963 ConstArrayView<IMeshMaterial*> env_materials = me->materials();
964 const MeshMaterialVariableIndexer* env_var_idx = me->variableIndexer();
965 const Int16 env_id = me->componentId();
966 Integer nb_env_mat = env_materials.size();
967 Integer nb_env_cell = me->cells().size();
968 Integer nb_pure_mat = 0;
969 if (nb_env_mat > 1) {
970 ENUMERATE_CELL (icell, me->cells()) {
971 if (constituent_list.cellNbMaterial(icell, env_id) <= 1)
972 ++nb_pure_mat;
973 }
974 }
975 else
976 nb_pure_mat = nb_env_cell;
977 o << "-- Env name=" << me->name()
978 << " nb_mat=" << nb_env_mat
979 << " var_idx=" << env_var_idx->index()
980 << " nb_cell=" << nb_env_cell
981 << " nb_pure_mat=" << nb_pure_mat;
982 if (nb_env_cell != 0)
983 o << " percent=" << (nb_pure_mat * 100) / nb_env_cell;
984 o << '\n';
985 for (Integer j = 0; j < nb_env_mat; ++j) {
986 IMeshMaterial* mm = env_materials[j];
987 const MeshMaterialVariableIndexer* idx = mm->_internalApi()->variableIndexer();
988 o << "-- Mat name=" << mm->name()
989 << " nb_cell=" << mm->cells().size()
990 << " var_idx=" << idx->index()
991 << "\n";
992 }
993 }
994}
995
996/*---------------------------------------------------------------------------*/
997/*---------------------------------------------------------------------------*/
998
999bool MeshMaterialMng::
1000synchronizeMaterialsInCells()
1001{
1002 return m_mms->synchronizeMaterialsInCells();
1003}
1004
1005/*---------------------------------------------------------------------------*/
1006/*---------------------------------------------------------------------------*/
1007
1008void MeshMaterialMng::
1009checkMaterialsInCells(Integer max_print)
1010{
1011 m_mms->checkMaterialsInCells(max_print);
1012}
1013
1014/*---------------------------------------------------------------------------*/
1015/*---------------------------------------------------------------------------*/
1016
1017void MeshMaterialMng::
1018dumpCellInfos(Cell cell, std::ostream& o)
1019{
1020 CellToAllEnvCellConverter all_env_cell_converter(this);
1021 AllEnvCell all_env_cell = all_env_cell_converter[cell];
1022 Cell global_cell = all_env_cell.globalCell();
1023 o << "Cell uid=" << ItemPrinter(global_cell) << '\n';
1024 ENUMERATE_CELL_ENVCELL (ienvcell, all_env_cell) {
1025 o << "ENV name=" << (*ienvcell).environment()->name()
1026 << " component_idx=" << ComponentItemLocalId(ienvcell) << '\n';
1027 ENUMERATE_CELL_MATCELL (imatcell, (*ienvcell)) {
1028 o << "MAT name=" << (*imatcell).material()->name()
1029 << " component_idx=" << ComponentItemLocalId(imatcell) << '\n';
1030 }
1031 }
1032}
1033
1034/*---------------------------------------------------------------------------*/
1035/*---------------------------------------------------------------------------*/
1036
1037CellToAllEnvCellConverter MeshMaterialMng::
1038cellToAllEnvCellConverter()
1039{
1040 return CellToAllEnvCellConverter(componentItemSharedInfo(LEVEL_ALLENVIRONMENT));
1041}
1042
1043/*---------------------------------------------------------------------------*/
1044/*---------------------------------------------------------------------------*/
1045
1046void MeshMaterialMng::
1047_checkEndCreate()
1048{
1049 if (m_is_end_create)
1050 ARCANE_FATAL("Invalid method call because endCreate() has already been called");
1051}
1052
1053/*---------------------------------------------------------------------------*/
1054/*---------------------------------------------------------------------------*/
1055
1056AllEnvCellVectorView MeshMaterialMng::
1057_view(SmallSpan<const Int32> local_ids)
1058{
1059 return AllEnvCellVectorView(local_ids.constSmallView(), componentItemSharedInfo(LEVEL_ALLENVIRONMENT));
1060}
1061
1062/*---------------------------------------------------------------------------*/
1063/*---------------------------------------------------------------------------*/
1064
1065class MeshMaterialMngFactory
1067{
1068 public:
1069
1070 MeshMaterialMngFactory()
1071 {
1072 IMeshMaterialMng::_internalSetFactory(this);
1073 }
1074 ~MeshMaterialMngFactory()
1075 {
1076 IMeshMaterialMng::_internalSetFactory(nullptr);
1077 }
1078
1079 public:
1080
1081 Ref<IMeshMaterialMng> getTrueReference(const MeshHandle& mesh_handle, bool is_create) override;
1082
1083 public:
1084
1085 static MeshMaterialMngFactory m_mesh_material_mng_factory;
1086};
1087
1088MeshMaterialMngFactory MeshMaterialMngFactory::m_mesh_material_mng_factory{};
1089
1090/*---------------------------------------------------------------------------*/
1091/*---------------------------------------------------------------------------*/
1092
1093Ref<IMeshMaterialMng> MeshMaterialMngFactory::
1094getTrueReference(const MeshHandle& mesh_handle, bool is_create)
1095{
1096 //TODO: implement lock for multi-threading
1097 typedef AutoDestroyUserData<Ref<IMeshMaterialMng>> UserDataType;
1098
1099 const char* name = "MeshMaterialMng_StdMat";
1100 IUserDataList* udlist = mesh_handle.meshUserDataList();
1101
1102 IUserData* ud = udlist->data(name, true);
1103 if (!ud) {
1104 if (!is_create)
1105 return {};
1106 IMeshMaterialMng* mm = arcaneCreateMeshMaterialMng(mesh_handle, "StdMat");
1107 Ref<IMeshMaterialMng> mm_ref = makeRef(mm);
1108 udlist->setData(name, new UserDataType(new Ref<IMeshMaterialMng>(mm_ref)));
1109 return mm_ref;
1110 }
1111 auto adud = dynamic_cast<UserDataType*>(ud);
1112 if (!adud)
1113 ARCANE_FATAL("Can not cast to IMeshMaterialMng*");
1114 return *(adud->data());
1115}
1116
1117/*---------------------------------------------------------------------------*/
1118/*---------------------------------------------------------------------------*/
1119
1120bool MeshMaterialMng::
1121isInMeshMaterialExchange() const
1122{
1123 return m_exchange_mng->isInMeshMaterialExchange();
1124}
1125
1126/*---------------------------------------------------------------------------*/
1127/*---------------------------------------------------------------------------*/
1128
1129void MeshMaterialMng::
1130_checkCreateProperties()
1131{
1132 if (m_properties)
1133 return;
1134 m_properties = std::make_unique<Properties>(*(mesh()->properties()), String("MeshMaterialMng_") + name());
1135}
1136
1137/*---------------------------------------------------------------------------*/
1138/*---------------------------------------------------------------------------*/
1139namespace
1140{
1141 const Int32 SERIALIZE_VERSION = 1;
1142}
1143void MeshMaterialMng::
1144_saveInfosInProperties()
1145{
1146 _checkCreateProperties();
1147
1148 // Save the version number to ensure compatibility during recovery
1149 m_properties->set("Version", SERIALIZE_VERSION);
1150
1151 // Save the necessary information in the properties to recreate the
1152 // materials and environments.
1153 UniqueArray<String> material_info_names;
1154 for (MeshMaterialInfo* mat_info : m_materials_info) {
1155 material_info_names.add(mat_info->name());
1156 }
1157 m_properties->set("MaterialInfoNames", material_info_names);
1158
1159 UniqueArray<String> env_names;
1160 UniqueArray<Int32> env_nb_mat;
1161 UniqueArray<String> env_mat_names;
1162 ENUMERATE_ENV (ienv, this) {
1163 IMeshEnvironment* env = *ienv;
1164 env_names.add(env->name());
1165 info(5) << "SAVE ENV_NAME name=" << env->name() << " nb_mat=" << env->nbMaterial();
1166 env_nb_mat.add(env->nbMaterial());
1167 ENUMERATE_MAT (imat, env) {
1168 const String& name = (*imat)->infos()->name();
1169 info(5) << "SAVE MAT_NAME name=" << name;
1170 env_mat_names.add(name);
1171 }
1172 }
1173 m_properties->set("EnvNames", env_names);
1174 m_properties->set("EnvNbMat", env_nb_mat);
1175 m_properties->set("EnvMatNames", env_mat_names);
1176
1177 // Save the necessary information for the blocks.
1178 // For each block, its name and the name of the corresponding cell group.
1179 UniqueArray<String> block_names;
1180 UniqueArray<String> block_cell_group_names;
1181 UniqueArray<Int32> block_nb_env;
1182 UniqueArray<String> block_env_names;
1183 for (IMeshBlock* block : m_blocks) {
1184 block_names.add(block->name());
1185 block_cell_group_names.add(block->cells().name());
1186 block_nb_env.add(block->nbEnvironment());
1187 ENUMERATE_ENV (ienv, block) {
1188 const String& name = (*ienv)->name();
1189 info(5) << "SAVE BLOCK ENV_NAME name=" << name;
1190 block_env_names.add(name);
1191 }
1192 }
1193 m_properties->set("BlockNames", block_names);
1194 m_properties->set("BlockCellGroupNames", block_cell_group_names);
1195 m_properties->set("BlockNbEnv", block_nb_env);
1196 m_properties->set("BlockEnvNames", block_env_names);
1197}
1198
1199/*---------------------------------------------------------------------------*/
1200/*---------------------------------------------------------------------------*/
1201
1202void MeshMaterialMng::
1203recreateFromDump()
1204{
1205 if (m_is_end_create)
1206 ARCANE_FATAL("Can not recreate a created instance");
1207
1208 _checkCreateProperties();
1209
1210 info() << "Creating material infos from dump";
1211
1212 // Save the version number to ensure compatibility during recovery
1213 Int32 v = m_properties->getInt32("Version");
1214 if (v != SERIALIZE_VERSION)
1215 ARCANE_FATAL("Bad serializer version: trying to read from incompatible checkpoint v={0} expected={1}",
1216 v, SERIALIZE_VERSION);
1217
1218 UniqueArray<String> material_info_names;
1219 m_properties->get("MaterialInfoNames", material_info_names);
1220 for (const String& mat_name : material_info_names)
1221 this->registerMaterialInfo(mat_name);
1222
1223 UniqueArray<String> env_names;
1224 UniqueArray<Int32> env_nb_mat;
1225 UniqueArray<String> env_mat_names;
1226 m_properties->get("EnvNames", env_names);
1227 m_properties->get("EnvNbMat", env_nb_mat);
1228 m_properties->get("EnvMatNames", env_mat_names);
1229
1230 Integer mat_index = 0;
1231 for (Integer ienv = 0, nenv = env_names.size(); ienv < nenv; ++ienv) {
1232 Materials::MeshEnvironmentBuildInfo env_build(env_names[ienv]);
1233 Integer nb_mat = env_nb_mat[ienv];
1234 for (Integer imat = 0; imat < nb_mat; ++imat) {
1235 env_build.addMaterial(env_mat_names[mat_index]);
1236 ++mat_index;
1237 }
1238 this->createEnvironment(env_build);
1239 }
1240
1241 // Recreate the blocks.
1242 // For each block, its name and the name of the corresponding cell group.
1243 UniqueArray<String> block_names;
1244 UniqueArray<String> block_cell_group_names;
1245 UniqueArray<String> block_env_names;
1246 UniqueArray<Int32> block_nb_env;
1247 m_properties->get("BlockNames", block_names);
1248 m_properties->get("BlockCellGroupNames", block_cell_group_names);
1249 m_properties->get("BlockNbEnv", block_nb_env);
1250 m_properties->get("BlockEnvNames", block_env_names);
1251 const IItemFamily* cell_family = mesh()->cellFamily();
1252 Integer block_env_index = 0;
1253 for (Integer i = 0, n = block_names.size(); i < n; ++i) {
1254 String name = block_names[i];
1255 String cell_group_name = block_cell_group_names[i];
1256 CellGroup cells = cell_family->findGroup(cell_group_name);
1257 if (cells.null())
1258 ARCANE_FATAL("Can not find cell group '{0}' for block creation",
1259 cell_group_name);
1260 MeshBlockBuildInfo mbbi(name, cells);
1261 if (!block_nb_env.empty()) {
1262 Integer nb_env = block_nb_env[i];
1263 for (Integer ienv = 0; ienv < nb_env; ++ienv) {
1264 const String& name2 = block_env_names[block_env_index];
1265 ++block_env_index;
1266 IMeshEnvironment* env = findEnvironment(name2, false);
1267 if (!env)
1268 ARCANE_FATAL("Invalid environment name '{0}' for recreating blocks", name2);
1269 mbbi.addEnvironment(env);
1270 }
1271 }
1272 this->createBlock(mbbi);
1273 }
1274
1275 endCreate(true);
1276}
1277
1278/*---------------------------------------------------------------------------*/
1279/*---------------------------------------------------------------------------*/
1280
1281void MeshMaterialMng::
1282_onMeshDestroyed()
1283{
1284 // This instance must be destroyed here because it requires IItemFamily
1285 // in its destructor, and it is possible that the family no longer exists
1286 // if the IMeshMaterialMng destructor is called after the mesh destruction
1287 // (which can happen in C# for example).
1288 m_exchange_mng.reset();
1289
1290 _unregisterAllVariables();
1291}
1292
1293/*---------------------------------------------------------------------------*/
1294/*---------------------------------------------------------------------------*/
1295
1296void MeshMaterialMng::
1297_unregisterAllVariables()
1298{
1299 // Copy all references into an array.
1300 // This must be done before calling unregisterVariable()
1301 // because the latter modifies the linked list of references
1302 UniqueArray<MeshMaterialVariableRef*> m_all_refs;
1303
1304 for (const auto& i : m_full_name_variable_map) {
1305 const IMeshMaterialVariable* var = i.second;
1306
1307 for (MeshMaterialVariableRef::Enumerator iref(var); iref.hasNext(); ++iref) {
1308 MeshMaterialVariableRef* ref = *iref;
1309 m_all_refs.add(ref);
1310 }
1311 }
1312
1313 for (MeshMaterialVariableRef* ref : m_all_refs)
1314 ref->unregisterVariable();
1315}
1316
1317/*---------------------------------------------------------------------------*/
1318/*---------------------------------------------------------------------------*/
1319
1320ComponentItemSharedInfo* MeshMaterialMng::
1321componentItemSharedInfo(Int32 level) const
1322{
1323 ComponentItemInternalData* data = m_all_env_data->componentItemInternalData();
1324 ComponentItemSharedInfo* shared_info = nullptr;
1325 if (level == LEVEL_MATERIAL)
1326 shared_info = data->matSharedInfo();
1327 else if (level == LEVEL_ENVIRONMENT)
1328 shared_info = data->envSharedInfo();
1329 else if (level == LEVEL_ALLENVIRONMENT)
1330 shared_info = data->allEnvSharedInfo();
1331 else
1332 ARCANE_FATAL("Bad internal type of component");
1333
1334 return shared_info;
1335}
1336
1337/*---------------------------------------------------------------------------*/
1338/*---------------------------------------------------------------------------*/
1339
1340void MeshMaterialMng::
1341_dumpStats()
1342{
1343 IEnumeratorTracer* tracer = IEnumeratorTracer::singleton();
1344 if (tracer)
1345 tracer->dumpStats();
1346
1347 if (m_modifier)
1348 m_modifier->dumpStats();
1349
1350 for (IMeshEnvironment* env : m_environments) {
1351 // Do not display statistics if the environment has only one material
1352 // because it uses the same indexer as the material and the statistics
1353 // for it will be displayed when iterating over the materials.
1354 if (env->nbMaterial() > 1)
1355 env->_internalApi()->variableIndexer()->dumpStats();
1356 }
1357 for (IMeshMaterial* mat : m_materials) {
1358 mat->_internalApi()->variableIndexer()->dumpStats();
1359 }
1360}
1361
1362/*---------------------------------------------------------------------------*/
1363/*---------------------------------------------------------------------------*/
1364
1365void MeshMaterialMng::
1366createAllCellToAllEnvCell()
1367{
1368 if (!m_accelerator_envcell_container) {
1369 m_accelerator_envcell_container = std::make_unique<AllCellToAllEnvCellContainer>(this);
1370 m_accelerator_envcell_container->initialize();
1371 }
1372}
1373
1374/*---------------------------------------------------------------------------*/
1375/*---------------------------------------------------------------------------*/
1376
1377SmallSpan<const Int32> MeshMaterialMng::
1378identitySelectionView()
1379{
1380 // NOTE: this array could perhaps be managed directly
1381 // by the family if there is interest in using it in other contexts
1382 Int32 max_local_id = m_mesh_handle.mesh()->cellFamily()->maxLocalId();
1383 {
1384 std::scoped_lock sl(m_indexed_selection_identity_mutex);
1385 Int32 size = m_indexed_selection_identity.size();
1386 if (max_local_id > size) {
1387 m_indexed_selection_identity.resize(max_local_id);
1388 for (Int32 i = size; i < max_local_id; ++i)
1389 m_indexed_selection_identity[i] = i;
1390 }
1391 return m_indexed_selection_identity.constView();
1392 }
1393}
1394
1395/*---------------------------------------------------------------------------*/
1396/*---------------------------------------------------------------------------*/
1397
1398} // End namespace Arcane::Materials
1399
1400/*---------------------------------------------------------------------------*/
1401/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
Memory and allocator management functions.
UserData that self-destructs once detached.
Interface of a list that manages user data.
virtual void setData(const String &name, IUserData *ud)=0
Sets the user data associated with the name name.
virtual IUserData * data(const String &name, bool allow_null=false) const =0
Data associated with name.
Interface for user data attached to another object.
Definition IUserData.h:33
Interface for the material and environment manager of a mesh.
Handle on a mesh.
Definition MeshHandle.h:48
IUserDataList * meshUserDataList() const
Associated user data.
Definition MeshHandle.h:158
Reference to an instance.
#define ENUMERATE_ENV(ienv, container)
Macro to iterate over a list of environments.
#define ENUMERATE_CELL_MATCELL(iname, env_cell)
Macro to iterate over all MatCell cells of a cell.
#define ENUMERATE_CELL_ENVCELL(iname, all_env_cell)
Macro to iterate over all EnvCell cells of a cell.
#define ENUMERATE_ALLENVCELL(iname,...)
Macro to iterate over all AllEnvCell cells of a group.
#define ENUMERATE_MAT(imat, container)
Macro to iterate over a list of materials.
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
RunQueue makeQueue(const Runner &runner)
Creates a queue associated with runner.
eExecutionPolicy
Execution policy for a Runner.
@ Thread
Multi-threaded execution policy.
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indicates if exec_policy corresponds to an accelerator.
Always enables tracing in Arcane parts concerning materials.
IMemoryAllocator * getDefaultDataAllocator()
Default allocator for data.
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
Int32 Integer
Type representing an integer.
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
Memory management utility functions.