Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ConstituentConnectivityList.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/* ConstituentConnectivityList.cc (C) 2000-2024 */
9/* */
10/* Management of constituent connectivity lists. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/internal/ConstituentConnectivityList.h"
15
16#include "arcane/core/IItemFamily.h"
17
18#include "arcane/utils/ITraceMng.h"
20#include "arcane/core/internal/IDataInternal.h"
21#include "arcane/core/internal/IItemFamilyInternal.h"
22
23#include "arcane/materials/internal/MeshMaterialMng.h"
24
25#include "arcane/accelerator/core/RunQueue.h"
26#include "arcane/accelerator/RunCommandLoop.h"
27#include "arcane/accelerator/Scan.h"
28#include "arcane/accelerator/Reduce.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::Materials
34{
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace
39{
40 // This method is the same as MeshUtils::removeItemAndKeepOrder().
41 // It would be necessary to merge the two.
42 // NOTE: With C++20, we should be able to remove this method and
43 // use std::erase()
44
45 template <typename DataType>
46 ARCCORE_HOST_DEVICE void _removeValueAndKeepOrder(ArrayView<DataType> values, DataType value_to_remove)
47 {
48 Integer n = values.size();
49#ifndef ARCCORE_DEVICE_CODE
50 if (n <= 0)
51 ARCANE_FATAL("Can not remove item lid={0} because list is empty", value_to_remove);
52#endif
53 --n;
54 if (n == 0) {
55 if (values[0] == value_to_remove)
56 return;
57 }
58 else {
59 // If the element is the last one, do nothing.
60 if (values[n] == value_to_remove)
61 return;
62 for (Integer i = 0; i < n; ++i) {
63 if (values[i] == value_to_remove) {
64 for (Integer z = i; z < n; ++z)
65 values[z] = values[z + 1];
66 return;
67 }
68 }
69 }
70#if defined(ARCCORE_DEVICE_CODE)
71 // With Intel DPC++ 2024.1, using this function with the
72 // CUDA backend causes an error in the generated assembly.
73#if !defined(__INTEL_LLVM_COMPILER)
74 assert(false);
75#endif
76#else
77 ARCANE_FATAL("No value to remove '{0}' found in list {1}", value_to_remove, values);
78#endif
79 }
80
81} // namespace
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
85
90{
91 public:
92
96 class View
97 {
98 public:
99
100 explicit View(ConstituentContainer& c)
101 : nb_components_view(c.m_nb_component_as_array.view())
102 , component_indexes_view(c.m_component_index_as_array.view())
103 , component_list_view(c.m_component_list_as_array.view())
104 {
105 }
106
107 public:
108
109 ARCCORE_HOST_DEVICE SmallSpan<const Int16> components(Int32 item_lid) const
110 {
111 Int16 n = nb_components_view[item_lid];
112 Int32 index = component_indexes_view[item_lid];
113 return component_list_view.subPart(index, n);
114 }
115
116 private:
117
118 SmallSpan<Int16> nb_components_view;
119 SmallSpan<Int32> component_indexes_view;
120 SmallSpan<Int16> component_list_view;
121 };
122
123 public:
124
125 ConstituentContainer(const MeshHandle& mesh, const String& var_base_name)
126 : m_nb_component(VariableBuildInfo(mesh, var_base_name + "NbComponent", IVariable::PPrivate))
127 , m_component_index(VariableBuildInfo(mesh, var_base_name + "Index", IVariable::PPrivate))
128 , m_component_list(VariableBuildInfo(mesh, var_base_name + "List", IVariable::PPrivate))
129 , m_nb_component_as_array(m_nb_component._internalTrueData()->_internalDeprecatedValue())
130 , m_component_index_as_array(m_component_index._internalTrueData()->_internalDeprecatedValue())
131 , m_component_list_as_array(m_component_list._internalTrueData()->_internalDeprecatedValue())
132 {
133 }
134
135 public:
136
137 void endCreate(bool is_continue)
138 {
139 if (!is_continue)
140 _resetConnectivities();
141 }
142
143 ArrayView<Int16> components(CellLocalId item_lid)
144 {
145 Int16 n = m_nb_component[item_lid];
146 Int32 index = m_component_index[item_lid];
147 //Int32 list_size = m_component_list.size();
148 //std::cout << "CELL=" << item_lid << " nb_mat=" << n
149 // << " index=" << index << " list_size=" << list_size << "\n";
150 return m_component_list_as_array.subView(index, n);
151 }
152
153 void checkResize(Int64 size)
154 {
155 if (MeshUtils::checkResizeArray(m_nb_component_as_array, size, false))
157 if (MeshUtils::checkResizeArray(m_component_index_as_array, size, false))
159 }
160
161 void reserve(Int64 capacity)
162 {
163 m_nb_component_as_array.reserve(capacity);
164 m_component_index_as_array.reserve(capacity);
165 }
166
167 void changeLocalIds(Int32ConstArrayView new_to_old_ids)
168 {
169 m_nb_component.variable()->compact(new_to_old_ids);
170 m_component_index.variable()->compact(new_to_old_ids);
171 }
172
173 void notifyUpdateConnectivityList()
174 {
175 m_component_list.updateFromInternal();
176 }
177
179 {
180 _resetConnectivities();
181 }
182
183 private:
184
191
192 public:
193
194 VariableArrayInt16::ContainerType& m_nb_component_as_array;
195 VariableArrayInt32::ContainerType& m_component_index_as_array;
196 VariableArrayInt16::ContainerType& m_component_list_as_array;
197
198 private:
199
200 void _resetConnectivities()
201 {
202 m_nb_component.fill(0);
203 m_component_index.fill(0);
204 // The first element of the list is used for empty constituents
205 m_component_list.resize(1);
206 m_component_list[0] = 0;
207 }
208};
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
217{
218 public:
219
220 NumberOfMaterialComputer(ConstituentContainer::View view,
221 SmallSpan<const Int16> environment_for_materials)
222 : m_view(view)
223 , m_environment_for_materials(environment_for_materials)
224 {
225 }
226
227 public:
228
229 ARCCORE_HOST_DEVICE Int16 cellNbMaterial(Int32 cell_local_id, Int16 env_id) const
230 {
231 auto mats = m_view.components(cell_local_id);
232 Int16 nb_mat = 0;
233 for (Int16 mat_id : mats) {
234 Int16 current_id = m_environment_for_materials[mat_id];
235 if (current_id == env_id)
236 ++nb_mat;
237 }
238 return nb_mat;
239 }
240
241 private:
242
246};
247
248/*---------------------------------------------------------------------------*/
249/*---------------------------------------------------------------------------*/
250
252{
253 public:
254
255 Container(const MeshHandle& mesh, const String& var_base_name)
256 : m_environment(mesh, var_base_name + String("ComponentEnvironment"))
257 , m_material(mesh, var_base_name + String("ComponentMaterial"))
258 {
259 }
260
261 public:
262
263 void checkResize(Int32 lid)
264 {
265 Int64 wanted_size = lid + 1;
266 m_environment.checkResize(wanted_size);
267 m_material.checkResize(wanted_size);
268 }
269
270 void changeLocalIds(Int32ConstArrayView new_to_old_ids)
271 {
272 m_environment.changeLocalIds(new_to_old_ids);
273 m_material.changeLocalIds(new_to_old_ids);
274 }
275
276 void reserve(Int64 capacity)
277 {
278 m_environment.reserve(capacity);
279 m_material.reserve(capacity);
280 }
281
282 public:
283
284 ConstituentContainer m_environment;
285 ConstituentContainer m_material;
286};
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
291ConstituentConnectivityList::
292ConstituentConnectivityList(MeshMaterialMng* mm)
293: TraceAccessor(mm->traceMng())
294, m_material_mng(mm)
295, m_container(new Container(mm->meshHandle(), String("ComponentEnviroment") + mm->name()))
296{
297 // Indicates if modification is forced in fillModifiedConstituents()
298 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_MATERIAL_FORCE_TRANSFORM", true)) {
299 m_is_force_transform_all_constituants = (v.value() != 0);
300 info() << "Force transformation in 'ConstituentConnectivityList' v=" << m_is_force_transform_all_constituants;
301 }
302}
303
304/*---------------------------------------------------------------------------*/
305/*---------------------------------------------------------------------------*/
306
307ConstituentConnectivityList::
308~ConstituentConnectivityList()
309{
310 delete m_container;
311}
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
316void ConstituentConnectivityList::
317endCreate(bool is_continue)
318{
319 // Now (February 2024) we always build incremental connectivities
320 const bool always_build_connectivity = true;
321
322 // Registers with the family to be notified of changes
323 // but only if incremental modification support was requested
324 // to avoid unnecessarily consuming memory.
325 // Eventually, we will do it all the time
326 m_cell_family = m_material_mng->mesh()->cellFamily();
327 {
328 int opt_flag_value = m_material_mng->modificationFlags();
329 bool use_incremental = (opt_flag_value & (int)eModificationFlags::IncrementalRecompute) != 0;
330 if (use_incremental || always_build_connectivity) {
331 m_cell_family->_internalApi()->addSourceConnectivity(this);
332 m_is_active = true;
333 info() << "Activating incremental material connectivities";
334 }
335 }
336 if (!is_continue) {
337 Int32 max_local_id = m_cell_family->maxLocalId();
338 m_container->checkResize(max_local_id + 1);
339 m_container->m_environment.endCreate(is_continue);
340 m_container->m_material.endCreate(is_continue);
341 }
342
343 // Fills an array indicating the index
344 // of the corresponding environment for each material index.
345 {
346 ConstArrayView<MeshMaterial*> materials = m_material_mng->trueMaterials();
347 const Int32 nb_mat = materials.size();
348 auto environment_for_materials = m_environment_for_materials.hostModifier();
349 environment_for_materials.resize(nb_mat);
350 auto local_view = environment_for_materials.view();
351 for (Int32 i = 0; i < nb_mat; ++i)
352 local_view[i] = materials[i]->trueEnvironment()->componentId();
353 }
354}
355
356/*---------------------------------------------------------------------------*/
357/*---------------------------------------------------------------------------*/
358
359void ConstituentConnectivityList::
360_addCells(Int16 component_id, SmallSpan<const Int32> cells_local_id,
361 ConstituentContainer& component, RunQueue& queue)
362{
363 const Int32 nb_item = cells_local_id.size();
364 if (nb_item == 0)
365 return;
366 Array<Int16>& nb_component = component.m_nb_component_as_array;
367 Array<Int32>& component_index = component.m_component_index_as_array;
368 Array<Int16>& component_list = component.m_component_list_as_array;
369
370 SmallSpan<Int16> nb_component_view = component.m_nb_component_as_array.view();
371
372 // TODO: Use persistent working arrays.
373 NumArray<Int32, MDDim1> new_indexes(nb_item, queue.memoryRessource());
374 // To copy the number of elements to add from the device to the CPU
375 NumArray<Int32, MDDim1> new_indexes_to_add(1, eMemoryRessource::HostPinned);
376
377 // Calculates the index of the new elements
378 {
379 Accelerator::GenericScanner scanner(queue);
380 SmallSpan<Int32> new_indexes_view = new_indexes;
381 SmallSpan<Int32> new_indexes_to_add_view = new_indexes_to_add;
382 auto getter = [=] ARCCORE_HOST_DEVICE(Int32 index) -> Int32 {
383 return 1 + nb_component_view[cells_local_id[index]];
384 };
385 auto setter = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 value) {
386 new_indexes_view[index] = value;
387 if (index == (nb_item - 1))
388 new_indexes_to_add_view[0] = new_indexes_view[index] + nb_component_view[cells_local_id[index]] + 1;
389 };
390 Accelerator::ScannerSumOperator<Int32> op;
391 scanner.applyWithIndexExclusive(nb_item, 0, getter, setter, op, A_FUNCINFO);
392 }
393 queue.barrier();
394
395 const Int32 nb_indexes_to_add = new_indexes_to_add[0];
396 const Int32 current_list_index = component_list.size();
397
398 MemoryUtils::checkResizeArrayWithCapacity(component_list, current_list_index + nb_indexes_to_add, false);
399
400 {
401 auto command = makeCommand(queue);
402 SmallSpan<Int16> nb_component_view = nb_component.view();
403 SmallSpan<Int32> component_index_view = component_index.view();
404 SmallSpan<Int16> component_list_view = component_list.view();
405 SmallSpan<const Int32> new_indexes_view = new_indexes;
406 command << RUNCOMMAND_LOOP1(iter, nb_item)
407 {
408 auto [i] = iter();
409 Int32 cell_id = cells_local_id[i];
410 const Int16 n = nb_component_view[cell_id];
411 Int32 new_pos = current_list_index + new_indexes_view[i];
412 if (n != 0) {
413 // Copies the old values.
414 // TODO: This leaves holes in the list that must be removed
415 // via compaction.
416 Int32 current_pos = component_index_view[cell_id];
417 SmallSpan<const Int16> current_values(&component_list_view[current_pos], n);
418 SmallSpan<Int16> new_values(&component_list_view[new_pos], n);
419 new_values.copy(current_values);
420 }
421 component_index_view[cell_id] = new_pos;
422 component_list_view[new_pos + n] = component_id;
423 ++nb_component_view[cell_id];
424 };
425 }
426
427 component.notifyUpdateConnectivityList();
428}
429
430/*---------------------------------------------------------------------------*/
431/*---------------------------------------------------------------------------*/
432
433void ConstituentConnectivityList::
434_removeCells(Int16 component_id, SmallSpan<const Int32> cells_local_id,
435 ConstituentContainer& component, RunQueue& queue)
436{
437 SmallSpan<Int16> nb_component = component.m_nb_component_as_array.view();
438 SmallSpan<Int32> component_index = component.m_component_index_as_array.view();
439 SmallSpan<Int16> component_list = component.m_component_list_as_array.view();
440
441 const Int32 n = cells_local_id.size();
442 auto command = makeCommand(queue);
443 command << RUNCOMMAND_LOOP1(iter, n)
444 {
445 auto [i] = iter();
446 Int32 id = cells_local_id[i];
447 //for (Int32 id : cell_ids) {
448 CellLocalId cell_id(id);
449 const Int32 current_pos = component_index[cell_id];
450 const Int32 n = nb_component[cell_id];
451 ArrayView<Int16> current_values(n, &component_list[current_pos]);
452 // Removes the deleted middle element from the list
453 _removeValueAndKeepOrder(current_values, component_id);
454 // Sets an invalid value to indicate that the location is free
455 current_values[n - 1] = (-1);
456 --nb_component[cell_id];
457 };
458}
459
460/*---------------------------------------------------------------------------*/
461/*---------------------------------------------------------------------------*/
462
463void ConstituentConnectivityList::
464addCellsToEnvironment(Int16 env_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
465{
466 _addCells(env_id, cell_ids, m_container->m_environment, queue);
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471
472void ConstituentConnectivityList::
473removeCellsToEnvironment(Int16 env_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
474{
475 _removeCells(env_id, cell_ids, m_container->m_environment, queue);
476}
477
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
480
481void ConstituentConnectivityList::
482addCellsToMaterial(Int16 mat_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
483{
484 _addCells(mat_id, cell_ids, m_container->m_material, queue);
485}
486
487/*---------------------------------------------------------------------------*/
488/*---------------------------------------------------------------------------*/
489
490void ConstituentConnectivityList::
491removeCellsToMaterial(Int16 mat_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
492{
493 _removeCells(mat_id, cell_ids, m_container->m_material, queue);
494}
495
496/*---------------------------------------------------------------------------*/
497/*---------------------------------------------------------------------------*/
498
499ConstArrayView<Int16> ConstituentConnectivityList::
500cellsNbEnvironment() const
501{
502 return m_container->m_environment.m_nb_component_as_array;
503}
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
508ConstArrayView<Int16> ConstituentConnectivityList::
509cellsNbMaterial() const
510{
511 return m_container->m_material.m_nb_component_as_array;
512}
513
514/*---------------------------------------------------------------------------*/
515/*---------------------------------------------------------------------------*/
516
517/*---------------------------------------------------------------------------*/
518/*---------------------------------------------------------------------------*/
519
521cellNbMaterial(CellLocalId cell_id, Int16 env_id) const
522{
523 auto environment_for_materials = m_environment_for_materials.hostView();
524 Int16 nb_mat = 0;
525 ArrayView<Int16> mats = m_container->m_material.components(cell_id);
526 for (Int16 mat_id : mats) {
527 Int16 current_id = environment_for_materials[mat_id];
528 if (current_id == env_id)
529 ++nb_mat;
530 }
531 return nb_mat;
532}
533
534/*---------------------------------------------------------------------------*/
535/*---------------------------------------------------------------------------*/
536
539 SmallSpan<Int16> cells_nb_material, RunQueue& queue)
540{
541 ConstituentContainer::View materials_container_view(m_container->m_material);
542 bool is_device = isAcceleratorPolicy(queue.executionPolicy());
543 auto environment_for_materials = m_environment_for_materials.view(is_device);
544 const Int32 n = cells_local_id.size();
545 auto command = makeCommand(queue);
546 command << RUNCOMMAND_LOOP1(iter, n)
547 {
548 auto [i] = iter();
549 Int32 cell_id = cells_local_id[i];
550 Int16 nb_mat = 0;
551 SmallSpan<const Int16> mats = materials_container_view.components(cell_id);
552 for (Int16 mat_id : mats) {
553 Int16 current_id = environment_for_materials[mat_id];
554 if (current_id == env_id)
555 ++nb_mat;
556 }
557 cells_nb_material[i] = nb_mat;
558 };
559}
560
561/*---------------------------------------------------------------------------*/
562/*---------------------------------------------------------------------------*/
563
566 SmallSpan<bool> cells_do_transform, bool is_add, RunQueue& queue)
567{
568 ConstituentContainer::View materials_container_view(m_container->m_material);
569 bool is_device = queue.isAcceleratorPolicy();
570 auto environment_for_materials = m_environment_for_materials.view(is_device);
571
572 NumberOfMaterialComputer nb_mat_computer(materials_container_view, environment_for_materials);
574 const Int32 n = cells_local_id.size();
575 auto command = makeCommand(queue);
576 Accelerator::ReducerSum2<Int32> sum_transformed(command);
577 command << RUNCOMMAND_LOOP1(iter, n, sum_transformed)
578 {
579 auto [i] = iter();
580 Int32 local_id = cells_local_id[i];
581 bool do_transform = false;
582 // In case of addition, we switch from pure to partial if there are multiple environments or
583 // multiple materials in the environment.
584 // In case of removal, we switch from partial to pure if we are the only material
585 // and the only environment.
586 const Int16 nb_env = cells_nb_env[local_id];
587 if (is_add) {
588 do_transform = (nb_env > 1);
589 if (!do_transform)
590 do_transform = nb_mat_computer.cellNbMaterial(local_id, env_id) > 1;
591 }
592 else {
593 do_transform = (nb_env == 1);
594 if (do_transform)
595 do_transform = nb_mat_computer.cellNbMaterial(local_id, env_id) == 1;
596 }
597 if (do_transform) {
598 cells_do_transform[local_id] = do_transform;
599 sum_transformed.combine(1);
600 }
601 };
602 return sum_transformed.reducedValue();
603}
604
605/*---------------------------------------------------------------------------*/
606/*---------------------------------------------------------------------------*/
607
609fillCellsIsPartial(SmallSpan<const Int32> cells_local_id, Int16 env_id,
610 SmallSpan<bool> cells_is_partial, RunQueue& queue)
611{
612 ConstituentContainer::View materials_container_view(m_container->m_material);
613 bool is_device = queue.isAcceleratorPolicy();
614 auto environment_for_materials = m_environment_for_materials.view(is_device);
615 NumberOfMaterialComputer nb_mat_computer(materials_container_view, environment_for_materials);
617 const Int32 n = cells_local_id.size();
618 auto command = makeCommand(queue);
619
620 command << RUNCOMMAND_LOOP1(iter, n)
621 {
622 auto [i] = iter();
623 Int32 local_id = cells_local_id[i];
624 // We only take the global index if we are the only material and the only
625 // environment in the cell. Otherwise, we take a multiple index
626 bool is_partial = (cells_nb_env[local_id] > 1 || nb_mat_computer.cellNbMaterial(local_id, env_id) > 1);
627 cells_is_partial[i] = is_partial;
628 };
629}
630
631/*---------------------------------------------------------------------------*/
632/*---------------------------------------------------------------------------*/
633
639printConstituents(SmallSpan<const Int32> cells_local_id) const
640{
641 const ConstituentContainer::View materials_view(m_container->m_material);
642 const ConstituentContainer::View environments_view(m_container->m_environment);
643
644 for (Int32 i = 0, n = cells_local_id.size(); i < n; ++i) {
645 Int32 lid = cells_local_id[i];
646 info() << "Cell index=" << i << " lid=" << lid
647 << " materials=" << materials_view.components(lid)
648 << " environments=" << environments_view.components(lid);
649 }
650}
651
652/*---------------------------------------------------------------------------*/
653/*---------------------------------------------------------------------------*/
681 SmallSpan<bool> is_modified_materials,
682 SmallSpan<bool> is_modified_environments,
683 int modified_mat_id, bool is_add, const RunQueue& queue)
684{
685 const Int32 n = cells_local_id.size();
686 if (n <= 0)
687 return;
688
689 bool is_device = queue.isAcceleratorPolicy();
690 const ConstituentContainer::View materials_view(m_container->m_material);
691 const ConstituentContainer::View environments_view(m_container->m_environment);
692 auto env_for_mat = m_environment_for_materials.view(is_device);
693 NumberOfMaterialComputer nb_mat_computer(materials_view, m_environment_for_materials.view(is_device));
694 Int16 modified_env_id = m_environment_for_materials.hostView()[modified_mat_id];
695 ConstArrayView<Int16> cells_nb_environment = cellsNbEnvironment();
696
697 auto command = makeCommand(queue);
698 ITraceMng* tm = traceMng();
699 tm->info(4) << "FillModifiedConstituents modified_mat=" << modified_mat_id
700 << " modified_env=" << modified_env_id << " is_add=" << is_add;
701 const bool force_transform = m_is_force_transform_all_constituants;
702
703 if (force_transform) {
704 // If we force the modification for everyone,
705 // directly fill the array of modified environments and materials
706 command << RUNCOMMAND_LOOP1(iter, n)
707 {
708 auto [i] = iter();
709 const Int32 local_id = cells_local_id[i];
710 SmallSpan<const Int16> cell_envs(environments_view.components(local_id));
711 for (Int16 x : cell_envs)
712 is_modified_environments[x] = true;
713 SmallSpan<const Int16> cell_mats(materials_view.components(local_id));
714 for (Int16 x : cell_mats)
715 is_modified_materials[x] = true;
716 };
717 return;
718 }
719
720 command << RUNCOMMAND_LOOP1(iter, n)
721 {
722 auto [i] = iter();
723 const Int32 local_id = cells_local_id[i];
724 const Int16 nb_mat_in_modified_env = nb_mat_computer.cellNbMaterial(local_id, modified_env_id);
725 const Int16 nb_env = cells_nb_environment[local_id];
726 // No environments in the cell. This is initialization.
727 // No material or environment other than the added one is affected.
728 if (nb_env == 0)
729 return;
730 //tm->info() << "FillModified: Cell lid=" << local_id << " nb_mat_in_modified_env=" << nb_mat_in_modified_env << " nb_env=" << nb_env;
731 SmallSpan<const Int16> cell_envs(environments_view.components(local_id));
732 for (Int16 x : cell_envs) {
733 // Do not process the environment currently being modified
734 if (x == modified_env_id)
735 continue;
736 bool do_transform = false;
737 if (is_add) {
738 // In case of addition, we transform if there is only one environment and it is us
739 // (this is necessarily the case, as we are in the loop of the cell environments)
740 do_transform = nb_env == 1;
741 }
742 else {
743 // I transform if we go from 2 environments to only 1 (I am necessarily this environment
744 // if I am in the loop)
745 do_transform = nb_env == 2;
746 }
747 if (do_transform) {
748 //tm->info() << "FillModified: SetTransform Cell lid=" << local_id << " env=" << x;
749 is_modified_environments[x] = true;
750 }
751 }
752
753 SmallSpan<const Int16> cell_mats(materials_view.components(local_id));
754 for (Int16 x : cell_mats) {
755 // Do not process the material currently being modified
756 if (x == modified_mat_id)
757 continue;
758 bool do_transform = false;
759 Int16 my_env_id = env_for_mat[x];
760 // TODO: calculate only if necessary.
761 Int16 my_mat_nb_env = nb_mat_computer.cellNbMaterial(local_id, my_env_id);
762 //tm->info() << "FillModified: CheckMat lid=" << local_id
763 // << " mat_id=" << x << " mat_env=" << my_env_id
764 // << " my_mat_nb_env=" << my_mat_nb_env;
765 if (is_add) {
766 if (my_env_id != modified_env_id && (nb_mat_in_modified_env != 0))
767 continue;
768 do_transform = (nb_env == 1) && (my_mat_nb_env == 1);
769 }
770 else {
771 // I transform if I am the material of the modified environment and there are only two materials in the environment (because I will become the only material
772 // of the environment)
773 // NOTE: this condition is necessary but does not guarantee that I will
774 // necessarily transform. For now, we leave it this way to not be too
775 // restrictive.
776 do_transform = true;
777 if (nb_env == 1)
778 do_transform = (my_env_id == modified_env_id) && (my_mat_nb_env == 2);
779 }
780 if (do_transform) {
781 //tm->info() << "FillModified: SetTransform Cell lid=" << local_id << " mat=" << x;
782 is_modified_materials[x] = true;
783 }
784 }
785 };
786}
787
788/*---------------------------------------------------------------------------*/
789/*---------------------------------------------------------------------------*/
790
792notifySourceFamilyLocalIdChanged([[maybe_unused]] Int32ConstArrayView new_to_old_ids)
793{
794 m_container->changeLocalIds(new_to_old_ids);
795}
796
797/*---------------------------------------------------------------------------*/
798/*---------------------------------------------------------------------------*/
799
802{
803 Int32 lid = item.localId();
804 m_container->checkResize(lid + 1);
805
806 m_container->m_environment.m_nb_component_as_array[lid] = 0;
807 m_container->m_environment.m_component_index_as_array[lid] = 0;
808
809 m_container->m_material.m_nb_component_as_array[lid] = 0;
810 m_container->m_material.m_component_index_as_array[lid] = 0;
811}
812
813/*---------------------------------------------------------------------------*/
814/*---------------------------------------------------------------------------*/
815
817reserveMemoryForNbSourceItems(Int32 n, [[maybe_unused]] bool pre_alloc_connectivity)
818{
819 info() << "Constituent: reserve=" << n;
820 m_container->reserve(n);
821}
822
823/*---------------------------------------------------------------------------*/
824/*---------------------------------------------------------------------------*/
825
830
831/*---------------------------------------------------------------------------*/
832/*---------------------------------------------------------------------------*/
833
839
840/*---------------------------------------------------------------------------*/
841/*---------------------------------------------------------------------------*/
842
845{
846 m_container->m_environment.removeAllConnectivities();
847 m_container->m_material.removeAllConnectivities();
848}
849
850/*---------------------------------------------------------------------------*/
851/*---------------------------------------------------------------------------*/
852
853} // namespace Arcane::Materials
854
855/*---------------------------------------------------------------------------*/
856/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Utility functions for the mesh.
bool checkResizeArray(Array< DataType > &array, Int64 new_size, bool force_resize)
Resizes an array that is indexed by 'ItemLocalId'.
Definition MeshUtils.h:401
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
1D loop on accelerator with additional arguments.
eExecutionPolicy executionPolicy() const
Execution policy of the queue.
Definition RunQueue.cc:169
bool isAcceleratorPolicy() const
Indicates if the instance is associated with an accelerator.
Definition RunQueue.cc:331
Modifiable view of an array of type T.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sub-view starting from element abegin and containing asize elements.
ArrayView< T > view() const
Mutable view of this array.
Constant view of an array of type T.
Template class for converting a type.
virtual ItemVectorView view(Int32ConstArrayView local_ids)=0
View on the entities.
virtual IItemFamilyInternal * _internalApi()=0
Internal Arcane API.
virtual IItemFamily * cellFamily()=0
Returns the cell family.
virtual TraceMessage info()=0
Stream for an information message.
Interface of a variable.
Definition IVariable.h:40
Index of an Item in a variable.
Definition ItemLocalId.h:42
VariableArrayInt32 m_component_index
Index in m_component_list (Sized according to the number of cells).
VariableArrayInt16 m_nb_component
Number of environments per cell (sized according to the number of cells).
Class for calculating the number of materials in an environment.
SmallSpan< const Int16 > m_environment_for_materials
View indicating the environment associated with the materials.
ConstArrayView< Int16 > cellsNbMaterial() const
Arrays of the total number of materials per cell (indexed by localId()).
void printConstituents(SmallSpan< const Int32 > cells_local_id) const
Displays the constituents of a list of entities.
void fillCellsNbMaterial(SmallSpan< const Int32 > cells_local_id, Int16 env_id, SmallSpan< Int16 > cells_nb_material, RunQueue &queue)
Fills cells_nb_material with the number of materials of environment env_id.
void fillModifiedConstituents(SmallSpan< const Int32 > cells_local_id, SmallSpan< bool > is_modified_materials, SmallSpan< bool > is_modified_environments, int modified_mat_id, bool is_add, const RunQueue &queue)
Fills the constituents affected by a modification.
void notifySourceItemAdded(ItemLocalId item) override
Notifies the connectivity that an entity has been added to the source family.
Int16 cellNbMaterial(CellLocalId cell_id, Int16 env_id)
Number of materials of the cell cell_id for environment index env_id.
ConstArrayView< Int16 > cellsNbEnvironment() const
Arrays of the total number of environments per cell (indexed by localId()).
void notifyReadFromDump() override
Notifies the connectivity that a read has been performed from a dump.
UniqueArray< Int16 > m_environment_for_materials
Index of the environment to which a material belongs.
void notifySourceFamilyLocalIdChanged(Int32ConstArrayView new_to_old_ids) override
Notifies the connectivity that the source family has been compacted.
void removeAllConnectivities()
Removes all connected entities.
Int32 fillCellsToTransform(SmallSpan< const Int32 > cells_local_id, Int16 env_id, SmallSpan< bool > cells_do_transform, bool is_add, RunQueue &queue)
Fills cells_do_transform indicating if the cell transitions from pure to partial.
Ref< IIncrementalItemSourceConnectivity > toSourceReference() override
Returns a reference to the instance.
void reserveMemoryForNbSourceItems(Int32 n, bool pre_alloc_connectivity) override
Reserves memory for n source entities.
void fillCellsIsPartial(SmallSpan< const Int32 > cells_local_id, Int16 env_id, SmallSpan< bool > cells_is_partial, RunQueue &queue)
Fills cells_is_partial indicating if the cell is partial for environment env_id.
Implementation of a material manager.
IMesh * mesh() override
Associated mesh.
int modificationFlags() const override
Flags to parameterize modifications.
Handle on a mesh.
Definition MeshHandle.h:48
Reference to an instance.
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
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
Parameters necessary for building a variable.
void updateFromInternal() override
Updates from the internal part.
VariableRefArrayT< Int32 > VariableArrayInt32
Array variable of 32-bit integer type.
VariableRefArrayT< Int16 > VariableArrayInt16
Array variable of 16-bit integer type.
RunCommand makeCommand(const RunQueue &run_queue)
Creates a command associated with the queue run_queue.
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indicates if exec_policy corresponds to an accelerator.
Always enables tracing in Arcane parts concerning materials.
@ IncrementalRecompute
Indicates that the incremental version of AllEnvData::forceRecompute() is used.
Int32 checkResizeArrayWithCapacity(Array< DataType > &array, Int64 new_size, bool force_resize)
Resizes an array by adding a memory reserve.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482
std::int16_t Int16
Signed integer type of 16 bits.
std::int32_t Int32
Signed integer type of 32 bits.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.