Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshMaterialVariableIndexer.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/* MeshMaterialVariableIndexer.cc (C) 2000-2024 */
9/* */
10/* Indexer pour les variables materiaux. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ITraceMng.h"
15#include "arcane/utils/ValueChecker.h"
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ArgumentException.h"
18#include "arcane/utils/NotSupportedException.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/ValueConvert.h"
21#include "arcane/utils/MemoryUtils.h"
22
23#include "arcane/materials/internal/MeshMaterialVariableIndexer.h"
24#include "arcane/materials/internal/ComponentItemListBuilder.h"
25#include "arcane/materials/internal/ConstituentModifierWorkInfo.h"
26
27#include "arcane/accelerator/Filter.h"
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34namespace Arcane::Materials
35{
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39MeshMaterialVariableIndexer::
40MeshMaterialVariableIndexer(ITraceMng* tm, const String& name)
41: TraceAccessor(tm)
42, m_name(name)
43, m_matvar_indexes(platform::getAcceleratorHostMemoryAllocator())
44, m_local_ids(platform::getAcceleratorHostMemoryAllocator())
45{
46 _init();
47 m_matvar_indexes.setDebugName(String("VariableIndexerMatVarIndexes")+name);
48 m_local_ids.setDebugName(String("VariableIndexerLocalIdsIndexes")+name);
49}
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
57void MeshMaterialVariableIndexer::
58_init()
59{
60 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_PRINT_USELESS_TRANSFORMATION", true))
61 m_is_print_useless_transform = (v.value() != 0);
62}
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67void MeshMaterialVariableIndexer::
68endUpdate(const ComponentItemListBuilderOld& builder)
69{
70 ConstArrayView<MatVarIndex> pure_matvar = builder.pureMatVarIndexes();
71 ConstArrayView<MatVarIndex> partial_matvar = builder.partialMatVarIndexes();
72
73 Integer nb_pure = pure_matvar.size();
74 Integer nb_partial = partial_matvar.size();
75 m_matvar_indexes.resize(nb_pure + nb_partial);
76
77 m_matvar_indexes.subView(0, nb_pure).copy(pure_matvar);
78 m_matvar_indexes.subView(nb_pure, nb_partial).copy(partial_matvar);
79
80 Int32ConstArrayView local_ids_in_multiple = builder.partialLocalIds();
81
82 {
83 m_local_ids.resize(nb_pure + nb_partial);
84 Integer index = 0;
85 for (Integer i = 0, n = nb_pure; i < n; ++i) {
86 m_local_ids[index] = pure_matvar[i].valueIndex();
87 ++index;
88 }
89 for (Integer i = 0, n = nb_partial; i < n; ++i) {
90 m_local_ids[index] = local_ids_in_multiple[i];
91 ++index;
92 }
93 }
94
95 // NOTE: a priori, ici on est sur que m_max_index_in_multiple_array vaut
96 // nb_partial+1
97 {
98 Int32 max_index_in_multiple = (-1);
99 for (Integer i = 0; i < nb_partial; ++i) {
100 max_index_in_multiple = math::max(partial_matvar[i].valueIndex(), max_index_in_multiple);
101 }
102 m_max_index_in_multiple_array = max_index_in_multiple;
103 }
104
105 info(4) << "END_UPDATE max_index=" << m_max_index_in_multiple_array;
106}
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
111void MeshMaterialVariableIndexer::
112endUpdateAdd(const ComponentItemListBuilder& builder, RunQueue& queue)
113{
114 SmallSpan<const Int32> pure_indexes = builder.pureIndexes();
115 SmallSpan<const Int32> partial_indexes = builder.partialIndexes();
116
117 Integer nb_pure_to_add = pure_indexes.size();
118 Integer nb_partial_to_add = partial_indexes.size();
120 Integer current_nb_item = nbItem();
121 const Int32 new_size = current_nb_item + total_to_add;
122
123 MemoryUtils::checkResizeArrayWithCapacity(m_matvar_indexes, new_size, false);
124 MemoryUtils::checkResizeArrayWithCapacity(m_local_ids, new_size, false);
125
126 SmallSpan<const Int32> local_ids_in_multiple = builder.partialLocalIds();
129
130 Int32 max_index_in_multiple = m_max_index_in_multiple_array;
131 {
132 auto command = makeCommand(queue);
134 Int32 max_to_add = math::max(nb_pure_to_add, nb_partial_to_add);
135 const Int32 component_index = m_index + 1;
137 {
138 auto [i] = iter();
139 if (i < nb_pure_to_add) {
140 Int32 index = pure_indexes[i];
141 local_ids_view[i] = index;
142 matvar_indexes[i] = MatVarIndex(0, index);
143 }
144 if (i < nb_partial_to_add) {
145 Int32 index = partial_indexes[i];
148 max_index_reducer.combine(index);
149 }
150 };
151 max_index_in_multiple = math::max(max_index_reducer.reducedValue(), m_max_index_in_multiple_array);
152 }
153 m_max_index_in_multiple_array = max_index_in_multiple;
154
155 info(4) << "END_UPDATE_ADD max_index=" << m_max_index_in_multiple_array
156 << " nb_partial_to_add=" << nb_partial_to_add;
157}
158
159/*---------------------------------------------------------------------------*/
160/*---------------------------------------------------------------------------*/
161
162void MeshMaterialVariableIndexer::
163endUpdateRemove(ConstituentModifierWorkInfo& work_info, Integer nb_remove, RunQueue& queue)
164{
165 endUpdateRemoveV2(work_info, nb_remove, queue);
166}
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
171void MeshMaterialVariableIndexer::
172endUpdateRemoveV2(ConstituentModifierWorkInfo& work_info, Integer nb_remove, RunQueue& queue)
173{
174 if (nb_remove == 0)
175 return;
176
177 Integer nb_item = nbItem();
178 Integer orig_nb_item = nb_item;
179
180 info(4) << "EndUpdateRemoveV2 nb_remove=" << nb_remove << " nb_item=" << nb_item;
181
182 if (nb_remove == nb_item) {
183 m_matvar_indexes.clear();
184 m_local_ids.clear();
185 return;
186 }
187
188 bool is_device = isAcceleratorPolicy(queue.executionPolicy());
189 auto saved_matvar_indexes_modifier = work_info.m_saved_matvar_indexes.modifier(is_device);
190 auto saved_local_ids_modifier = work_info.m_saved_local_ids.modifier(is_device);
191
192 saved_matvar_indexes_modifier.resize(nb_remove);
193 saved_local_ids_modifier.resize(nb_remove);
194
195 Accelerator::GenericFilterer filterer(queue);
196 SmallSpan<const bool> removed_cells = work_info.removedCells();
197 Span<MatVarIndex> last_matvar_indexes(saved_matvar_indexes_modifier.view());
198 Span<Int32> last_local_ids(saved_local_ids_modifier.view());
199 Span<Int32> local_ids(m_local_ids);
200 Span<MatVarIndex> matvar_indexes(m_matvar_indexes);
201
202 // Conserve \a nb_remove valeurs en partant de la fin de la liste
203 {
204 Int32 last_index = nb_item - 1;
205 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> bool {
206 Int32 lid = local_ids[last_index - index];
207 return !removed_cells[lid];
208 };
209 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
210 Int32 true_index = (last_index - input_index);
211 if (output_index < nb_remove) {
212 last_matvar_indexes[output_index] = matvar_indexes[true_index];
213 last_local_ids[output_index] = local_ids[true_index];
214 }
215 };
216 filterer.applyWithIndex(orig_nb_item, select_lambda, setter_lambda, A_FUNCINFO);
217 filterer.nbOutputElement();
218 }
219
220 // Remplit les trous des mailles supprimées avec les derniers éléments de la liste
221 {
222 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> bool {
223 Int32 lid = local_ids[index];
224 return removed_cells[lid];
225 };
226 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
227 matvar_indexes[input_index] = last_matvar_indexes[output_index];
228 local_ids[input_index] = last_local_ids[output_index];
229 };
230 filterer.applyWithIndex(orig_nb_item - nb_remove, select_lambda, setter_lambda, A_FUNCINFO);
231 filterer.nbOutputElement();
232 }
233 nb_item -= nb_remove;
234 m_matvar_indexes.resize(nb_item);
235 m_local_ids.resize(nb_item);
236
237 // Vérifie qu'on a bien supprimé autant d'entité que prévu.
238 Integer nb_remove_computed = (orig_nb_item - nb_item);
239 if (nb_remove_computed != nb_remove)
240 ARCANE_FATAL("Bad number of removed material items expected={0} v={1} name={2}",
241 nb_remove, nb_remove_computed, name());
242 info(4) << "END_UPDATE_REMOVE nb_removed=" << nb_remove;
243
244 // TODO: il faut recalculer m_max_index_in_multiple_array
245 // et compacter éventuellement les variables. (pas indispensable)
246}
247
248/*---------------------------------------------------------------------------*/
249/*---------------------------------------------------------------------------*/
250
251void MeshMaterialVariableIndexer::
252changeLocalIds(Int32ConstArrayView old_to_new_ids)
253{
254 this->_changeLocalIdsV2(this, old_to_new_ids);
255}
256
257/*---------------------------------------------------------------------------*/
258/*---------------------------------------------------------------------------*/
259
260void MeshMaterialVariableIndexer::
261_changeLocalIdsV2(MeshMaterialVariableIndexer* var_indexer, Int32ConstArrayView old_to_new_ids)
262{
263 // Nouvelle version du changement des localId() qui ne modifie pas l'ordre
264 // des m_matvar_indexes.
265
266 ITraceMng* tm = var_indexer->traceMng();
267
268 tm->info(4) << "ChangeLocalIdsV2 name=" << var_indexer->name();
269 // Il faut recopier le tableau des localId() car il va être modifié.
270 UniqueArray<Int32> ids_copy(var_indexer->localIds());
271 UniqueArray<MatVarIndex> matvar_indexes_copy(var_indexer->matvarIndexes());
272
273 var_indexer->m_local_ids.clear();
274 var_indexer->m_matvar_indexes.clear();
275
276 Integer nb = ids_copy.size();
277
278 tm->info(4) << "-- -- BEGIN_PROCESSING N=" << ids_copy.size();
279
280 for (Integer i = 0; i < nb; ++i) {
281 Int32 lid = ids_copy[i];
282 Int32 new_lid = old_to_new_ids[lid];
283 tm->info(5) << "I=" << i << " lid=" << lid << " new_lid=" << new_lid;
284
285 if (new_lid != NULL_ITEM_LOCAL_ID) {
286 MatVarIndex mvi = matvar_indexes_copy[i];
287 tm->info(5) << "I=" << i << " new_lid=" << new_lid << " mv=" << mvi;
288 Int32 value_index = mvi.valueIndex();
289 if (mvi.arrayIndex() == 0) {
290 // TODO: Vérifier si value_index, qui contient le localId() de l'entité
291 // ne dois pas être modifié.
292 // Normalement, il faudra avoir:
293 // value_index = new_lid;
294 // Mais cela plante actuellement car comme on ne récupère pas
295 // l'évènement executeReduce() sur les groupes il est possible
296 // que nous n'ayons pas les bons ids. (C'est quand même bizarre...)
297
298 // Variable globale: met à jour le localId() dans le MatVarIndex.
299 var_indexer->m_matvar_indexes.add(MatVarIndex(0, value_index));
300 var_indexer->m_local_ids.add(value_index);
301 }
302 else {
303 // Valeur partielle: rien ne change dans le MatVarIndex
304 var_indexer->m_matvar_indexes.add(mvi);
305 var_indexer->m_local_ids.add(new_lid);
306 }
307 }
308 }
309
310 // TODO: remplir la fin des tableaux avec des valeurs invalides (pour détecter les problèmes)
311 tm->info(4) << "-- -- ChangeLocalIdsV2 END_PROCESSING (V4)"
312 << " indexer_name=" << var_indexer->name()
313 << " nb_ids=" << var_indexer->m_local_ids.size();
314}
315
316/*---------------------------------------------------------------------------*/
317/*---------------------------------------------------------------------------*/
332void MeshMaterialVariableIndexer::
333transformCells(ConstituentModifierWorkInfo& work_info, RunQueue& queue,bool is_from_env)
334{
335 bool is_pure_to_partial = work_info.isAdd();
337
338 Integer nb = nbItem();
339 auto pure_local_ids_modifier = work_info.pure_local_ids.modifier(is_device);
340 auto partial_indexes_modifier = work_info.partial_indexes.modifier(is_device);
341 pure_local_ids_modifier.resize(nb);
342 partial_indexes_modifier.resize(nb);
343
344 SmallSpan<Int32> pure_local_ids = pure_local_ids_modifier.view();
345 SmallSpan<Int32> partial_indexes = partial_indexes_modifier.view();
346 SmallSpan<MatVarIndex> matvar_indexes = m_matvar_indexes.view();
347 SmallSpan<Int32> local_ids = m_local_ids.view();
349
351
352 if (is_pure_to_partial) {
353 // Transformation Pure -> Partial
354 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> bool {
356 if (mvi.arrayIndex() != 0)
357 return false;
358 Int32 local_id = local_ids[index];
359 bool do_transform = transformed_cells[local_id];
360 return do_transform;
361 };
362
363 Int32 max_index_in_multiple_array = m_max_index_in_multiple_array + 1;
364 const Int32 var_index = m_index + 1;
365 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
367 Int32 local_id = local_ids[input_index];
368 pure_local_ids[output_index] = local_id;
369 partial_indexes[output_index] = current_index;
371 };
372 filterer.applyWithIndex(nb, select_lambda, setter_lambda,
373 A_FUNCINFO1("ConstituentsTranformCellsFromPureToPartial"));
374 }
375 else {
376 // Transformation Partial -> Pure
377 auto select_lambda = [=] ARCCORE_HOST_DEVICE(Int32 index) -> bool {
379 if (mvi.arrayIndex() == 0)
380 return false;
381 Int32 local_id = local_ids[index];
382 bool do_transform = transformed_cells[local_id];
383 return do_transform;
384 };
385 auto setter_lambda = [=] ARCCORE_HOST_DEVICE(Int32 input_index, Int32 output_index) {
387 Int32 local_id = local_ids[input_index];
388 Int32 var_index = mvi.valueIndex();
389 pure_local_ids[output_index] = local_id;
390 partial_indexes[output_index] = var_index;
391 matvar_indexes[input_index] = MatVarIndex(0, local_id);
392 };
393 filterer.applyWithIndex(nb, select_lambda, setter_lambda,
394 A_FUNCINFO1("ConstituentsTranformCellsFromPartialToPure"));
395 }
396
397 const Int32 nb_out = filterer.nbOutputElement();
400
401 ++m_nb_transform_called;
402
403 // Normalement la liste retournée ne devrait pas être vide.
404 // Si c'est le cas, cela signifie que l'appel à cette méthode était inutile et que
405 // le calcul des constituants modifiés (via ConstituentConnectivityList::fillModifiedConstituents())
406 // était trop permissif.
407 if (nb_out == 0) {
409 ++m_nb_useless_add_transform;
410 else
411 ++m_nb_useless_remove_transform;
412 if (m_is_print_useless_transform)
413 info() << "VarIndex null transformation modified_name=" << name()
414 << " is_add=" << is_pure_to_partial << " is_from_env=" << is_from_env;
415 }
416
418 m_max_index_in_multiple_array += nb_out;
419}
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
424void MeshMaterialVariableIndexer::
425checkValid()
426{
427 ValueChecker vc(A_FUNCINFO);
428
429 Integer nb_item = nbItem();
430
431 vc.areEqual(nb_item, m_matvar_indexes.size(), "Incoherent size for local ids and matvar indexes");
432
433 // TODO: vérifier que les m_local_ids pour les parties pures correspondent
434 // au m_matvar_indexes.valueIndex() correspondant.
435}
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
439
440void MeshMaterialVariableIndexer::
441dumpStats() const
442{
443 if (m_nb_transform_called == 0)
444 return;
445 Int32 nb_useless_call = m_nb_useless_add_transform + m_nb_useless_remove_transform;
446 Int32 nb_useful_call = m_nb_transform_called - nb_useless_call;
447 info() << "VariableIndexer name=" << name()
448 << " nb_useful_transform=" << nb_useful_call
449 << " nb_useless_add=" << m_nb_useless_add_transform
450 << " nb_useless_remove=" << m_nb_useless_remove_transform;
451}
452
453/*---------------------------------------------------------------------------*/
454/*---------------------------------------------------------------------------*/
455
456} // End namespace Arcane::Materials
457
458/*---------------------------------------------------------------------------*/
459/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
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.
Algorithme générique de filtrage sur accélérateur.
Definition Filter.h:354
Classe pour effectuer une réduction 'max'.
Definition Reduce.h:780
File d'exécution pour un accélérateur.
eExecutionPolicy executionPolicy() const
Politique d'exécution de la file.
Definition RunQueue.cc:168
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Classe d'aide à la construction d'une liste de ComponentItem pour un MeshMaterialVariableIndexer.
Classe d'aide à la construction d'une liste de ComponentItem pour un MeshMaterialVariableIndexer.
Structure de travail utilisée lors de la modification des constituants (via MeshMaterialModifier).
Représente un index sur les variables matériaux et milieux.
Vérification de la validité de certaines valeurs.
Vue constante d'un tableau de type T.
TraceMessage info() const
Flot pour un message d'information.
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.
IMemoryAllocator * getAcceleratorHostMemoryAllocator()
Allocateur spécifique pour les accélérateurs.
Int32 Integer
Type représentant un entier.