Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
ConstituentConnectivityList.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* Gestion des listes de connectivité des constituants. */
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"
27#include "arcane/accelerator/Scan.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::Materials
34{
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace
39{
40 // Cette méthode est la même que MeshUtils::removeItemAndKeepOrder().
41 // Il faudrait pouvoir fusionner les deux.
42 // NOTE: Avec le C++20, on devrait pouvoir supprimer cette méthode et
43 // utiliser 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 // Si l'élément est le dernier, ne fait rien.
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 // Avec Intel DPC++ 2024.1 l'utilisation de cette fonction avec le
72 // backend CUDA provoque une erreur dans l'assembleur généré.
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/*!
86 * \brief Conteneur des données de connectivité pour un type de constituant.
87 */
89{
90 public:
91
92 /*!
93 * \brief Vue sur une liste de constituants des mailles.
94 */
95 class View
96 {
97 public:
98
99 explicit View(ConstituentContainer& c)
100 : nb_components_view(c.m_nb_component_as_array.view())
101 , component_indexes_view(c.m_component_index_as_array.view())
102 , component_list_view(c.m_component_list_as_array.view())
103 {
104 }
105
106 public:
107
108 ARCCORE_HOST_DEVICE SmallSpan<const Int16> components(Int32 item_lid) const
109 {
110 Int16 n = nb_components_view[item_lid];
111 Int32 index = component_indexes_view[item_lid];
112 return component_list_view.subPart(index, n);
113 }
114
115 private:
116
117 SmallSpan<Int16> nb_components_view;
118 SmallSpan<Int32> component_indexes_view;
119 SmallSpan<Int16> component_list_view;
120 };
121
122 public:
123
124 ConstituentContainer(const MeshHandle& mesh, const String& var_base_name)
125 : m_nb_component(VariableBuildInfo(mesh, var_base_name + "NbComponent", IVariable::PPrivate))
126 , m_component_index(VariableBuildInfo(mesh, var_base_name + "Index", IVariable::PPrivate))
127 , m_component_list(VariableBuildInfo(mesh, var_base_name + "List", IVariable::PPrivate))
128 , m_nb_component_as_array(m_nb_component._internalTrueData()->_internalDeprecatedValue())
129 , m_component_index_as_array(m_component_index._internalTrueData()->_internalDeprecatedValue())
130 , m_component_list_as_array(m_component_list._internalTrueData()->_internalDeprecatedValue())
131 {
132 }
133
134 public:
135
136 void endCreate(bool is_continue)
137 {
138 if (!is_continue)
139 _resetConnectivities();
140 }
141
142 ArrayView<Int16> components(CellLocalId item_lid)
143 {
144 Int16 n = m_nb_component[item_lid];
145 Int32 index = m_component_index[item_lid];
146 //Int32 list_size = m_component_list.size();
147 //std::cout << "CELL=" << item_lid << " nb_mat=" << n
148 // << " index=" << index << " list_size=" << list_size << "\n";
149 return m_component_list_as_array.subView(index, n);
150 }
151
152 void checkResize(Int64 size)
153 {
154 if (MeshUtils::checkResizeArray(m_nb_component_as_array, size, false))
155 m_nb_component.updateFromInternal();
156 if (MeshUtils::checkResizeArray(m_component_index_as_array, size, false))
157 m_component_index.updateFromInternal();
158 }
159
160 void reserve(Int64 capacity)
161 {
162 m_nb_component_as_array.reserve(capacity);
163 m_component_index_as_array.reserve(capacity);
164 }
165
166 void changeLocalIds(Int32ConstArrayView new_to_old_ids)
167 {
168 m_nb_component.variable()->compact(new_to_old_ids);
169 m_component_index.variable()->compact(new_to_old_ids);
170 }
171
172 void notifyUpdateConnectivityList()
173 {
174 m_component_list.updateFromInternal();
175 }
176
177 void removeAllConnectivities()
178 {
179 _resetConnectivities();
180 }
181
182 private:
183
184 //! Nombre de milieux par maille (dimensionné au nombre de mailles)
185 VariableArrayInt16 m_nb_component;
186 //! Indice dans \a m_component_list (Dimensionné au nombre de mailles)
187 VariableArrayInt32 m_component_index;
188 //! Liste des constituants
189 VariableArrayInt16 m_component_list;
190
191 public:
192
193 VariableArrayInt16::ContainerType& m_nb_component_as_array;
194 VariableArrayInt32::ContainerType& m_component_index_as_array;
195 VariableArrayInt16::ContainerType& m_component_list_as_array;
196
197 private:
198
199 void _resetConnectivities()
200 {
201 m_nb_component.fill(0);
202 m_component_index.fill(0);
203 // Le premier élément de la liste est utilisé pour les constituants vides
204 m_component_list.resize(1);
205 m_component_list[0] = 0;
206 }
207};
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211/*!
212 * \brief Classe pour calculer le nombre de matériaux d'un milieu.
213 */
215{
216 public:
217
219 SmallSpan<const Int16> environment_for_materials)
220 : m_view(view)
221 , m_environment_for_materials(environment_for_materials)
222 {
223 }
224
225 public:
226
227 ARCCORE_HOST_DEVICE Int16 cellNbMaterial(Int32 cell_local_id, Int16 env_id) const
228 {
229 auto mats = m_view.components(cell_local_id);
230 Int16 nb_mat = 0;
231 for (Int16 mat_id : mats) {
232 Int16 current_id = m_environment_for_materials[mat_id];
233 if (current_id == env_id)
234 ++nb_mat;
235 }
236 return nb_mat;
237 }
238
239 private:
240
242 //! Vue indiquant le milieu associé aux matériaux
243 SmallSpan<const Int16> m_environment_for_materials;
244};
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
250{
251 public:
252
253 Container(const MeshHandle& mesh, const String& var_base_name)
254 : m_environment(mesh, var_base_name + String("ComponentEnvironment"))
255 , m_material(mesh, var_base_name + String("ComponentMaterial"))
256 {
257 }
258
259 public:
260
261 void checkResize(Int32 lid)
262 {
263 Int64 wanted_size = lid + 1;
264 m_environment.checkResize(wanted_size);
265 m_material.checkResize(wanted_size);
266 }
267
268 void changeLocalIds(Int32ConstArrayView new_to_old_ids)
269 {
270 m_environment.changeLocalIds(new_to_old_ids);
271 m_material.changeLocalIds(new_to_old_ids);
272 }
273
274 void reserve(Int64 capacity)
275 {
276 m_environment.reserve(capacity);
277 m_material.reserve(capacity);
278 }
279
280 public:
281
282 ConstituentContainer m_environment;
283 ConstituentContainer m_material;
284};
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
288
289ConstituentConnectivityList::
290ConstituentConnectivityList(MeshMaterialMng* mm)
291: TraceAccessor(mm->traceMng())
292, m_material_mng(mm)
293, m_container(new Container(mm->meshHandle(), String("ComponentEnviroment") + mm->name()))
294{
295 // Indique si on force la modification dans fillModifiedConstituents()
296 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_MATERIAL_FORCE_TRANSFORM", true)) {
297 m_is_force_transform_all_constituants = (v.value() != 0);
298 info() << "Force transformation in 'ConstituentConnectivityList' v=" << m_is_force_transform_all_constituants;
299 }
300}
301
302/*---------------------------------------------------------------------------*/
303/*---------------------------------------------------------------------------*/
304
305ConstituentConnectivityList::
306~ConstituentConnectivityList()
307{
308 delete m_container;
309}
310
311/*---------------------------------------------------------------------------*/
312/*---------------------------------------------------------------------------*/
313
314void ConstituentConnectivityList::
315endCreate(bool is_continue)
316{
317 // Maintenant (février 2024) on construit toujours les connectivités incrémentales
318 const bool always_build_connectivity = true;
319
320 // S'enregistre auprès la famille pour être notifié des évolutions
321 // mais uniquement si on a demandé le support des modifications incrémentales
322 // pour éviter de consommer inutilement de la mémoire.
323 // A terme on le fera tout le temps
324 m_cell_family = m_material_mng->mesh()->cellFamily();
325 {
326 int opt_flag_value = m_material_mng->modificationFlags();
327 bool use_incremental = (opt_flag_value & (int)eModificationFlags::IncrementalRecompute) != 0;
328 if (use_incremental || always_build_connectivity) {
329 m_cell_family->_internalApi()->addSourceConnectivity(this);
330 m_is_active = true;
331 info() << "Activating incremental material connectivities";
332 }
333 }
334 if (!is_continue) {
335 Int32 max_local_id = m_cell_family->maxLocalId();
336 m_container->checkResize(max_local_id + 1);
337 m_container->m_environment.endCreate(is_continue);
338 m_container->m_material.endCreate(is_continue);
339 }
340
341 // Remplit un tableau indiquant pour chaque index de matériau l'index
342 // du milieu correspondant.
343 {
344 ConstArrayView<MeshMaterial*> materials = m_material_mng->trueMaterials();
345 const Int32 nb_mat = materials.size();
346 auto environment_for_materials = m_environment_for_materials.hostModifier();
347 environment_for_materials.resize(nb_mat);
348 auto local_view = environment_for_materials.view();
349 for (Int32 i = 0; i < nb_mat; ++i)
350 local_view[i] = materials[i]->trueEnvironment()->componentId();
351 }
352}
353
354/*---------------------------------------------------------------------------*/
355/*---------------------------------------------------------------------------*/
356
357void ConstituentConnectivityList::
358_addCells(Int16 component_id, SmallSpan<const Int32> cells_local_id,
359 ConstituentContainer& component, RunQueue& queue)
360{
361 const Int32 nb_item = cells_local_id.size();
362 if (nb_item == 0)
363 return;
364 Array<Int16>& nb_component = component.m_nb_component_as_array;
365 Array<Int32>& component_index = component.m_component_index_as_array;
366 Array<Int16>& component_list = component.m_component_list_as_array;
367
368 SmallSpan<Int16> nb_component_view = component.m_nb_component_as_array.view();
369
370 // TODO: Utiliser des tableaux de travail à conserver.
371 NumArray<Int32, MDDim1> new_indexes(nb_item, queue.memoryRessource());
372 // Pour recopier le nombre d'éléments à ajouter du device vers le CPU
373 NumArray<Int32, MDDim1> new_indexes_to_add(1, eMemoryRessource::HostPinned);
374
375 // Calcul l'index des nouveaux éléments
376 {
377 Accelerator::GenericScanner scanner(queue);
378 SmallSpan<Int32> new_indexes_view = new_indexes;
379 SmallSpan<Int32> new_indexes_to_add_view = new_indexes_to_add;
380 auto getter = [=] ARCCORE_HOST_DEVICE(Int32 index) -> Int32 {
381 return 1 + nb_component_view[cells_local_id[index]];
382 };
383 auto setter = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 value) {
384 new_indexes_view[index] = value;
385 if (index == (nb_item - 1))
386 new_indexes_to_add_view[0] = new_indexes_view[index] + nb_component_view[cells_local_id[index]] + 1;
387 };
388 Accelerator::ScannerSumOperator<Int32> op;
389 scanner.applyWithIndexExclusive(nb_item, 0, getter, setter, op, A_FUNCINFO);
390 }
391 queue.barrier();
392
393 const Int32 nb_indexes_to_add = new_indexes_to_add[0];
394 const Int32 current_list_index = component_list.size();
395
396 MemoryUtils::checkResizeArrayWithCapacity(component_list, current_list_index + nb_indexes_to_add, false);
397
398 {
399 auto command = makeCommand(queue);
400 SmallSpan<Int16> nb_component_view = nb_component.view();
401 SmallSpan<Int32> component_index_view = component_index.view();
402 SmallSpan<Int16> component_list_view = component_list.view();
403 SmallSpan<const Int32> new_indexes_view = new_indexes;
404 command << RUNCOMMAND_LOOP1(iter, nb_item)
405 {
406 auto [i] = iter();
407 Int32 cell_id = cells_local_id[i];
408 const Int16 n = nb_component_view[cell_id];
409 Int32 new_pos = current_list_index + new_indexes_view[i];
410 if (n != 0) {
411 // Recopie les anciennes valeurs.
412 // TODO: cela laisse des trous dans la liste qu'il faudra supprimer
413 // via un compactage.
414 Int32 current_pos = component_index_view[cell_id];
415 SmallSpan<const Int16> current_values(&component_list_view[current_pos], n);
416 SmallSpan<Int16> new_values(&component_list_view[new_pos], n);
417 new_values.copy(current_values);
418 }
419 component_index_view[cell_id] = new_pos;
420 component_list_view[new_pos + n] = component_id;
421 ++nb_component_view[cell_id];
422 };
423 }
424
425 component.notifyUpdateConnectivityList();
426}
427
428/*---------------------------------------------------------------------------*/
429/*---------------------------------------------------------------------------*/
430
431void ConstituentConnectivityList::
432_removeCells(Int16 component_id, SmallSpan<const Int32> cells_local_id,
433 ConstituentContainer& component, RunQueue& queue)
434{
435 SmallSpan<Int16> nb_component = component.m_nb_component_as_array.view();
436 SmallSpan<Int32> component_index = component.m_component_index_as_array.view();
437 SmallSpan<Int16> component_list = component.m_component_list_as_array.view();
438
439 const Int32 n = cells_local_id.size();
440 auto command = makeCommand(queue);
441 command << RUNCOMMAND_LOOP1(iter, n)
442 {
443 auto [i] = iter();
444 Int32 id = cells_local_id[i];
445 //for (Int32 id : cell_ids) {
446 CellLocalId cell_id(id);
447 const Int32 current_pos = component_index[cell_id];
448 const Int32 n = nb_component[cell_id];
449 ArrayView<Int16> current_values(n, &component_list[current_pos]);
450 // Enlève de la liste le milieu supprimé
451 _removeValueAndKeepOrder(current_values, component_id);
452 // Met une valeur invalide pour indiquer que l'emplacement est libre
453 current_values[n - 1] = (-1);
454 --nb_component[cell_id];
455 };
456}
457
458/*---------------------------------------------------------------------------*/
459/*---------------------------------------------------------------------------*/
460
461void ConstituentConnectivityList::
462addCellsToEnvironment(Int16 env_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
463{
464 _addCells(env_id, cell_ids, m_container->m_environment, queue);
465}
466
467/*---------------------------------------------------------------------------*/
468/*---------------------------------------------------------------------------*/
469
470void ConstituentConnectivityList::
471removeCellsToEnvironment(Int16 env_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
472{
473 _removeCells(env_id, cell_ids, m_container->m_environment, queue);
474}
475
476/*---------------------------------------------------------------------------*/
477/*---------------------------------------------------------------------------*/
478
479void ConstituentConnectivityList::
480addCellsToMaterial(Int16 mat_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
481{
482 _addCells(mat_id, cell_ids, m_container->m_material, queue);
483}
484
485/*---------------------------------------------------------------------------*/
486/*---------------------------------------------------------------------------*/
487
488void ConstituentConnectivityList::
489removeCellsToMaterial(Int16 mat_id, SmallSpan<const Int32> cell_ids, RunQueue& queue)
490{
491 _removeCells(mat_id, cell_ids, m_container->m_material, queue);
492}
493
494/*---------------------------------------------------------------------------*/
495/*---------------------------------------------------------------------------*/
496
497ConstArrayView<Int16> ConstituentConnectivityList::
498cellsNbEnvironment() const
499{
500 return m_container->m_environment.m_nb_component_as_array;
501}
502
503/*---------------------------------------------------------------------------*/
504/*---------------------------------------------------------------------------*/
505
506ConstArrayView<Int16> ConstituentConnectivityList::
507cellsNbMaterial() const
508{
509 return m_container->m_material.m_nb_component_as_array;
510}
511
512/*---------------------------------------------------------------------------*/
513/*---------------------------------------------------------------------------*/
514
515/*---------------------------------------------------------------------------*/
516/*---------------------------------------------------------------------------*/
517
518Int16 ConstituentConnectivityList::
519cellNbMaterial(CellLocalId cell_id, Int16 env_id) const
520{
521 auto environment_for_materials = m_environment_for_materials.hostView();
522 Int16 nb_mat = 0;
523 ArrayView<Int16> mats = m_container->m_material.components(cell_id);
524 for (Int16 mat_id : mats) {
525 Int16 current_id = environment_for_materials[mat_id];
526 if (current_id == env_id)
527 ++nb_mat;
528 }
529 return nb_mat;
530}
531
532/*---------------------------------------------------------------------------*/
533/*---------------------------------------------------------------------------*/
534
535void ConstituentConnectivityList::
536fillCellsNbMaterial(SmallSpan<const Int32> cells_local_id, Int16 env_id,
537 SmallSpan<Int16> cells_nb_material, RunQueue& queue)
538{
539 ConstituentContainer::View materials_container_view(m_container->m_material);
540 bool is_device = isAcceleratorPolicy(queue.executionPolicy());
541 auto environment_for_materials = m_environment_for_materials.view(is_device);
542 const Int32 n = cells_local_id.size();
543 auto command = makeCommand(queue);
544 command << RUNCOMMAND_LOOP1(iter, n)
545 {
546 auto [i] = iter();
547 Int32 cell_id = cells_local_id[i];
548 Int16 nb_mat = 0;
549 SmallSpan<const Int16> mats = materials_container_view.components(cell_id);
550 for (Int16 mat_id : mats) {
551 Int16 current_id = environment_for_materials[mat_id];
552 if (current_id == env_id)
553 ++nb_mat;
554 }
555 cells_nb_material[i] = nb_mat;
556 };
557}
558
559/*---------------------------------------------------------------------------*/
560/*---------------------------------------------------------------------------*/
561
562Int32 ConstituentConnectivityList::
563fillCellsToTransform(SmallSpan<const Int32> cells_local_id, Int16 env_id,
564 SmallSpan<bool> cells_do_transform, bool is_add, RunQueue& queue)
565{
566 ConstituentContainer::View materials_container_view(m_container->m_material);
567 bool is_device = queue.isAcceleratorPolicy();
568 auto environment_for_materials = m_environment_for_materials.view(is_device);
569
570 NumberOfMaterialComputer nb_mat_computer(materials_container_view, environment_for_materials);
571 SmallSpan<const Int16> cells_nb_env = cellsNbEnvironment();
572 const Int32 n = cells_local_id.size();
573 auto command = makeCommand(queue);
574 Accelerator::ReducerSum2<Int32> sum_transformed(command);
575 command << RUNCOMMAND_LOOP1(iter, n, sum_transformed)
576 {
577 auto [i] = iter();
578 Int32 local_id = cells_local_id[i];
579 bool do_transform = false;
580 // En cas d'ajout on passe de pure à partiel s'il y a plusieurs milieux ou
581 // plusieurs matériaux dans le milieu.
582 // En cas de suppression, on passe de partiel à pure si on est le seul matériau
583 // et le seul milieu.
584 const Int16 nb_env = cells_nb_env[local_id];
585 if (is_add) {
586 do_transform = (nb_env > 1);
587 if (!do_transform)
588 do_transform = nb_mat_computer.cellNbMaterial(local_id, env_id) > 1;
589 }
590 else {
591 do_transform = (nb_env == 1);
592 if (do_transform)
593 do_transform = nb_mat_computer.cellNbMaterial(local_id, env_id) == 1;
594 }
595 if (do_transform) {
596 cells_do_transform[local_id] = do_transform;
597 sum_transformed.combine(1);
598 }
599 };
600 return sum_transformed.reducedValue();
601}
602
603/*---------------------------------------------------------------------------*/
604/*---------------------------------------------------------------------------*/
605
606void ConstituentConnectivityList::
607fillCellsIsPartial(SmallSpan<const Int32> cells_local_id, Int16 env_id,
608 SmallSpan<bool> cells_is_partial, RunQueue& queue)
609{
610 ConstituentContainer::View materials_container_view(m_container->m_material);
611 bool is_device = queue.isAcceleratorPolicy();
612 auto environment_for_materials = m_environment_for_materials.view(is_device);
613 NumberOfMaterialComputer nb_mat_computer(materials_container_view, environment_for_materials);
614 SmallSpan<const Int16> cells_nb_env = cellsNbEnvironment();
615 const Int32 n = cells_local_id.size();
616 auto command = makeCommand(queue);
617
618 command << RUNCOMMAND_LOOP1(iter, n)
619 {
620 auto [i] = iter();
621 Int32 local_id = cells_local_id[i];
622 // On ne prend l'indice global que si on est le seul matériau et le seul
623 // milieu de la maille. Sinon, on prend un indice multiple
624 bool is_partial = (cells_nb_env[local_id] > 1 || nb_mat_computer.cellNbMaterial(local_id, env_id) > 1);
625 cells_is_partial[i] = is_partial;
626 };
627}
628
629/*---------------------------------------------------------------------------*/
630/*---------------------------------------------------------------------------*/
631/*!
632 * \brief Affiche les constituants d'une liste d'entités
633 * @param cells_local_id Liste des numéros locaux des entitiés
634 */
635void ConstituentConnectivityList::
636printConstituents(SmallSpan<const Int32> cells_local_id) const
637{
638 const ConstituentContainer::View materials_view(m_container->m_material);
639 const ConstituentContainer::View environments_view(m_container->m_environment);
640
641 for (Int32 i = 0, n = cells_local_id.size(); i < n; ++i) {
642 Int32 lid = cells_local_id[i];
643 info() << "Cell index=" << i << " lid=" << lid
644 << " materials=" << materials_view.components(lid)
645 << " environments=" << environments_view.components(lid);
646 }
647}
648
649/*---------------------------------------------------------------------------*/
650/*---------------------------------------------------------------------------*/
651/*!
652 * \brief Remplit les constituants concernés par une modification.
653 *
654 * Les mailles concernées par la modification sont données \a cells_local_id.
655 * \a modified_mat_id est le numéro du matériau ajouté (si \a is_add est vrai)
656 * ou supprimé (si \a is_add est faux).
657 *
658 * Met à \a true les valeurs de \a is_modified_materials et \a is_modified_environments
659 * s'ils sont dans une des mailles de \a cells_local_id.
660 *
661 * Cette méthode permet d'optimiser le calcul des constituants qui seront impactés
662 * par une modification en tentant de déterminer à l'avance ceux qui seront
663 * impactés. Cela permet d'éviter d'appeler des noyaux de calcul (par exemple calculer la liste
664 * de mailles à transformer d'un constituant) si on sait que le constituant n'est pas impacté.
665 *
666 * Il est possible de revenir à l'ancien mécanisme et de supprimer cette optimisation
667 * en remplissant \a is_modified_materials et \a is_modified_environments à \a true pour tout
668 * le monde. Cela est le cas si m_is_force_transform_all_constituants est vrai.
669 *
670 * \note il est important que \a is_modified_materials et \a is_modified_environments soit
671 * vrai si le constituant correspondant est modifié. Sans cela, il y aura une incohérence
672 * dans les constituants. Par contre, ce n'est pas grave si on marque un constituant modifié
673 * et qu'il s'avère que ce n'est pas le cas. Cela signifie juste qu'on va faire des
674 * opérations inutiles (dans MeshMaterialVariableIndexer::transformCells()).
675 */
676void ConstituentConnectivityList::
677fillModifiedConstituents(SmallSpan<const Int32> cells_local_id,
678 SmallSpan<bool> is_modified_materials,
679 SmallSpan<bool> is_modified_environments,
680 int modified_mat_id, bool is_add, const RunQueue& queue)
681{
682 const Int32 n = cells_local_id.size();
683 if (n <= 0)
684 return;
685
686 bool is_device = queue.isAcceleratorPolicy();
687 const ConstituentContainer::View materials_view(m_container->m_material);
688 const ConstituentContainer::View environments_view(m_container->m_environment);
689 auto env_for_mat = m_environment_for_materials.view(is_device);
690 NumberOfMaterialComputer nb_mat_computer(materials_view, m_environment_for_materials.view(is_device));
691 Int16 modified_env_id = m_environment_for_materials.hostView()[modified_mat_id];
692 ConstArrayView<Int16> cells_nb_environment = cellsNbEnvironment();
693
694 auto command = makeCommand(queue);
695 ITraceMng* tm = traceMng();
696 tm->info(4) << "FillModifiedConstituents modified_mat=" << modified_mat_id
697 << " modified_env=" << modified_env_id << " is_add=" << is_add;
698 const bool force_transform = m_is_force_transform_all_constituants;
699
700 if (force_transform) {
701 // Si on force la modification pour tout le monde,
702 // remplit directement le tableau des milieux et matériaux modifiés
703 command << RUNCOMMAND_LOOP1(iter, n)
704 {
705 auto [i] = iter();
706 const Int32 local_id = cells_local_id[i];
707 SmallSpan<const Int16> cell_envs(environments_view.components(local_id));
708 for (Int16 x : cell_envs)
709 is_modified_environments[x] = true;
710 SmallSpan<const Int16> cell_mats(materials_view.components(local_id));
711 for (Int16 x : cell_mats)
712 is_modified_materials[x] = true;
713 };
714 return;
715 }
716
717 command << RUNCOMMAND_LOOP1(iter, n)
718 {
719 auto [i] = iter();
720 const Int32 local_id = cells_local_id[i];
721 const Int16 nb_mat_in_modified_env = nb_mat_computer.cellNbMaterial(local_id, modified_env_id);
722 const Int16 nb_env = cells_nb_environment[local_id];
723 // Pas de milieux dans la maille. Il s'agit de l'initialisation.
724 // Aucun matériau ni milieu autre que celui ajouté n'est concerné.
725 if (nb_env == 0)
726 return;
727 //tm->info() << "FillModified: Cell lid=" << local_id << " nb_mat_in_modified_env=" << nb_mat_in_modified_env << " nb_env=" << nb_env;
728 SmallSpan<const Int16> cell_envs(environments_view.components(local_id));
729 for (Int16 x : cell_envs) {
730 // Ne traite pas le milieu en cours de modification
731 if (x == modified_env_id)
732 continue;
733 bool do_transform = false;
734 if (is_add) {
735 // En cas d'ajout, on se transforme s'il n'y a qu'un milieu et que c'est nous
736 // (c'est forcément le cas, car on est dans la boucle des milieux de la maille)
737 do_transform = nb_env == 1;
738 }
739 else {
740 // Je me transforme si on passe de 2 milieux à 1 seul (je suis forcément ce milieu
741 // si je suis dans la boucle)
742 do_transform = nb_env == 2;
743 }
744 if (do_transform) {
745 //tm->info() << "FillModified: SetTransform Cell lid=" << local_id << " env=" << x;
746 is_modified_environments[x] = true;
747 }
748 }
749
750 SmallSpan<const Int16> cell_mats(materials_view.components(local_id));
751 for (Int16 x : cell_mats) {
752 // Ne traite pas le matériau en cours de modification
753 if (x == modified_mat_id)
754 continue;
755 bool do_transform = false;
756 Int16 my_env_id = env_for_mat[x];
757 // TODO: ne calculer que si nécessaire.
758 Int16 my_mat_nb_env = nb_mat_computer.cellNbMaterial(local_id, my_env_id);
759 //tm->info() << "FillModified: CheckMat lid=" << local_id
760 // << " mat_id=" << x << " mat_env=" << my_env_id
761 // << " my_mat_nb_env=" << my_mat_nb_env;
762 if (is_add) {
763 if (my_env_id != modified_env_id && (nb_mat_in_modified_env != 0))
764 continue;
765 do_transform = (nb_env == 1) && (my_mat_nb_env == 1);
766 }
767 else {
768 // Je me transforme si je suis le matériau du milieu modifié et qu'il n'y
769 // a que deux matériaux dans le milieu (car je vais me retrouver le seul matériau
770 // du milieu)
771 // NOTE: cette condition est nécessaire mais ne garantit par que je vais
772 // forcément me transformer. Pour l'instant on laisse cela pour ne pas être trop
773 // restrictif.
774 do_transform = true;
775 if (nb_env == 1)
776 do_transform = (my_env_id == modified_env_id) && (my_mat_nb_env == 2);
777 }
778 if (do_transform) {
779 //tm->info() << "FillModified: SetTransform Cell lid=" << local_id << " mat=" << x;
780 is_modified_materials[x] = true;
781 }
782 }
783 };
784}
785
786/*---------------------------------------------------------------------------*/
787/*---------------------------------------------------------------------------*/
788
789void ConstituentConnectivityList::
790notifySourceFamilyLocalIdChanged([[maybe_unused]] Int32ConstArrayView new_to_old_ids)
791{
792 m_container->changeLocalIds(new_to_old_ids);
793}
794
795/*---------------------------------------------------------------------------*/
796/*---------------------------------------------------------------------------*/
797
798void ConstituentConnectivityList::
799notifySourceItemAdded(ItemLocalId item)
800{
801 Int32 lid = item.localId();
802 m_container->checkResize(lid + 1);
803
804 m_container->m_environment.m_nb_component_as_array[lid] = 0;
805 m_container->m_environment.m_component_index_as_array[lid] = 0;
806
807 m_container->m_material.m_nb_component_as_array[lid] = 0;
808 m_container->m_material.m_component_index_as_array[lid] = 0;
809}
810
811/*---------------------------------------------------------------------------*/
812/*---------------------------------------------------------------------------*/
813
814void ConstituentConnectivityList::
815reserveMemoryForNbSourceItems(Int32 n, [[maybe_unused]] bool pre_alloc_connectivity)
816{
817 info() << "Constituent: reserve=" << n;
818 m_container->reserve(n);
819}
820
821/*---------------------------------------------------------------------------*/
822/*---------------------------------------------------------------------------*/
823
824void ConstituentConnectivityList::
825notifyReadFromDump()
826{
827}
828
829/*---------------------------------------------------------------------------*/
830/*---------------------------------------------------------------------------*/
831
832Ref<IIncrementalItemSourceConnectivity> ConstituentConnectivityList::
833toSourceReference()
834{
835 return Arccore::makeRef<IIncrementalItemSourceConnectivity>(this);
836}
837
838/*---------------------------------------------------------------------------*/
839/*---------------------------------------------------------------------------*/
840
841void ConstituentConnectivityList::
842removeAllConnectivities()
843{
844 m_container->m_environment.removeAllConnectivities();
845 m_container->m_material.removeAllConnectivities();
846}
847
848/*---------------------------------------------------------------------------*/
849/*---------------------------------------------------------------------------*/
850
851} // namespace Arcane::Materials
852
853/*---------------------------------------------------------------------------*/
854/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur le maillage.
Types et fonctions pour gérer les synchronisations sur les accélérateurs.
Types et macros pour gérer les boucles sur les accélérateurs.
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
Boucle sur accélérateur avec arguments supplémentaires pour les réductions.
virtual void compact(Int32ConstArrayView new_to_old_ids)=0
Compacte les valeurs de la variable.
Conteneur des données de connectivité pour un type de constituant.
Handle sur un maillage.
Definition MeshHandle.h:47
Paramètres nécessaires à la construction d'une variable.
void updateFromInternal() override
Mise à jour à partir de la partie interne.
Array< DataType > ContainerType
Type de la classe gérant la valeur de la variable.
IVariable * variable() const
Variable associée.
Vue modifiable d'un tableau d'un type T.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sous-vue à partir de l'élément abegin et contenant asize éléments.
ArrayView< T > view() const
Vue mutable sur ce tableau.
void fill(ConstReferenceType value)
Remplit le tableau avec la valeur value.
Vue constante d'un tableau de type T.
Vue d'un tableau d'éléments de type T.
Definition Span.h:670
constexpr __host__ __device__ SmallSpan< T, DynExtent > subPart(Int32 abegin, Int32 asize) const
Sous-vue à partir de l'élément abegin et contenant asize éléments.
Definition Span.h:765
Chaîne de caractères unicode.
VariableRefArrayT< Int32 > VariableArrayInt32
Variable tableau de type entier 32 bits.
VariableRefArrayT< Int16 > VariableArrayInt16
Variable tableau de type entier 16 bits.
RunCommand makeCommand(const RunQueue &run_queue)
Créé une commande associée à la file run_queue.
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indique si exec_policy correspond à un accélérateur.
Active toujours les traces dans les parties Arcane concernant les matériaux.
@ IncrementalRecompute
Indique qu'on utilise la version incrémentale de AllEnvData::forceRecompute().
@ HostPinned
Alloue sur l'hôte.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:640
Int32 Integer
Type représentant un entier.