Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ItemGroupInternal.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/* ItemGroupInternal.cc (C) 2000-2026 */
9/* */
10/* Partie interne à Arcane de ItemGroup. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/internal/ItemGroupInternal.h"
15
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/ArrayUtils.h"
19#include "arcane/utils/ArgumentException.h"
20#include "arcane/utils/Convert.h"
21
22#include "arcane/core/ItemGroupObserver.h"
23#include "arcane/core/IItemFamily.h"
24#include "arcane/core/IMesh.h"
25#include "arcane/core/ItemPrinter.h"
26#include "arcane/core/MeshPartInfo.h"
28#include "arcane/core/internal/IDataInternal.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39ItemGroupInternal::
40ItemGroupInternal()
41: m_internal_api(this)
42, m_sub_parts_by_type(this)
43{
44 _init();
45}
46
47/*---------------------------------------------------------------------------*/
48/*---------------------------------------------------------------------------*/
49
50ItemGroupInternal::
51ItemGroupInternal(IItemFamily* family, const String& name)
52: m_internal_api(this)
53, m_mesh(family->mesh())
54, m_item_family(family)
55, m_variable_name(String("GROUP_") + family->name() + name)
56, m_is_null(false)
57, m_kind(family->itemKind())
58, m_name(name)
59, m_sub_parts_by_type(this)
60{
61 _init();
62}
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67ItemGroupInternal::
68ItemGroupInternal(IItemFamily* family, ItemGroupImpl* parent, const String& name)
69: m_internal_api(this)
70, m_mesh(parent->mesh())
71, m_item_family(family)
72, m_parent(parent)
73, m_variable_name(String("GROUP_") + m_item_family->name() + name)
74, m_is_null(false)
75, m_kind(family->itemKind())
76, m_name(name)
77, m_sub_parts_by_type(this)
78{
79 _init();
80}
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
84
85ItemGroupInternal::
86~ItemGroupInternal()
87{
88 // (HP) TODO: vérifier qu'il n'y a plus d'observer à cet instant
89 // Ceux des sous-groupes n'ont pas été détruits
90 for (const auto& i : m_observers) {
91 delete i.second;
92 }
93 delete m_variable_items_local_id;
94 delete m_compute_functor;
95}
96
97/*---------------------------------------------------------------------------*/
98/*---------------------------------------------------------------------------*/
99
100void ItemGroupInternal::
101_init()
102{
103 if (m_item_family)
104 m_full_name = m_item_family->fullName() + "_" + m_name;
105
106 // Si un maillage est associé et qu'on n'est un groupe enfant alors les données du groupe
107 // sont conservées dans une variable.
108 if (m_mesh && !m_parent) {
109 int property = IVariable::PSubDomainDepend | IVariable::PPrivate;
110 VariableBuildInfo vbi(m_mesh, m_variable_name, property);
111 m_variable_items_local_id = new VariableArrayInt32(vbi);
112 m_items_local_id = &m_variable_items_local_id->_internalTrueData()->_internalDeprecatedValue();
113 updateTimestamp();
114 }
115
116 m_is_check_simd_padding = arcaneIsCheck();
117 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_CHECK_SIMDPADDING", true)) {
118 m_is_check_simd_padding = (v.value() > 0);
119 m_is_print_check_simd_padding = (v.value() > 1);
120 }
121
122 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_PRINT_APPLYSIMDPADDING", true)) {
123 m_is_print_apply_simd_padding = (v.value() > 0);
124 m_is_print_stack_apply_simd_padding = (v.value() > 1);
125 }
126
127 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_LOCK_FOR_ITEMGROUP_UPDATE", true)) {
128 if (v.value() > 0)
129 m_check_need_update_mutex.create();
130 }
131}
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
136ItemInternalList ItemGroupInternal::
137items() const
138{
139 if (m_item_family)
140 return m_item_family->itemsInternal();
141 return m_mesh->itemsInternal(m_kind);
142}
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147Int32 ItemGroupInternal::
148maxLocalId() const
149{
150 return m_item_family->maxLocalId();
151}
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156ItemInfoListView ItemGroupInternal::
157itemInfoListView() const
158{
159 if (m_item_family)
160 return m_item_family->itemInfoListView();
161 return m_mesh->itemFamily(m_kind)->itemInfoListView();
162}
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
167void ItemGroupInternal::
168resetSubGroups()
169{
170 if (!m_is_all_items)
171 ARCANE_FATAL("Call to _resetSubGroups() is only valid for group of AllItems");
172
173 m_own_group = nullptr;
174 m_ghost_group = nullptr;
175 m_interface_group = nullptr;
176 m_node_group = nullptr;
177 m_edge_group = nullptr;
178 m_face_group = nullptr;
179 m_cell_group = nullptr;
180 m_inner_face_group = nullptr;
181 m_outer_face_group = nullptr;
182 m_active_cell_group = nullptr;
183 m_own_active_cell_group = nullptr;
184 m_active_face_group = nullptr;
185 m_own_active_face_group = nullptr;
186 m_inner_active_face_group = nullptr;
187 m_outer_active_face_group = nullptr;
188 m_level_cell_group.clear();
189 m_own_level_cell_group.clear();
190 m_sub_parts_by_type.clear();
191 m_sub_groups.clear();
192}
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
196
197void ItemGroupInternal::
198notifyExtendObservers(const Int32ConstArrayView* info)
199{
200 ARCANE_ASSERT((!m_need_recompute || m_is_all_items), ("Operation on invalid group"));
201 for (const auto& i : m_observers) {
202 IItemGroupObserver* obs = i.second;
203 obs->executeExtend(info);
204 }
205 if (m_group_index_table.isUsed())
206 m_group_index_table->update();
207}
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211
212void ItemGroupInternal::
213notifyReduceObservers(const Int32ConstArrayView* info)
214{
215 ARCANE_ASSERT((!m_need_recompute || m_is_all_items), ("Operation on invalid group"));
216 for (const auto& i : m_observers) {
217 IItemGroupObserver* obs = i.second;
218 obs->executeReduce(info);
219 }
220 if (m_group_index_table.isUsed())
221 m_group_index_table->update();
222}
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
227void ItemGroupInternal::
228notifyCompactObservers(const Int32ConstArrayView* info)
229{
230 ARCANE_ASSERT((!m_need_recompute || m_is_all_items), ("Operation on invalid group"));
231 for (const auto& i : m_observers) {
232 IItemGroupObserver* obs = i.second;
233 obs->executeCompact(info);
234 }
235 if (m_group_index_table.isUsed())
236 m_group_index_table->compact(info);
237}
238
239/*---------------------------------------------------------------------------*/
240/*---------------------------------------------------------------------------*/
241
242void ItemGroupInternal::
243notifyInvalidateObservers()
244{
245#ifndef NO_USER_WARNING
246#warning "(HP) Assertion need fix"
247#endif /* NO_USER_WARNING */
248 // Cela peut se produire en cas d'invalidation en cascade
249 // ARCANE_ASSERT((!m_need_recompute),("Operation on invalid group"));
250 for (const auto& i : m_observers) {
251 IItemGroupObserver* obs = i.second;
252 obs->executeInvalidate();
253 }
254 if (m_group_index_table.isUsed())
255 m_group_index_table->update();
256}
257
258/*---------------------------------------------------------------------------*/
259/*---------------------------------------------------------------------------*/
260
264void ItemGroupInternal::
265checkIsContiguous()
266{
267 m_is_contiguous = false;
268 Int32ConstArrayView lids = itemsLocalId();
269 if (lids.empty()) {
270 m_is_contiguous = false;
271 return;
272 }
273 Int32 first_lid = lids[0];
274
275 bool is_bad = false;
276 for (Integer i = 0, n = lids.size(); i < n; ++i) {
277 if (lids[i] != (first_lid + i)) {
278 is_bad = true;
279 break;
280 }
281 }
282 if (!is_bad)
283 m_is_contiguous = true;
284}
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
288
289void ItemGroupInternal::
290applySimdPadding()
291{
292 if (m_is_print_apply_simd_padding) {
293 String stack;
294 if (m_is_print_stack_apply_simd_padding)
295 stack = String(" stack=") + platform::getStackTrace();
296 ITraceMng* tm = m_item_family->traceMng();
297 tm->info() << "ApplySimdPadding group_name=" << m_name << stack;
298 }
299 // Fait un padding des derniers éléments du tableau en recopiant la
300 // dernière valeurs.
301 m_internal_api.notifySimdPaddingDone();
302 Arcane::applySimdPadding(mutableItemsLocalId());
303}
304
305/*---------------------------------------------------------------------------*/
306/*---------------------------------------------------------------------------*/
307
334void ItemGroupInternal::
335checkUpdateSimdPadding()
336{
337 if (m_simd_timestamp >= timestamp()) {
338 // Vérifie que le padding est bon
340 if (m_is_print_check_simd_padding && m_item_family) {
341 ITraceMng* tm = m_item_family->traceMng();
342 tm->info() << "check padding name=" << fullName()
343 << " timestamp=" << timestamp()
344 << " simd_timestamp=" << m_simd_timestamp
345 << " size=" << mutableItemsLocalId().size()
346 << " capacity=" << mutableItemsLocalId().capacity();
347 }
348 ArrayUtils::checkSimdPadding(itemsLocalId());
349 }
350 return;
351 }
352 this->applySimdPadding();
353}
354
355/*---------------------------------------------------------------------------*/
356/*---------------------------------------------------------------------------*/
357
358void ItemGroupInternal::
359_removeItems(SmallSpan<const Int32> items_local_id)
360{
361 if (!((!m_need_recompute && !isAllItems()) || (m_transaction_mode && isAllItems())))
362 ARCANE_FATAL("Operation on invalid group");
363
364 if (m_compute_functor && !m_transaction_mode)
365 ARCANE_FATAL("Cannot remove items on computed group ({0})", name());
366
367 IMesh* amesh = mesh();
368 if (!amesh)
369 throw ArgumentException(A_FUNCINFO, "null group");
370
371 ITraceMng* trace = amesh->traceMng();
372 if (isOwn() && amesh->meshPartInfo().nbPart() != 1)
373 ARCANE_THROW(NotSupportedException, "Cannot remove items if isOwn() is true");
374
375 Int32 nb_item_to_remove = items_local_id.size();
376
377 // N'est utile que si on a des observers
378 UniqueArray<Int32> removed_local_ids;
379
380 if (nb_item_to_remove != 0) { // on ne peut tout de même pas faire de retour anticipé à cause des observers
381
382 Int32Array& items_lid = mutableItemsLocalId();
383 const Int32 old_size = items_lid.size();
384 bool has_removed = false;
385
386 if (isAllItems()) {
387 // Algorithme anciennement dans DynamicMeshKindInfo
388 // Supprime des items du groupe all_items par commutation avec les
389 // éléments de fin de ce groupe
390 // ie memoire persistante O(size groupe), algo O(remove items)
391 has_removed = true;
392 Integer nb_item = old_size;
393 for (Integer i = 0, n = nb_item_to_remove; i < n; ++i) {
394 Int32 removed_local_id = items_local_id[i];
395 Int32 index = m_items_index_in_all_group[removed_local_id];
396 --nb_item;
397 Int32 moved_local_id = items_lid[nb_item];
398 items_lid[index] = moved_local_id;
399 m_items_index_in_all_group[moved_local_id] = index;
400 }
401 items_lid.resize(nb_item);
402 }
403 else {
404 // Algorithme pour les autres groupes
405 // Décalage de tableau
406 // ie mémoire locale O(size groupe), algo O(size groupe)
407 // Marque un tableau indiquant les entités à supprimer
408 UniqueArray<bool> remove_flags(maxLocalId(), false);
409 for (Int32 i = 0; i < nb_item_to_remove; ++i)
410 remove_flags[items_local_id[i]] = true;
411
412 {
413 Int32 next_index = 0;
414 for (Int32 i = 0; i < old_size; ++i) {
415 Int32 lid = items_lid[i];
416 if (remove_flags[lid]) {
417 removed_local_ids.add(lid);
418 continue;
419 }
420 items_lid[next_index] = lid;
421 ++next_index;
422 }
423 if (next_index != old_size) {
424 has_removed = true;
425 items_lid.resize(next_index);
426 }
427 }
428 }
429
430 updateTimestamp();
431 if (arcaneIsCheck()) {
432 trace->info(5) << "ItemGroupImpl::removeItems() group <" << name() << "> "
433 << " old_size=" << old_size
434 << " new_size=" << nbItem()
435 << " removed?=" << has_removed;
436 checkValid();
437 }
438 }
439
440 Int32ConstArrayView observation_info(removed_local_ids);
441 notifyReduceObservers(&observation_info);
442}
443
444/*---------------------------------------------------------------------------*/
445/*---------------------------------------------------------------------------*/
446
447void ItemGroupInternal::
448checkValid()
449{
450 ITraceMng* msg = mesh()->traceMng();
451 if (m_need_recompute && m_compute_functor) {
452 msg->debug(Trace::High) << "ItemGroupImpl::checkValid on " << name() << " : skip group to recompute";
453 return;
454 }
455
456 // Les points suivants sont vérifiés
457 // - une entité n'est présente qu'une fois dans le groupe
458 // - les entités du groupe ne sont pas détruites
459 UniqueArray<bool> presence_checks(maxLocalId());
460 presence_checks.fill(0);
461 Integer nb_error = 0;
462
463 ItemInternalList items(this->items());
464 Integer items_size = items.size();
465 Int32ConstArrayView items_lid(itemsLocalId());
466
467 for (Integer i = 0, is = items_lid.size(); i < is; ++i) {
468 Integer lid = items_lid[i];
469 if (lid >= items_size) {
470 if (nb_error < 10) {
471 msg->error() << "Wrong local index lid=" << lid << " max=" << items_size
472 << " var_max_size=" << maxLocalId();
473 }
474 ++nb_error;
475 continue;
476 }
477 ItemInternal* item = items[lid];
478 if (item->isSuppressed()) {
479 if (nb_error < 10) {
480 msg->error() << "Item " << ItemPrinter(item) << " in group "
481 << name() << " does not exist anymore";
482 }
483 ++nb_error;
484 }
485 if (presence_checks[lid]) {
486 if (nb_error < 10) {
487 msg->error() << "Item " << ItemPrinter(item) << " in group "
488 << name() << " was found twice or more";
489 }
490 ++nb_error;
491 }
492 presence_checks[lid] = true;
493 }
494 if (isAllItems()) {
495 for (Integer i = 0, n = items_lid.size(); i < n; ++i) {
496 Int32 local_id = items_lid[i];
497 Int32 index_in_all_group = m_items_index_in_all_group[local_id];
498 if (index_in_all_group != i) {
499 if (nb_error < 10) {
500 msg->error() << A_FUNCINFO
501 << ": " << itemKindName(m_kind)
502 << ": incoherence between 'local_id' and index in the group 'All' "
503 << " i=" << i
504 << " local_id=" << local_id
505 << " index=" << index_in_all_group;
506 }
507 ++nb_error;
508 }
509 }
510 }
511 if (nb_error != 0) {
512 String parent_name = "none";
513 if (m_parent)
514 parent_name = m_parent->name();
515 ARCANE_FATAL("Error in group name='{0}' parent='{1}' nb_error={2}",
516 name(), parent_name, nb_error);
517 }
518}
519
520/*---------------------------------------------------------------------------*/
521/*---------------------------------------------------------------------------*/
522
523void ItemGroupInternal::
524_notifyDirectRemoveItems(SmallSpan<const Int32> removed_ids, Int32 nb_remaining)
525{
526 mutableItemsLocalId().resize(nb_remaining);
527 updateTimestamp();
528 if (arcaneIsCheck())
529 checkValid();
530 // NOTE: la liste \a removed_ids n'est pas forcément dans le même ordre
531 // que celle obtenue via removeItems()
532 Int32ConstArrayView observation_info(removed_ids.smallView());
533 notifyReduceObservers(&observation_info);
534}
535
536/*---------------------------------------------------------------------------*/
537/*---------------------------------------------------------------------------*/
538
539/*---------------------------------------------------------------------------*/
540/*---------------------------------------------------------------------------*/
541
542void ItemGroupImplInternal::
543setAsConstituentGroup()
544{
545 m_p->m_is_constituent_group = true;
546}
547
548/*---------------------------------------------------------------------------*/
549/*---------------------------------------------------------------------------*/
550
551SmallSpan<Int32> ItemGroupImplInternal::
552itemsLocalId()
553{
554 return m_p->itemsLocalId();
555}
556
557/*---------------------------------------------------------------------------*/
558/*---------------------------------------------------------------------------*/
559
560void ItemGroupImplInternal::
561notifyDirectRemoveItems(SmallSpan<const Int32> removed_ids, Int32 nb_remaining)
562{
563 m_p->_notifyDirectRemoveItems(removed_ids, nb_remaining);
564}
565
566/*---------------------------------------------------------------------------*/
567/*---------------------------------------------------------------------------*/
568
569void ItemGroupImplInternal::
570notifySimdPaddingDone()
571{
572 m_p->m_simd_timestamp = m_p->timestamp();
573}
574
575/*---------------------------------------------------------------------------*/
576/*---------------------------------------------------------------------------*/
577
578void ItemGroupImplInternal::
579setMemoryRessourceForItemLocalId(eMemoryRessource mem)
580{
581 VariableArrayInt32* v = m_p->m_variable_items_local_id;
582 if (v)
583 VariableUtils::experimentalChangeAllocator(v->variable(), mem);
584}
585
586/*---------------------------------------------------------------------------*/
587/*---------------------------------------------------------------------------*/
588
589} // End namespace Arcane
590
591/*---------------------------------------------------------------------------*/
592/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur les variables.
Integer size() const
Nombre d'éléments du vecteur.
Exception lorsqu'un argument est invalide.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
constexpr bool empty() const noexcept
true si le tableau est vide (size()==0)
virtual ITraceMng * traceMng()=0
Gestionnaire de message associé
virtual const MeshPartInfo & meshPartInfo() const =0
Informations sur les parties du maillage.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
bool m_is_check_simd_padding
Vrai si les localIds sont consécutifs.
void applySimdPadding()
Applique le padding pour la vectorisation.
IItemFamily * m_item_family
Famille associée.
Int64 m_simd_timestamp
Temps de la derniere modification pour le calcul des infos SIMD.
String m_name
Nom du groupe.
Exception lorsqu'une opération n'est pas supportée.
Vue d'un tableau d'éléments de type T.
Definition Span.h:802
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:325
Chaîne de caractères unicode.
Vecteur 1D de données avec sémantique par valeur (style STL).
IVariable * variable() const
Variable associée.
VariableRefArrayT< Int32 > VariableArrayInt32
Variable tableau de type entier 32 bits.
String getStackTrace()
Retourne une chaîne de caractere contenant la pile d'appel.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:68
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:480
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466
const char * itemKindName(eItemKind kind)
Nom du genre d'entité.
Arcane::eMemoryResource eMemoryRessource
Typedef pour la version Arcane historique (avec 2's').
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:121
std::int32_t Int32
Type entier signé sur 32 bits.