Arcane  v3.15.3.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
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
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
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
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{
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.
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.
void fill(ConstReferenceType value)
Remplit le tableau avec la valeur value.
Vue constante d'un tableau de type T.
Référence à une instance.
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().
Int32 checkResizeArrayWithCapacity(Array< DataType > &array, Int64 new_size, bool force_resize)
Redimensionne un tableau en ajoutant une réserve de mémoire.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:572
Int32 Integer
Type représentant un entier.