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