Arcane  v3.16.4.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
ItemGroupImpl.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/* ItemGroupImpl.cc (C) 2000-2025 */
9/* */
10/* Implémentation d'un groupe d'entités de maillage. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/ItemGroupImpl.h"
15
16#include "arcane/utils/String.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/ArgumentException.h"
19
20#include "arcane/core/ItemGroupObserver.h"
21#include "arcane/core/IItemFamily.h"
22#include "arcane/core/ItemGroup.h"
23#include "arcane/core/IMesh.h"
24#include "arcane/core/MeshPartInfo.h"
25#include "arcane/core/MeshKind.h"
26#include "arcane/core/ItemPrinter.h"
27#include "arcane/core/IItemOperationByBasicType.h"
28#include "arcane/core/ItemGroupComputeFunctor.h"
29#include "arcane/core/IVariableSynchronizer.h"
30#include "arcane/core/ParallelMngUtils.h"
31#include "arcane/core/internal/ItemGroupInternal.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41/*!
42 * \internal
43 * \brief Classe d'un groupe nul.
44 */
45class ItemGroupImplNull
46: public ItemGroupImpl
47{
48 public:
49
50 ItemGroupImplNull() : ItemGroupImpl() {}
51
52 public:
53
54 //! Retourne le nom du groupe
55 const String& name() const { return m_name; }
56 const String& fullName() const { return m_name; }
57
58 public:
59
60 virtual void convert(NodeGroup& g) { g = NodeGroup(); }
61 virtual void convert(EdgeGroup& g) { g = EdgeGroup(); }
62 virtual void convert(FaceGroup& g) { g = FaceGroup(); }
63 virtual void convert(CellGroup& g) { g = CellGroup(); }
64
65 private:
66
67 String m_name;
68};
69
70/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
72
73ItemGroupImpl* ItemGroupImpl::shared_null = nullptr;
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77
78class ItemGroupImplItemGroupComputeFunctor
79: public ItemGroupComputeFunctor
80{
81 private:
82
83 typedef void (ItemGroupImpl::*FuncPtr)();
84
85 public:
86
87 ItemGroupImplItemGroupComputeFunctor(ItemGroupImpl* parent, FuncPtr funcPtr)
88 : ItemGroupComputeFunctor()
89 , m_parent(parent)
90 , m_function(funcPtr) { }
91
92 public:
93
94 void executeFunctor() override
95 {
96 (m_parent->*m_function)();
97 }
98
99 private:
100
101 ItemGroupImpl * m_parent;
102 FuncPtr m_function;
103};
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108ItemGroupImpl* ItemGroupImpl::
109checkSharedNull()
110{
111 // Normalement ce test n'est vrai que si on a une instance globale
112 // de 'ItemGroup' ce qui est déconseillé. Sinon, _buildSharedNull() a été
113 // automatiquement appelé lors de l'initialisation (dans arcaneInitialize()).
114 if (!shared_null)
115 _buildSharedNull();
116 return shared_null;
117}
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
123ItemGroupImpl(IItemFamily* family,const String& name)
124: m_p (new ItemGroupInternal(family,name))
125{
126}
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
130
133: m_p(new ItemGroupInternal(family,parent,name))
134{
135}
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
142: m_p (new ItemGroupInternal())
143{
144}
145
146/*---------------------------------------------------------------------------*/
147/*---------------------------------------------------------------------------*/
148
151{
152 delete m_p;
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
159name() const
160{
161 return m_p->name();
162}
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
168fullName() const
169{
170 return m_p->fullName();
171}
172
173/*---------------------------------------------------------------------------*/
174/*---------------------------------------------------------------------------*/
175
177size() const
178{
179 return m_p->itemsLocalId().size();
180}
181
182/*---------------------------------------------------------------------------*/
183/*---------------------------------------------------------------------------*/
184
186empty() const
187{
188 return m_p->itemsLocalId().empty();
189}
190
191/*---------------------------------------------------------------------------*/
192/*---------------------------------------------------------------------------*/
193
195itemsLocalId() const
196{
197 return m_p->itemsLocalId();
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
205{
206 if (m_p->m_transaction_mode)
207 ARCANE_FATAL("Transaction mode already started");
208 m_p->m_transaction_mode = true;
209}
210
211/*---------------------------------------------------------------------------*/
212/*---------------------------------------------------------------------------*/
213
216{
217 if (!m_p->m_transaction_mode)
218 ARCANE_FATAL("Transaction mode not started");
219 m_p->m_transaction_mode = false;
220 if (m_p->m_need_recompute) {
221 m_p->m_need_recompute = false;
222 m_p->m_need_invalidate_on_recompute = false;
223 m_p->notifyInvalidateObservers();
224 }
225}
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
230Int32Array& ItemGroupImpl::
231unguardedItemsLocalId(const bool self_invalidate)
232{
233 ITraceMng* trace = m_p->m_mesh->traceMng();
234 trace->debug(Trace::Medium) << "ItemGroupImpl::unguardedItemsLocalId on group " << name()
235 << " with self_invalidate=" << self_invalidate;
236
237 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
238 ARCANE_FATAL("Direct access for computed group in only available during a transaction");
239
240 _forceInvalidate(self_invalidate);
241 return m_p->mutableItemsLocalId();
242}
243
244/*---------------------------------------------------------------------------*/
245/*---------------------------------------------------------------------------*/
246
248parent() const
249{
250 return m_p->m_parent;
251}
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
257mesh() const
258{
259 return m_p->mesh();
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
266itemFamily() const
267{
268 return m_p->m_item_family;
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
275null() const
276{
277 return m_p->null();
278}
279
280/*---------------------------------------------------------------------------*/
281/*---------------------------------------------------------------------------*/
282
284isOwn() const
285{
286 return m_p->m_is_own;
287}
288
289/*---------------------------------------------------------------------------*/
290/*---------------------------------------------------------------------------*/
291
293setOwn(bool v)
294{
295 const bool is_own = m_p->m_is_own;
296 if (is_own == v)
297 return;
298 if (!is_own) {
299 if (m_p->m_own_group)
300 ARCANE_THROW(NotSupportedException,"Setting Own with 'Own' sub-group already defined");
301 }
302 else {
303 // On a le droit de remettre setOwn() à 'false' pour le groupe de toutes
304 // les entités. Cela est nécessaire en reprise si le nombre de parties
305 // du maillage est différent du IParallelMng associé à la famille
306 if (!isAllItems())
307 ARCANE_THROW(NotSupportedException,"Un-setting Own on a own group");
308 }
309 m_p->m_is_own = v;
310 // (HP) TODO: Faut il notifier des observers ?
311}
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
317itemKind() const
318{
319 return m_p->kind();
320}
321
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
324
326ownGroup()
327{
328 ItemGroupImpl* ii = m_p->m_own_group;
329 // Le flag est déjà positionné dans le ItemGroupInternal::_init ou ItemGroupImpl::setOwn
330 if (!ii) {
331 if (m_p->m_is_own){
332 ii = this;
333 m_p->m_own_group = ii;
334 } else {
335 ii = createSubGroup("Own",m_p->m_item_family,new OwnItemGroupComputeFunctor());
336 m_p->m_own_group = ii;
337 ii->setOwn(true);
338 }
339 }
340 return ii;
341}
342
343/*---------------------------------------------------------------------------*/
344/*---------------------------------------------------------------------------*/
345
348{
349 ItemGroupImpl* ii = m_p->m_ghost_group;
350 if (!ii) {
351 ii = createSubGroup("Ghost",m_p->m_item_family,new GhostItemGroupComputeFunctor());
352 m_p->m_ghost_group = ii;
353 }
354 return ii;
355}
356
357/*---------------------------------------------------------------------------*/
358/*---------------------------------------------------------------------------*/
359
360ItemGroupImpl* ItemGroupImpl::
361interfaceGroup()
362{
363 if (itemKind()!=IK_Face)
364 return checkSharedNull();
365 ItemGroupImpl* ii = m_p->m_interface_group;
366 if (!ii) {
367 ii = createSubGroup("Interface",m_p->m_item_family,new InterfaceItemGroupComputeFunctor());
368 m_p->m_interface_group = ii;
369 }
370 return ii;
371}
372
373/*---------------------------------------------------------------------------*/
374/*---------------------------------------------------------------------------*/
375
377nodeGroup()
378{
379 if (itemKind()==IK_Node)
380 return this;
381 ItemGroupImpl* ii = m_p->m_node_group;
382 if (!ii){
383 ii = createSubGroup("Nodes",m_p->m_mesh->nodeFamily(),new ItemItemGroupComputeFunctor<Node>());
384 m_p->m_node_group = ii;
385 }
386 return ii;
387}
388
389/*---------------------------------------------------------------------------*/
390/*---------------------------------------------------------------------------*/
391
393edgeGroup()
394{
395 if (itemKind()==IK_Edge)
396 return this;
397 ItemGroupImpl* ii = m_p->m_edge_group;
398 if (!ii){
399 ii = createSubGroup("Edges",m_p->m_mesh->edgeFamily(),new ItemItemGroupComputeFunctor<Edge>());
400 m_p->m_edge_group = ii;
401 }
402 return ii;
403}
404
405/*---------------------------------------------------------------------------*/
406/*---------------------------------------------------------------------------*/
407
409faceGroup()
410{
411 if (itemKind()==IK_Face)
412 return this;
413 ItemGroupImpl* ii = m_p->m_face_group;
414 if (!ii){
415 ii = createSubGroup("Faces",m_p->m_mesh->faceFamily(),new ItemItemGroupComputeFunctor<Face>());
416 m_p->m_face_group = ii;
417 }
418 return ii;
419}
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
425cellGroup()
426{
427 if (itemKind()==IK_Cell)
428 return this;
429 ItemGroupImpl* ii = m_p->m_cell_group;
430 if (!ii){
431 ii = createSubGroup("Cells",m_p->m_mesh->cellFamily(),new ItemItemGroupComputeFunctor<Cell>());
432 m_p->m_cell_group = ii;
433 }
434 return ii;
435}
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
439
442{
443 if (itemKind()!=IK_Cell)
444 return checkSharedNull();
445 ItemGroupImpl* ii = m_p->m_inner_face_group;
446 if (!ii){
447 ii = createSubGroup("InnerFaces",m_p->m_mesh->faceFamily(),
449 m_p->m_inner_face_group = ii;
450 }
451 return ii;
452}
453
454/*---------------------------------------------------------------------------*/
455/*---------------------------------------------------------------------------*/
456
459{
460 if (itemKind()!=IK_Cell)
461 return checkSharedNull();
462 ItemGroupImpl* ii = m_p->m_outer_face_group;
463 if (!ii){
464 ii = createSubGroup("OuterFaces",m_p->m_mesh->faceFamily(),
466 m_p->m_outer_face_group = ii;
467 }
468 return ii;
469}
470/*---------------------------------------------------------------------------*/
471/*---------------------------------------------------------------------------*/
472//! AMR
473
474/*---------------------------------------------------------------------------*/
475/*---------------------------------------------------------------------------*/
476
479{
480 if (itemKind()!=IK_Cell)
481 return checkSharedNull();
482 ItemGroupImpl* ii = m_p->m_active_cell_group;
483
484 if (!ii){
485 ii = createSubGroup("ActiveCells",m_p->m_mesh->cellFamily(),
487 m_p->m_active_cell_group = ii;
488 }
489 return ii;
490}
491
492/*---------------------------------------------------------------------------*/
493/*---------------------------------------------------------------------------*/
494
497{
498 if (itemKind()!=IK_Cell)
499 return checkSharedNull();
500 ItemGroupImpl* ii = m_p->m_own_active_cell_group;
501 // Le flag est déjà positionné dans le ItemGroupInternal::_init ou ItemGroupImpl::setOwn
502 if (!ii) {
503 ii = createSubGroup("OwnActiveCells",m_p->m_mesh->cellFamily(),
505 m_p->m_own_active_cell_group = ii;
506 ii->setOwn(true);
507 }
508 return ii;
509}
510/*---------------------------------------------------------------------------*/
511/*---------------------------------------------------------------------------*/
512
514levelCellGroup(const Integer& level)
515{
516 if (itemKind()!=IK_Cell)
517 return checkSharedNull();
518 ItemGroupImpl* ii = m_p->m_level_cell_group[level];
519 if (!ii){
520 ii = createSubGroup(String::format("LevelCells{0}",level),
521 m_p->m_mesh->cellFamily(),
523 m_p->m_level_cell_group[level] = ii;
524 }
525 return ii;
526}
527
528/*---------------------------------------------------------------------------*/
529/*---------------------------------------------------------------------------*/
530
532ownLevelCellGroup(const Integer& level)
533{
534 if (itemKind()!=IK_Cell)
535 return checkSharedNull();
536 ItemGroupImpl* ii = m_p->m_own_level_cell_group[level];
537 // Le flag est déjà positionné dans le ItemGroupInternal::_init ou ItemGroupImpl::setOwn
538 if (!ii) {
539 ii = createSubGroup(String::format("OwnLevelCells{0}",level),
540 m_p->m_mesh->cellFamily(),
542 m_p->m_own_level_cell_group[level] = ii;
543 ii->setOwn(true);
544 }
545 return ii;
546}
547/*---------------------------------------------------------------------------*/
548/*---------------------------------------------------------------------------*/
549
552{
553 if (itemKind()!=IK_Cell)
554 return checkSharedNull();
555 ItemGroupImpl* ii = m_p->m_active_face_group;
556 if (!ii){
557 ii = createSubGroup("ActiveFaces",m_p->m_mesh->faceFamily(),
559 m_p->m_active_face_group = ii;
560 }
561 return ii;
562}
563
564/*---------------------------------------------------------------------------*/
565/*---------------------------------------------------------------------------*/
566
569{
570 if (itemKind()!=IK_Cell)
571 return checkSharedNull();
572 ItemGroupImpl* ii = m_p->m_own_active_face_group;
573 if (!ii){
574 ii = createSubGroup("OwnActiveFaces",m_p->m_mesh->faceFamily(),
576 m_p->m_own_active_face_group = ii;
577 }
578 return ii;
579}
580/*---------------------------------------------------------------------------*/
581/*---------------------------------------------------------------------------*/
582
585{
586 if (itemKind()!=IK_Cell)
587 return checkSharedNull();
588 ItemGroupImpl* ii = m_p->m_inner_active_face_group;
589 if (!ii){
590 ii = createSubGroup("InnerActiveFaces",m_p->m_mesh->faceFamily(),
592 m_p->m_inner_active_face_group = ii;
593 }
594 return ii;
595}
596
597/*---------------------------------------------------------------------------*/
598/*---------------------------------------------------------------------------*/
599
602{
603 if (itemKind()!=IK_Cell)
604 return checkSharedNull();
605 ItemGroupImpl* ii = m_p->m_outer_active_face_group;
606 if (!ii){
607 ii = createSubGroup("OuterActiveFaces",m_p->m_mesh->faceFamily(),
609 m_p->m_outer_active_face_group = ii;
610 }
611 return ii;
612}
613/*---------------------------------------------------------------------------*/
614/*---------------------------------------------------------------------------*/
615
617createSubGroup(const String& suffix, IItemFamily* family, ItemGroupComputeFunctor * functor)
618{
619 String sub_name = name() + "_" + suffix;
620 auto finder = m_p->m_sub_groups.find(sub_name);
621 if (finder != m_p->m_sub_groups.end()) {
622 ARCANE_FATAL("Cannot create already existing sub-group ({0}) in group ({1})",
623 suffix, name());
624 }
625 ItemGroup ig = family->createGroup(sub_name,ItemGroup(this));
626 ItemGroupImpl* ii = ig.internal();
627 ii->setComputeFunctor(functor);
628 functor->setGroup(ii);
629 // Observer par défaut : le sous groupe n'est pas intéressé par les infos détaillées de transition
631 &ItemGroupImpl::_executeInvalidate));
632 m_p->m_sub_groups[sub_name] = ii;
633 ii->invalidate(false);
634 return ii;
635}
636
637/*---------------------------------------------------------------------------*/
638/*---------------------------------------------------------------------------*/
639
641findSubGroup(const String& suffix)
642{
643 String sub_name = name() + "_" + suffix;
644 auto finder = m_p->m_sub_groups.find(sub_name);
645 if (finder != m_p->m_sub_groups.end()) {
646 return finder->second.get();
647 }
648 else {
649 // ou bien erreur ?
650 return checkSharedNull();
651 }
652}
653
654/*---------------------------------------------------------------------------*/
655/*---------------------------------------------------------------------------*/
656
658changeIds(Int32ConstArrayView old_to_new_ids)
659{
660 ITraceMng* trace = m_p->m_mesh->traceMng();
661 if (m_p->m_compute_functor) {
662 trace->debug(Trace::High) << "ItemGroupImpl::changeIds on "
663 << name() << " : skip computed group";
664 return;
665 }
666
667 // ItemGroupImpl ne fait d'habitude pas le checkNeedUpdate lui meme, plutot le ItemGroup
669 if (isAllItems()) {
670 // Int32ArrayView items_lid = m_p->itemsLocalId();
671 // for( Integer i=0, is=items_lid.size(); i<is; ++i ) {
672 // Integer lid = items_lid[i];
673 // ARCANE_ASSERT((lid = old_to_new_ids[lid]),("Non uniform order on allItems"));;
674 // }
675 // m_p->notifyCompactObservers(&old_to_new_ids);
676 m_p->notifyInvalidateObservers();
677 return;
678 }
679
680 Int32ArrayView items_lid = m_p->itemsLocalId();
681 for( Integer i=0, is=items_lid.size(); i<is; ++i ){
682 Integer old_id = items_lid[i];
683 items_lid[i] = old_to_new_ids[old_id];
684 }
685
686 m_p->updateTimestamp();
687 // Pour l'instant, il ne faut pas trier les entités des variables
688 // partielles car les valeurs correspondantes des variables ne sont
689 // pas mises à jour (il faut implémenter changeGroupIds pour cela)
690 // NOTE: est-ce utile de le faire ?
691 // NOTE: faut-il le faire pour les autre aussi ? A priori, cela n'est
692 // utile que pour garantir le meme resultat parallele/sequentiel
693 if (m_p->m_observer_need_info) {
694 m_p->notifyCompactObservers(&old_to_new_ids);
695 } else {
696 // Pas besoin d'infos, on peut changer arbitrairement leur ordre
697 // TODO: #warning "(HP) Connexion de ce triage d'item avec la famille ?"
698 std::sort(std::begin(items_lid),std::end(items_lid));
699 m_p->notifyCompactObservers(nullptr);
700 }
701}
702
703/*---------------------------------------------------------------------------*/
704/*---------------------------------------------------------------------------*/
705
707invalidate(bool force_recompute)
708{
709#ifdef ARCANE_DEBUG
710 // if (force_recompute){
711 ITraceMng* msg = m_p->m_mesh->traceMng();
712 msg->debug(Trace::High) << "ItemGroupImpl::invalidate(force=" << force_recompute << ")"
713 << " name=" << name();
714// }
715#endif
716
717 m_p->updateTimestamp();
718 m_p->setNeedRecompute();
719 if (force_recompute)
721 m_p->notifyInvalidateObservers();
722}
723
724/*---------------------------------------------------------------------------*/
725/*---------------------------------------------------------------------------*/
726
728itemsInternal() const
729{
730 return m_p->items();
731}
732
733/*---------------------------------------------------------------------------*/
734/*---------------------------------------------------------------------------*/
735
737itemInfoListView() const
738{
739 return m_p->itemInfoListView();
740}
741
742/*---------------------------------------------------------------------------*/
743/*---------------------------------------------------------------------------*/
744
746isLocalToSubDomain() const
747{
748 return m_p->m_is_local_to_sub_domain;
749}
750
751/*---------------------------------------------------------------------------*/
752/*---------------------------------------------------------------------------*/
753
756{
757 m_p->m_is_local_to_sub_domain = v;
758}
759
760/*---------------------------------------------------------------------------*/
761/*---------------------------------------------------------------------------*/
762
764addItems(Int32ConstArrayView items_local_id,bool check_if_present)
765{
766 ARCANE_ASSERT(( (!m_p->m_need_recompute && !isAllItems()) || (m_p->m_transaction_mode && isAllItems()) ),
767 ("Operation on invalid group"));
768 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
769 ARCANE_FATAL("Cannot add items on computed group ({0})", name());
770 IMesh* amesh = mesh();
771 if (!amesh)
772 throw ArgumentException(A_FUNCINFO,"null group");
773 ITraceMng* trace = amesh->traceMng();
774
775 Integer nb_item_to_add = items_local_id.size();
776 if (nb_item_to_add==0)
777 return;
778
779 Int32Array& items_lid = m_p->mutableItemsLocalId();
780 const Integer current_size = items_lid.size();
781 Integer nb_added = 0;
782
783 if(isAllItems()) {
784 // Ajoute les nouveaux items à la fin
785 Integer nb_items_id = current_size;
786 m_p->m_items_index_in_all_group.resize(m_p->maxLocalId());
787 for( Integer i=0, is=nb_item_to_add; i<is; ++i ){
788 Int32 local_id = items_local_id[i];
789 items_lid.add(local_id);
790 m_p->m_items_index_in_all_group[local_id] = nb_items_id+i;
791 }
792 nb_added = nb_item_to_add;
793 }
794 else if (check_if_present) {
795 // Vérifie que les entités à ajouter ne sont pas déjà présentes
796 UniqueArray<bool> presence_checks(m_p->maxLocalId());
797 presence_checks.fill(false);
798 for( Integer i=0, is=items_lid.size(); i<is; ++i ){
799 presence_checks[items_lid[i]] = true;
800 }
801
802 for( Integer i=0; i<nb_item_to_add; ++i ) {
803 const Integer lid = items_local_id[i];
804 if (!presence_checks[lid]){
805 items_lid.add(lid);
806 // Met à \a true comme cela si l'entité est présente plusieurs fois
807 // dans \a items_local_id cela fonctionne quand même.
808 presence_checks[lid] = true;
809 ++nb_added;
810 }
811 }
812 }
813 else {
814 nb_added = nb_item_to_add;
815 MemoryUtils::checkResizeArrayWithCapacity(items_lid,current_size+nb_added,false);
816 SmallSpan<Int32> ptr = items_lid.subView(current_size,nb_added);
817 MemoryUtils::copy<Int32>(ptr, items_local_id);
818 }
819
820 if (arcaneIsCheck()){
821 trace->info(5) << "ItemGroupImpl::addItems() group <" << name() << "> "
822 << " checkpresent=" << check_if_present
823 << " nb_current=" << current_size
824 << " want_to_add=" << nb_item_to_add
825 << " effective_added=" << nb_added;
826 checkValid();
827 }
828
829 if (nb_added!=0) {
830 m_p->updateTimestamp();
831 Int32ConstArrayView observation_info(nb_added, items_lid.unguardedBasePointer()+current_size);
832 m_p->notifyExtendObservers(&observation_info);
833 }
834}
835
836/*---------------------------------------------------------------------------*/
837/*---------------------------------------------------------------------------*/
838
840removeItems(Int32ConstArrayView items_local_id,[[maybe_unused]] bool check_if_present)
841{
842 m_p->_removeItems(items_local_id);
843}
844
845/*---------------------------------------------------------------------------*/
846/*---------------------------------------------------------------------------*/
847
849removeAddItems(Int32ConstArrayView removed_items_lids,
850 Int32ConstArrayView added_items_lids,
851 bool check_if_present)
852{
853 ARCANE_ASSERT(( (!m_p->m_need_recompute && !isAllItems()) || (m_p->m_transaction_mode && isAllItems()) ),
854 ("Operation on invalid group"));
855 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
856 ARCANE_FATAL("Cannot remove items on computed group ({0})", name());
857 IMesh* amesh = mesh();
858 if (!amesh)
859 throw ArgumentException(A_FUNCINFO,"null group");
860 ITraceMng* trace = amesh->traceMng();
861 if (isOwn() && amesh->meshPartInfo().nbPart()!=1){
862 ARCANE_THROW(NotSupportedException,"Cannot remove items if isOwn() is true");
863 }
864
865 Int32Array & items_lid = m_p->mutableItemsLocalId();
866
867 if(isAllItems()) {
868 ItemInternalList internals = itemsInternal();
869 const Integer internal_size = internals.size();
870 const Integer new_size = m_p->m_item_family->nbItem();
871 items_lid.resize(new_size);
872 m_p->m_items_index_in_all_group.resize(m_p->maxLocalId());
873 if (new_size==internal_size){
874 // Il n'y a pas de trous dans la numérotation
875 for( Integer i=0; i<internal_size; ++i ){
876 Int32 local_id = internals[i]->localId();
877 items_lid[i] = local_id;
878 m_p->m_items_index_in_all_group[local_id] = i;
879 }
880 }
881 else{
882 Integer index = 0;
883 for( Integer i=0; i<internal_size; ++i ){
884 ItemInternal* item = internals[i];
885 if (!item->isSuppressed()){
886 Int32 local_id = item->localId();
887 items_lid[index] = local_id;
888 m_p->m_items_index_in_all_group[local_id] = index;
889 ++index;
890 }
891 }
892 if (index!=new_size)
893 ARCANE_FATAL("Inconsistent number of elements in the generation of the group '{0}' expected={1} present={2}",
894 name(), new_size, index);
895 }
896
897 // On ne peut pas savoir ce qui a changé donc dans le doute on
898 // incrémente le timestamp.
899 m_p->updateTimestamp();
900 }
901 else {
902 removeItems(removed_items_lids,check_if_present);
903 addItems(added_items_lids,check_if_present);
904 }
905
906 if(arcaneIsCheck()){
907 trace->info(5) << "ItemGroupImpl::removeAddItems() group <" << name() << "> "
908 << " old_size=" << m_p->m_item_family->nbItem()
909 << " new_size=" << size()
910 << " nb_removed=" << removed_items_lids.size()
911 << " nb_added=" << added_items_lids.size();
912 checkValid();
913 }
914}
915
916
917/*---------------------------------------------------------------------------*/
918/*---------------------------------------------------------------------------*/
919
921setItems(Int32ConstArrayView items_local_id)
922{
923 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
924 ARCANE_FATAL("Cannot set items on computed group ({0})", name());
925 Int32Array& buf = m_p->mutableItemsLocalId();
926 buf.resize(items_local_id.size());
927 Int32ArrayView buf_view(buf);
928 buf_view.copy(items_local_id);
929 m_p->updateTimestamp();
930 m_p->m_need_recompute = false;
931 if (arcaneIsCheck()){
932 ITraceMng* trace = m_p->mesh()->traceMng();
933 trace->debug(Trace::High) << "ItemGroupImpl::setItems() group <" << name() << "> "
934 << " size=" << size();
935 checkValid();
936 }
937
938 // On tolére encore le setItems initial en le convertissant en un addItems
939 if (size() != 0)
940 m_p->notifyInvalidateObservers();
941 else
942 m_p->notifyExtendObservers(&items_local_id);
943}
944
945/*---------------------------------------------------------------------------*/
946/*---------------------------------------------------------------------------*/
947
949{
950 public:
951 ItemSorter(ItemInfoListView items) : m_items(items){}
952 public:
953 void sort(Int32ArrayView local_ids) const
954 {
955 std::sort(std::begin(local_ids),std::end(local_ids),*this);
956 }
957 bool operator()(Int32 lid1,Int32 lid2) const
958 {
959 return m_items[lid1].uniqueId() < m_items[lid2].uniqueId();
960 }
961 private:
962 ItemInfoListView m_items;
963};
964
965/*---------------------------------------------------------------------------*/
966/*---------------------------------------------------------------------------*/
967
969setItems(Int32ConstArrayView items_local_id,bool do_sort)
970{
971 if (!do_sort){
972 setItems(items_local_id);
973 return;
974 }
975 UniqueArray<Int32> sorted_lid(items_local_id);
977 sorter.sort(sorted_lid);
978 setItems(sorted_lid);
979}
980
981/*---------------------------------------------------------------------------*/
982/*---------------------------------------------------------------------------*/
983
984void ItemGroupImpl::
985setIsAllItems()
986{
987 m_p->m_is_all_items = true;
988}
989
990/*---------------------------------------------------------------------------*/
991/*---------------------------------------------------------------------------*/
992
994isAllItems() const
995{
996 return m_p->m_is_all_items;
997}
998
999/*---------------------------------------------------------------------------*/
1000/*---------------------------------------------------------------------------*/
1001
1002class ItemCheckSuppressedFunctor
1003{
1004 public:
1005 ItemCheckSuppressedFunctor(ItemInternalList items)
1006 : m_items(items)
1007 {
1008 }
1009 public:
1010 bool operator()(Integer item_lid)
1011 {
1012 return m_items[item_lid]->isSuppressed();
1013 }
1014 private:
1015 ItemInternalList m_items;
1016};
1017
1018/*---------------------------------------------------------------------------*/
1019/*---------------------------------------------------------------------------*/
1020
1023{
1024 // TODO: (HP) Assertion need fix"
1025 // ARCANE_ASSERT((!m_p->m_need_recompute),("Operation on invalid group"));
1026 ITraceMng* trace = m_p->mesh()->traceMng();
1027 if (m_p->m_compute_functor) {
1028 trace->debug(Trace::High) << "ItemGroupImpl::removeSuppressedItems on " << name() << " : skip computed group";
1029 return;
1030 }
1031
1032 ItemInternalList items = m_p->items();
1033 Integer nb_item = items.size();
1034 Int32Array& items_lid = m_p->mutableItemsLocalId();
1035 Integer current_size = items_lid.size();
1036 if (arcaneIsCheck()){
1037 for( Integer i=0; i<current_size; ++i ){
1038 if (items_lid[i]>=nb_item){
1039 trace->fatal() << "ItemGroupImpl::removeSuppressedItems(): bad range "
1040 << " name=" << name()
1041 << " i=" << i << " lid=" << items_lid[i]
1042 << " max=" << nb_item;
1043 }
1044 }
1045 }
1046
1047 Int32UniqueArray removed_ids, removed_lids;
1048 Int32ConstArrayView * observation_info = NULL;
1049 Int32ConstArrayView * observation_info2 = NULL;
1050 Integer new_size;
1051 // Si le groupe posséde des observers ayant besoin d'info, il faut les calculer
1052 if (m_p->m_observer_need_info){
1053 removed_ids.reserve(current_size); // préparation à taille max
1054 Integer index = 0;
1055 for( Integer i=0; i<current_size; ++i ){
1056 if (!items[items_lid[i]]->isSuppressed()){
1057 items_lid[index] = items_lid[i];
1058 ++index;
1059 } else {
1060 // trace->debug(Trace::Highest) << "Remove from group " << name() << " item " << i << " " << items_lid[i] << " " << ItemPrinter(items[items_lid[i]]);
1061 removed_lids.add(items_lid[i]);
1062 }
1063 }
1064 new_size = index;
1065 if (new_size!=current_size){
1066 items_lid.resize(new_size);
1067 observation_info = new Int32ConstArrayView(removed_lids.size(), removed_lids.unguardedBasePointer());
1068 }
1069 }
1070 else{
1071 ItemCheckSuppressedFunctor f(m_p->items());
1072 auto ibegin = std::begin(items_lid);
1073 auto new_end = std::remove_if(ibegin,std::end(items_lid),f);
1074 new_size = (Integer)(new_end-ibegin);
1075 items_lid.resize(new_size);
1076 }
1077
1078 if (arcaneIsCheck()) {
1079 trace->debug(Trace::High) << "ItemGroupImpl::removeSupressedItems() group <" << name()
1080 << "> NEW SIZE=" << new_size << " OLD=" << current_size;
1081 checkValid();
1082 }
1083
1084 // Ne met à jour que si le groupe a été modifié
1085 if (current_size != new_size) {
1086 m_p->updateTimestamp();
1087 m_p->notifyReduceObservers(observation_info);
1088 delete observation_info;
1089 delete observation_info2;
1090 }
1091}
1092
1093/*---------------------------------------------------------------------------*/
1094/*---------------------------------------------------------------------------*/
1095
1097checkValid()
1098{
1099 m_p->checkValid();
1100}
1101
1102/*---------------------------------------------------------------------------*/
1103/*---------------------------------------------------------------------------*/
1104
1105bool ItemGroupImpl::
1106_checkNeedUpdate(bool do_padding)
1107{
1108 // NOTE: l'utilisation de verrou est pour l'instant expérimentale (juin 2025)
1109 // On met le verrou sur toute la méthode pour que ce soit plus simple, mais
1110 // on pourrait ne le faire qu'après vérification que la mise à jour
1111 // est vraiment utile.
1112 ItemGroupInternal::CheckNeedUpdateMutex::ScopedLock lock(m_p->m_check_need_update_mutex);
1113
1114 // En cas de problème sur des re-calculs très imbriqués, une proposition est
1115 // de désactiver les lignes #A pour activer les lignes #B
1116 bool has_recompute = false;
1117 if (m_p->m_need_recompute) {
1118 m_p->m_need_recompute = false;
1119 // bool need_invalidate_on_recompute = m_p->m_need_invalidate_on_recompute; // #B
1120 // m_p->m_need_invalidate_on_recompute = false; // #B
1121 if (m_p->m_compute_functor) {
1122 m_p->m_compute_functor->executeFunctor();
1123 }
1124 // if (need_invalidate_on_recompute) { // #B
1125 // m_p->notifyInvalidateObservers(); // #B
1126 // } // #B
1127
1128 if (m_p->m_need_invalidate_on_recompute) { // #A
1129 m_p->m_need_invalidate_on_recompute = false; // #A
1130 m_p->notifyInvalidateObservers(); // #A
1131 } // #A
1132 has_recompute = true;
1133 }
1134 if (do_padding)
1135 _checkUpdateSimdPadding();
1136 return has_recompute;
1137}
1138
1139/*---------------------------------------------------------------------------*/
1140/*---------------------------------------------------------------------------*/
1141
1142bool ItemGroupImpl::
1143_checkNeedUpdateNoPadding()
1144{
1145 return _checkNeedUpdate(false);
1146}
1147
1148/*---------------------------------------------------------------------------*/
1149/*---------------------------------------------------------------------------*/
1150
1151bool ItemGroupImpl::
1152_checkNeedUpdateWithPadding()
1153{
1154 return _checkNeedUpdate(true);
1155}
1156
1157/*---------------------------------------------------------------------------*/
1158/*---------------------------------------------------------------------------*/
1159
1162{
1163 return _checkNeedUpdate(false);
1164}
1165
1166/*---------------------------------------------------------------------------*/
1167/*---------------------------------------------------------------------------*/
1168
1169void ItemGroupImpl::
1170_checkUpdateSimdPadding()
1171{
1172 m_p->checkUpdateSimdPadding();
1173}
1174
1175/*---------------------------------------------------------------------------*/
1176/*---------------------------------------------------------------------------*/
1177
1179clear()
1180{
1181 Int32Array& items_lid = m_p->mutableItemsLocalId();
1182 if (!items_lid.empty())
1183 // Incrémente uniquement si le groupe n'est pas déjà vide
1184 m_p->updateTimestamp();
1185 items_lid.clear();
1186 m_p->m_need_recompute = false;
1187 for( const auto& i : m_p->m_sub_groups )
1188 i.second->clear();
1189 m_p->notifyInvalidateObservers();
1190}
1191
1192/*---------------------------------------------------------------------------*/
1193/*---------------------------------------------------------------------------*/
1194
1197{
1198 if (m_p->m_parent)
1199 return ItemGroup(m_p->m_parent);
1200 return ItemGroup();
1201}
1202
1203/*---------------------------------------------------------------------------*/
1204/*---------------------------------------------------------------------------*/
1205
1208{
1209 ARCANE_ASSERT((!m_p->m_need_recompute),("Operation on invalid group"));
1210 bool is_verbose = m_p->m_is_debug_apply_operation;
1211
1212 ITraceMng* tm = m_p->mesh()->traceMng();
1213 if (is_verbose)
1214 tm->info() << "applyOperation name=" << name() << " nb_item=" << size();
1215 if (m_p->isUseV2ForApplyOperation()){
1216 if (m_p->m_children_by_type_ids.empty()){
1217 _initChildrenByTypeV2();
1218 }
1219 Int64 t = m_p->timestamp();
1220 if (is_verbose)
1221 tm->info() << "applyOperation timestamp=" << t << " last=" << m_p->m_children_by_type_ids_computed_timestamp;
1222 if (m_p->m_children_by_type_ids_computed_timestamp != t){
1223 _computeChildrenByTypeV2();
1224 m_p->m_children_by_type_ids_computed_timestamp = t;
1225 }
1226 }
1227 else{
1228 if (m_p->m_children_by_type.empty())
1229 _initChildrenByType();
1230 }
1231 IItemFamily* family = m_p->m_item_family;
1232 const bool has_only_one_type = (m_p->m_unique_children_type != IT_NullType);
1233 if (is_verbose)
1234 tm->info() << "applyOperation has_only_one_type=" << has_only_one_type << " value=" << m_p->m_unique_children_type;
1235 // TODO: Supprimer la macro et la remplacer par une fonction.
1236
1237#define APPLY_OPERATION_ON_TYPE(ITEM_TYPE) \
1238 if (m_p->isUseV2ForApplyOperation()){\
1239 Int16 type_id = IT_##ITEM_TYPE;\
1240 Int32ConstArrayView sub_ids = m_p->m_children_by_type_ids[type_id]; \
1241 if (has_only_one_type && type_id==m_p->m_unique_children_type)\
1242 sub_ids = itemsLocalId(); \
1243 if (is_verbose && sub_ids.size()>0) \
1244 tm->info() << "Type=" << (int)IT_##ITEM_TYPE << " nb=" << sub_ids.size(); \
1245 if (sub_ids.size()!=0){\
1246 operation->apply##ITEM_TYPE(family->view(sub_ids)); \
1247 }\
1248 }\
1249 else { \
1250 ItemGroup group(m_p->m_children_by_type[IT_##ITEM_TYPE]); \
1251 if (!group.empty()) \
1252 operation->apply##ITEM_TYPE(group.view()); \
1253 }
1254
1255 APPLY_OPERATION_ON_TYPE(Vertex);
1256 APPLY_OPERATION_ON_TYPE(Line2);
1257 APPLY_OPERATION_ON_TYPE(Triangle3);
1258 APPLY_OPERATION_ON_TYPE(Quad4);
1259 APPLY_OPERATION_ON_TYPE(Pentagon5);
1260 APPLY_OPERATION_ON_TYPE(Hexagon6);
1261 APPLY_OPERATION_ON_TYPE(Tetraedron4);
1262 APPLY_OPERATION_ON_TYPE(Pyramid5);
1263 APPLY_OPERATION_ON_TYPE(Pentaedron6);
1264 APPLY_OPERATION_ON_TYPE(Hexaedron8);
1265 APPLY_OPERATION_ON_TYPE(Heptaedron10);
1266 APPLY_OPERATION_ON_TYPE(Octaedron12);
1267 APPLY_OPERATION_ON_TYPE(HemiHexa7);
1268 APPLY_OPERATION_ON_TYPE(HemiHexa6);
1269 APPLY_OPERATION_ON_TYPE(HemiHexa5);
1270 APPLY_OPERATION_ON_TYPE(HemiHexa7);
1271 APPLY_OPERATION_ON_TYPE(AntiWedgeLeft6);
1272 APPLY_OPERATION_ON_TYPE(AntiWedgeRight6);
1273 APPLY_OPERATION_ON_TYPE(DiTetra5);
1274 APPLY_OPERATION_ON_TYPE(DualNode);
1275 APPLY_OPERATION_ON_TYPE(DualEdge);
1276 APPLY_OPERATION_ON_TYPE(DualFace);
1277 APPLY_OPERATION_ON_TYPE(DualCell);
1278 APPLY_OPERATION_ON_TYPE(Link);
1279
1280#undef APPLY_OPERATION_ON_TYPE
1281}
1282
1283/*---------------------------------------------------------------------------*/
1284/*---------------------------------------------------------------------------*/
1285
1287needSynchronization() const
1288{
1289 return !(m_p->m_compute_functor != 0 ||
1290 m_p->m_is_local_to_sub_domain ||
1291 m_p->m_is_own);
1292}
1293
1294/*---------------------------------------------------------------------------*/
1295/*---------------------------------------------------------------------------*/
1296
1298timestamp() const
1299{
1300 return m_p->timestamp();
1301}
1302
1303/*---------------------------------------------------------------------------*/
1304/*---------------------------------------------------------------------------*/
1305
1307attachObserver(const void * ref, IItemGroupObserver * obs)
1308{
1309 auto finder = m_p->m_observers.find(ref);
1310 auto end = m_p->m_observers.end();
1311 if (finder != end) {
1312 delete finder->second;
1313 finder->second = obs;
1314 return;
1315 }
1316 else {
1317 m_p->m_observers[ref] = obs;
1318 }
1319
1320 // Mise à jour du flag de demande d'info
1321 _updateNeedInfoFlag(m_p->m_observer_need_info | obs->needInfo());
1322}
1323
1324/*---------------------------------------------------------------------------*/
1325/*---------------------------------------------------------------------------*/
1326
1328detachObserver(const void * ref)
1329{
1330 auto finder = m_p->m_observers.find(ref);
1331 auto end = m_p->m_observers.end();
1332
1333 if (finder == end)
1334 return;
1335
1336 IItemGroupObserver * obs = finder->second;
1337 delete obs;
1338 m_p->m_observers.erase(finder);
1339 // Mise à jour du flag de demande d'info
1340 bool new_observer_need_info = false;
1341 auto i = m_p->m_observers.begin();
1342 for( ; i != end ; ++i ) {
1343 IItemGroupObserver * obs = i->second;
1344 new_observer_need_info |= obs->needInfo();
1345 }
1346 _updateNeedInfoFlag(new_observer_need_info);
1347
1348 // On invalide la table de hachage éventuelle
1349 // des variables partielles si il n'y a plus
1350 // de référence.
1351 if(m_p->m_group_index_table.isUsed() && m_p->m_group_index_table.isUnique()) {
1352 m_p->m_group_index_table.reset();
1353 m_p->m_synchronizer.reset();
1354 }
1355}
1356
1357/*---------------------------------------------------------------------------*/
1358/*---------------------------------------------------------------------------*/
1359
1361hasInfoObserver() const
1362{
1363 return m_p->m_observer_need_info;
1364}
1365
1366/*---------------------------------------------------------------------------*/
1367/*---------------------------------------------------------------------------*/
1368
1371{
1372 delete m_p->m_compute_functor;
1373 m_p->m_compute_functor = functor;
1374}
1375
1376/*---------------------------------------------------------------------------*/
1377/*---------------------------------------------------------------------------*/
1378
1380hasComputeFunctor() const
1381{
1382 return (m_p->m_compute_functor);
1383}
1384
1385/*---------------------------------------------------------------------------*/
1386/*---------------------------------------------------------------------------*/
1387
1388void ItemGroupImpl::
1389_initChildrenByType()
1390{
1391 IItemFamily* family = m_p->m_item_family;
1392 ItemTypeMng* type_mng = family->mesh()->itemTypeMng();
1393 Integer nb_basic_item_type= ItemTypeMng::nbBasicItemType(); //NB_BASIC_ITEM_TYPE
1394 m_p->m_children_by_type.resize(nb_basic_item_type);
1395 for( Integer i=0; i<nb_basic_item_type; ++i ){
1396 // String child_name(name()+i);
1397 String child_name(type_mng->typeName(i));
1398 ItemGroupImpl* igi = createSubGroup(child_name,family,
1399 new ItemGroupImplItemGroupComputeFunctor(this,&ItemGroupImpl::_computeChildrenByType));
1400 m_p->m_children_by_type[i] = igi;
1401 }
1402}
1403
1404/*---------------------------------------------------------------------------*/
1405/*---------------------------------------------------------------------------*/
1406
1407void ItemGroupImpl::
1408_initChildrenByTypeV2()
1409{
1410 bool is_verbose = m_p->m_is_debug_apply_operation;
1411 if (is_verbose)
1412 m_p->mesh()->traceMng()->info() << "ItemGroupImpl::_initChildrenByTypeV2() name=" << name();
1413
1414 Int32 nb_basic_item_type= ItemTypeMng::nbBasicItemType();
1415 m_p->m_children_by_type_ids.resize(nb_basic_item_type);
1416 for( Integer i=0; i<nb_basic_item_type; ++i ){
1417 m_p->m_children_by_type_ids[i] = UniqueArray<Int32>{MemoryUtils::getDefaultDataAllocator()};
1418 }
1419}
1420
1421/*---------------------------------------------------------------------------*/
1422/*---------------------------------------------------------------------------*/
1423
1424void ItemGroupImpl::
1425_computeChildrenByType()
1426{
1427 ItemGroup that_group(this);
1428 ITraceMng * trace = that_group.mesh()->traceMng();
1429 trace->debug(Trace::High) << "ItemGroupImpl::_computeChildrenByType for " << name();
1430
1431 Integer nb_basic_item_type = ItemTypeMng::nbBasicItemType();
1432
1433 UniqueArray< SharedArray<Int32> > items_by_type(nb_basic_item_type);
1434 for( Integer i=0; i<nb_basic_item_type; ++i ){
1435 ItemGroupImpl * impl = m_p->m_children_by_type[i];
1436 impl->beginTransaction();
1437 }
1438
1439 ENUMERATE_ITEM(iitem,that_group){
1440 const Item& item = *iitem;
1441 Integer item_type = item.type();
1442 if (item_type<nb_basic_item_type)
1443 items_by_type[item_type].add(iitem.itemLocalId());
1444 }
1445
1446 for( Integer i=0; i<nb_basic_item_type; ++i ){
1447 ItemGroupImpl * impl = m_p->m_children_by_type[i];
1448 impl->setItems(items_by_type[i]);
1449 impl->endTransaction();
1450 }
1451}
1452
1453/*---------------------------------------------------------------------------*/
1454/*---------------------------------------------------------------------------*/
1455
1456void ItemGroupImpl::
1457_computeChildrenByTypeV2()
1458{
1459 ItemGroup that_group(this);
1460 Int32 nb_item = size();
1461 IMesh* mesh = m_p->mesh();
1462 ItemTypeMng* type_mng = mesh->itemTypeMng();
1463 ITraceMng* trace = mesh->traceMng();
1464 bool is_verbose = m_p->m_is_debug_apply_operation;
1465 if (is_verbose)
1466 trace->info() << "ItemGroupImpl::_computeChildrenByTypeV2 for " << name();
1467
1468 // Si le maillage est cartésien, on sait que toutes les entités ont le même type
1469 if (nb_item>0 && mesh->meshKind().meshStructure()==eMeshStructure::Cartesian){
1470 ItemInfoListView lv(m_p->m_item_family->itemInfoListView());
1471 m_p->m_unique_children_type = ItemTypeId{lv.typeId(m_p->itemsLocalId()[0])};
1472 return;
1473 }
1474
1475 Int32 nb_basic_item_type = ItemTypeMng::nbBasicItemType();
1476 m_p->m_unique_children_type = ItemTypeId{IT_NullType};
1477
1478 UniqueArray<Int32> nb_items_by_type(nb_basic_item_type);
1479 nb_items_by_type.fill(0);
1480 ENUMERATE_(Item,iitem,that_group){
1481 Item item = *iitem;
1482 Int16 item_type = item.type();
1483 if (item_type<nb_basic_item_type)
1484 ++nb_items_by_type[item_type];
1485 }
1486
1487 Int32 nb_different_type = 0;
1488 for( Int32 i=0; i<nb_basic_item_type; ++i ){
1489 m_p->m_children_by_type_ids[i].clear();
1490 const Int32 n = nb_items_by_type[i];
1491 m_p->m_children_by_type_ids[i].reserve(n);
1492 if (n>0)
1493 ++nb_different_type;
1494 if (is_verbose)
1495 trace->info() << "ItemGroupImpl::_computeChildrenByTypeV2 for " << name()
1496 << " type=" << type_mng->typeName(i) << " nb=" << n;
1497 }
1498 if (is_verbose)
1499 trace->info() << "ItemGroupImpl::_computeChildrenByTypeV2 for " << name()
1500 << " nb_item=" << nb_item << " nb_different_type=" << nb_different_type;
1501
1502 // Si nb_different_type == 1, cela signifie qu'il n'y a qu'un seul
1503 // type d'entité et on conserve juste ce type car dans ce cas on passera
1504 // directement le groupe en argument de applyOperation().
1505 if (nb_item>0 && nb_different_type==1){
1506 ItemInfoListView lv(m_p->m_item_family->itemInfoListView());
1507 m_p->m_unique_children_type = ItemTypeId{lv.typeId(m_p->itemsLocalId()[0])};
1508 if (is_verbose)
1509 trace->info() << "ItemGroupImpl::_computeChildrenByTypeV2 for " << name()
1510 << " unique_type=" << type_mng->typeName(m_p->m_unique_children_type);
1511 return;
1512 }
1513
1514 ENUMERATE_(Item,iitem,that_group){
1515 Item item = *iitem;
1516 Integer item_type = item.type();
1517 if (item_type<nb_basic_item_type)
1518 m_p->m_children_by_type_ids[item_type].add(iitem.itemLocalId());
1519 }
1520
1521 for( Int32 i=0; i<nb_basic_item_type; ++i )
1522 applySimdPadding(m_p->m_children_by_type_ids[i]);
1523}
1524
1525/*---------------------------------------------------------------------------*/
1526/*---------------------------------------------------------------------------*/
1527
1528void ItemGroupImpl::
1529_executeExtend(const Int32ConstArrayView* info)
1530{
1531 ARCANE_UNUSED(info);
1532 // On ne sait encore calculer appliquer des transformations à des groupes calculés
1533 // On choisit l'invalidation systématique
1534 m_p->notifyInvalidateObservers();
1535}
1536
1537/*---------------------------------------------------------------------------*/
1538/*---------------------------------------------------------------------------*/
1539
1540void ItemGroupImpl::
1541_executeReduce(const Int32ConstArrayView* info)
1542{
1543 ARCANE_UNUSED(info);
1544 // On ne sait encore calculer appliquer des transformations à des groupes calculés
1545 // On choisit l'invalidation systématique
1546 m_p->notifyInvalidateObservers();
1547}
1548
1549/*---------------------------------------------------------------------------*/
1550/*---------------------------------------------------------------------------*/
1551
1552void ItemGroupImpl::
1553_executeCompact(const Int32ConstArrayView* info)
1554{
1555 ARCANE_UNUSED(info);
1556 // On ne sait encore calculer appliquer des transformations à des groupes calculés
1557 // On choisit l'invalidation systématique en différé (évaluée lors du prochain checkNeedUpdate)
1558 m_p->notifyInvalidateObservers();
1559}
1560
1561/*---------------------------------------------------------------------------*/
1562/*---------------------------------------------------------------------------*/
1563
1564void ItemGroupImpl::
1565_executeInvalidate()
1566{
1567 m_p->setNeedRecompute();
1568 m_p->notifyInvalidateObservers();
1569}
1570
1571/*---------------------------------------------------------------------------*/
1572/*---------------------------------------------------------------------------*/
1573
1574void ItemGroupImpl::
1575_updateNeedInfoFlag(const bool flag)
1576{
1577 if (m_p->m_observer_need_info == flag)
1578 return;
1579 m_p->m_observer_need_info = flag;
1580 // Si change, change aussi l'observer du parent pour qu'il adapte les besoins en info de transition
1581 ItemGroupImpl * parent = m_p->m_parent;
1582 if (parent) {
1583 parent->detachObserver(this);
1584 if (m_p->m_observer_need_info) {
1585 parent->attachObserver(this,newItemGroupObserverT(this,
1586 &ItemGroupImpl::_executeExtend,
1587 &ItemGroupImpl::_executeReduce,
1588 &ItemGroupImpl::_executeCompact,
1589 &ItemGroupImpl::_executeInvalidate));
1590 } else {
1591 parent->attachObserver(this,newItemGroupObserverT(this,
1592 &ItemGroupImpl::_executeInvalidate));
1593 }
1594 }
1595}
1596
1597/*---------------------------------------------------------------------------*/
1598/*---------------------------------------------------------------------------*/
1599
1600void ItemGroupImpl::
1601_forceInvalidate(const bool self_invalidate)
1602{
1603 // (HP) TODO: Mettre un observer forceInvalidate pour prévenir tout le monde ?
1604 // avec forceInvalidate on doit invalider mais ne rien calculer
1605 if (self_invalidate) {
1606 m_p->setNeedRecompute();
1607 m_p->m_need_invalidate_on_recompute = true;
1608 }
1609
1610 for( const auto& i : m_p->m_sub_groups )
1611 i.second->_forceInvalidate(true);
1612}
1613
1614/*---------------------------------------------------------------------------*/
1615/*---------------------------------------------------------------------------*/
1616
1618destroy()
1619{
1620 // Détache les observateurs. Cela modifie \a m_observers donc il faut
1621 // en faire une copie
1622 {
1623 std::vector<const void*> ptrs;
1624 for( const auto& i : m_p->m_observers )
1625 ptrs.push_back(i.first);
1626 for( const void* i : ptrs )
1627 detachObserver(i);
1628 }
1629
1630 // Le groupe de toutes les entités est spécial. Il ne faut jamais le détruire
1631 // vraiement.
1632 if (m_p->m_is_all_items)
1633 m_p->resetSubGroups();
1634 else{
1635 delete m_p;
1636 m_p = new ItemGroupInternal();
1637 }
1638}
1639
1640/*---------------------------------------------------------------------------*/
1641/*---------------------------------------------------------------------------*/
1642
1645{
1646 if(!m_p->m_group_index_table.isUsed()) {
1647 m_p->m_group_index_table = SharedPtrT<GroupIndexTable>(new GroupIndexTable(this));
1648 ITraceMng* trace = m_p->m_mesh->traceMng();
1649 trace->debug(Trace::High) << "** CREATION OF LOCAL ID TO INDEX TABLE OF GROUP : " << m_p->m_name;
1650 m_p->m_group_index_table->update();
1651 }
1652 return m_p->m_group_index_table;
1653}
1654
1655/*---------------------------------------------------------------------------*/
1656/*---------------------------------------------------------------------------*/
1657
1660{
1661 if(!m_p->m_synchronizer.get()) {
1662 IParallelMng* pm = m_p->m_mesh->parallelMng();
1663 ItemGroup this_group(this);
1664 m_p->m_synchronizer = ParallelMngUtils::createSynchronizerRef(pm,this_group);
1665 ITraceMng* trace = m_p->m_mesh->traceMng();
1666 trace->debug(Trace::High) << "** CREATION OF SYNCHRONIZER OF GROUP : " << m_p->m_name;
1667 m_p->m_synchronizer->compute();
1668 }
1669 return m_p->m_synchronizer.get();
1670}
1671
1672/*---------------------------------------------------------------------------*/
1673/*---------------------------------------------------------------------------*/
1674
1677{
1678 return m_p->m_synchronizer.get();
1679}
1680
1681/*---------------------------------------------------------------------------*/
1682/*---------------------------------------------------------------------------*/
1683
1685checkIsSorted() const
1686{
1687 if (null())
1688 return true;
1689
1690 // TODO: stocker l'info dans un flag et ne refaire le test que si
1691 // la liste des entités a changer (utiliser timestamp()).
1692 ItemInternalList items(m_p->items());
1693 Int32ConstArrayView items_lid(m_p->itemsLocalId());
1694 Integer nb_item = items_lid.size();
1695 // On est toujours trié si une seule entité ou moins.
1696 if (nb_item<=1)
1697 return true;
1698 // Compare chaque uniqueId() avec le précédent et vérifie qu'il est
1699 // supérieur.
1700 ItemUniqueId last_uid = items[items_lid[0]]->uniqueId();
1701 for( Integer i=1; i<nb_item; ++i ){
1702 ItemUniqueId uid = items[items_lid[i]]->uniqueId();
1703 if (uid<last_uid)
1704 return false;
1705 last_uid = uid;
1706 }
1707 return true;
1708}
1709
1710/*---------------------------------------------------------------------------*/
1711/*---------------------------------------------------------------------------*/
1712
1713void ItemGroupImpl::
1714deleteMe()
1715{
1716 // S'il s'agit de 'shared_null'. Il faut le positionner à nullptr pour qu'il
1717 // soit réalloué éventuellement par _buildSharedNull().
1718 if (this==shared_null){
1719 shared_null = nullptr;
1720 }
1721 delete this;
1722}
1723
1724/*---------------------------------------------------------------------------*/
1725/*---------------------------------------------------------------------------*/
1726
1727void ItemGroupImpl::
1728_buildSharedNull()
1729{
1730 if (!shared_null){
1731 shared_null = new ItemGroupImplNull();
1732 shared_null->addRef();
1733 }
1734}
1735
1736/*---------------------------------------------------------------------------*/
1737/*---------------------------------------------------------------------------*/
1738
1739void ItemGroupImpl::
1740_destroySharedNull()
1741{
1742 // Supprime une référence à 'shared_null'. Si le nombre de référence
1743 // devient égal à 0, alors l'instance 'shared_null' est détruite.
1744 if (shared_null)
1745 shared_null->removeRef();
1746}
1747
1748/*---------------------------------------------------------------------------*/
1749/*---------------------------------------------------------------------------*/
1750
1753{
1754 return m_p->isContiguous();
1755}
1756
1757/*---------------------------------------------------------------------------*/
1758/*---------------------------------------------------------------------------*/
1759
1762{
1763 m_p->checkIsContiguous();
1764}
1765
1766/*---------------------------------------------------------------------------*/
1767/*---------------------------------------------------------------------------*/
1768
1770capacity() const
1771{
1772 Int32Array& items_lid = m_p->mutableItemsLocalId();
1773 return items_lid.capacity();
1774}
1775
1776/*---------------------------------------------------------------------------*/
1777/*---------------------------------------------------------------------------*/
1778
1781{
1782 if (hasComputeFunctor()){
1783 // Groupe calculé. On l'invalide et on supprime ses éléments
1784 invalidate(false);
1785 m_p->mutableItemsLocalId().clear();
1786 }
1787
1788 if (m_p->variableItemsLocalid())
1789 m_p->variableItemsLocalid()->variable()->shrinkMemory();
1790 else
1791 m_p->mutableItemsLocalId().shrink();
1792
1793 m_p->applySimdPadding();
1794}
1795
1796/*---------------------------------------------------------------------------*/
1797/*---------------------------------------------------------------------------*/
1798
1799ItemGroupImplInternal* ItemGroupImpl::
1800_internalApi() const
1801{
1802 return &m_p->m_internal_api;
1803}
1804
1805/*---------------------------------------------------------------------------*/
1806/*---------------------------------------------------------------------------*/
1807
1808} // End namespace Arcane
1809
1810/*---------------------------------------------------------------------------*/
1811/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
Integer capacity() const
Capacité (nombre d'éléments alloués) du vecteur.
Integer size() const
Nombre d'éléments du vecteur.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
Exception lorsqu'un argument est invalide.
void copy(const U &copy_array)
Recopie le tableau copy_array dans l'instance.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
void fill(ConstReferenceType value)
Remplit le tableau avec la valeur value.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void clear()
Supprime les éléments du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
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.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual ItemGroup createGroup(const String &name, Int32ConstArrayView local_ids, bool do_override=false)=0
Créé un groupe d'entités de nom name contenant les entités local_ids.
virtual IMesh * mesh() const =0
Maillage associé
virtual bool needInfo() const =0
Indique si l'observer aura besoin d'information de transition.
Interface d'un opérateur sur des entités rangées par type.
virtual ITraceMng * traceMng()=0
Gestionnaire de message associé
virtual ItemTypeMng * itemTypeMng() const =0
Gestionnaire de types d'entités associé
virtual const MeshPartInfo & meshPartInfo() const =0
Informations sur les parties du maillage.
Interface du gestionnaire de parallélisme pour un sous-domaine.
Interface du gestionnaire de traces.
virtual TraceMessage fatal()=0
Flot pour un message d'erreur fatale.
virtual TraceMessage info()=0
Flot pour un message d'information.
virtual TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium)=0
Flot pour un message de debug.
Interface d'un service de synchronisation de variable.
bool isSuppressed() const
Vrai si l'entité est supprimée.
Int32 localId() const
Numéro local (au sous-domaine) de l'entité
Fonctor pour le calcul des éléments d'un groupe.
void executeFunctor() override
Exécute la méthode associé
const String & name() const
Retourne le nom du groupe.
void removeItems(Int32ConstArrayView items_local_id, bool check_if_present)
Supprime les entités items_local_id du groupe.
bool checkNeedUpdate()
Réactualise le groupe si nécessaire.
ItemGroupImpl * activeCellGroup()
AMR.
void removeAddItems(Int32ConstArrayView removed_local_id, Int32ConstArrayView added_local_id, bool check_if_present)
Supprime et ajoute les entités removed_local_id et added_local_id du groupe.
ItemGroupImplInternal * _internalApi() const
API interne à Arcane.
void setItems(Int32ConstArrayView items_local_id)
Positionne les entités du groupe à items_local_id.
void setOwn(bool v)
Positionne la propriété de groupe local ou non.
Int64 timestamp() const
Retourne le temps du groupe. Ce temps est incrémenté après chaque modification.
ItemInternalList itemsInternal() const
Liste des entités sur lesquelles s'appuie le groupe.
void endTransaction()
Termine une transaction.
void invalidate(bool force_recompute)
Invalide le groupe.
ItemGroupImpl * nodeGroup()
Groupe des noeuds des éléments de ce groupe.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present)
Ajoute les entités de numéros locaux items_local_id.
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
ItemGroupImpl * parent() const
Groupe parent (0 si aucun)
ItemGroupImpl * cellGroup()
Groupe des mailles des éléments de ce groupe.
ItemGroupImpl * innerFaceGroup()
Groupe des faces internes des éléments de ce groupe.
eItemKind itemKind() const
Genre du groupe. Il s'agit du genre de ses éléments.
ItemGroupImpl * createSubGroup(const String &suffix, IItemFamily *family, ItemGroupComputeFunctor *functor)
Crée un sous-groupe calculé
void checkLocalIdsAreContiguous() const
Vérifie si les entités du groupe ont des localIds() contigüs.
virtual ~ItemGroupImpl()
Libère les ressources.
ItemGroupImpl * edgeGroup()
Groupe des arêtes des éléments de ce groupe.
bool null() const
Retourne true si le groupe est nul.
void clear()
Supprime les entités du groupe.
ItemGroupImpl * faceGroup()
Groupe des faces des éléments de ce groupe.
void destroy()
Détruit le groupe. Après cet appel, le groupe devient un groupe nul.
void setLocalToSubDomain(bool v)
Positionne le booléen indiquant si le groupe est local au sous-domaine.
void removeSuppressedItems()
Supprime du groupe les entités dont le flag isSuppressed() est vrai.
const String & fullName() const
Nom complet du groupe (avec maillage + famille)
ItemGroupImpl * ownGroup()
Groupe des entité propres des entités de ce groupe.
IMesh * mesh() const
Maillage auquel appartient le groupe (0 pour le groupe nul).
bool checkIsSorted() const
Vérifie et retourne si le groupe est trié par uniqueId() croissants.
void checkValid()
Vérifie que le groupe est valide.
IVariableSynchronizer * synchronizer()
Synchronizer du groupe.
Integer size() const
Nombre d'entités du groupe.
Int32ConstArrayView itemsLocalId() const
Liste des numéros locaux des entités de ce groupe.
bool needSynchronization() const
Indique si le groupe a structurellement besoin d'une synchro parallèle.
ItemGroupImpl * ownActiveCellGroup()
Groupe des mailles propres actives de ce groupe.
SharedPtrT< GroupIndexTable > localIdToIndex()
Table des local ids vers une position pour toutes les entités du groupe.
ItemInfoListView itemInfoListView() const
Liste des entités sur lesquelles s'appuie le groupe.
void attachObserver(const void *ref, IItemGroupObserver *obs)
Attache un observer.
ItemGroupImpl * outerActiveFaceGroup()
Groupe des faces externes actives des éléments de ce groupe.
void detachObserver(const void *ref)
Détache un observer.
IItemFamily * itemFamily() const
Familly à laquelle appartient le groupe (ou 0 si aucune)
bool isLocalToSubDomain() const
AMR OFF.
ItemGroupImpl * ghostGroup()
Items in the group not owned by the subdomain.
ItemGroupImpl * ownLevelCellGroup(const Integer &level)
Groupe des mailles propres actives de ce groupe.
Int64 capacity() const
Nombre d'éléments alloués.
bool isContiguousLocalIds() const
Indique si les entités du groupe ont des localIds() contigüs.
ItemGroupImpl * innerActiveFaceGroup()
Groupe des faces internes actives des éléments de ce groupe.
void applyOperation(IItemOperationByBasicType *operation)
Applique l'opération operation sur les entités du groupe.
void beginTransaction()
Débute une transaction.
ItemGroupImpl * levelCellGroup(const Integer &level)
Groupe des mailles actives de ce groupe.
bool hasComputeFunctor() const
Indique si le groupe est calculé
bool hasSynchronizer()
Indique si ce groupe possède un synchroniser.
bool hasInfoObserver() const
Indique si le contenu de ce groupe est observé.
void setComputeFunctor(IFunctor *functor)
Définit une fonction de calcul de groupe.
ItemGroupImpl * ownActiveFaceGroup()
Groupe des faces externes actives des éléments de ce groupe.
bool isOwn() const
Retourne si le groupe contient uniquement des éléments propres au sous-domaine.
ItemGroupImpl()
Construit un groupe nul.
ItemGroup parentGroup()
Groupe parent.
bool empty() const
Vrai si le groupe est vide.
ItemGroupImpl * activeFaceGroup()
Groupe des faces actives propres au domaine.
const String & name() const
Nom du groupe.
ItemGroupImpl * outerFaceGroup()
Groupe des faces externes des éléments de ce groupe.
void shrinkMemory()
Limite au maximum la mémoire utilisée par le groupe.
ItemGroupImpl * findSubGroup(const String &suffix)
Accède à un sous-groupe calculé
void changeIds(Int32ConstArrayView old_to_new_ids)
Change les indices des entités du groupe.
Vue sur une liste pour obtenir des informations sur les entités.
Gestionnaire des types d'entités d'un maillage.
Definition ItemTypeMng.h:65
static Integer nbBasicItemType()
nombre de types disponibles
String typeName(Integer id) const
Nom du type correspondant au numéro id.
Identifiant unique d'une entité.
Vue d'un tableau d'éléments de type T.
Definition Span.h:673
Chaîne de caractères unicode.
Vecteur 1D de données avec sémantique par valeur (style STL).
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
ItemGroupT< Edge > EdgeGroup
Groupe d'arêtes.
Definition ItemTypes.h:173
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
IMemoryAllocator * getDefaultDataAllocator()
Allocateur par défaut pour les données.
Int32 checkResizeArrayWithCapacity(Array< DataType > &array, Int64 new_size, bool force_resize)
Redimensionne un tableau en ajoutant une réserve de mémoire.
void copy(MutableMemoryView destination, eMemoryResource destination_mem, ConstMemoryView source, eMemoryResource source_mem, const RunQueue *queue=nullptr)
Copie de source vers destination en utilisant la file queue.
Ref< IVariableSynchronizer > createSynchronizerRef(IParallelMng *pm, IItemFamily *family)
Retourne une interface pour synchroniser des variables sur le groupe de la famille family.
-*- 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
std::int64_t Int64
Type entier signé sur 64 bits.
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
@ Cartesian
Maillage cartésien.
Definition MeshKind.h:35
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:428
ArrayView< Int32 > Int32ArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:540
eItemKind
Genre d'entité de maillage.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Face
Entité de maillage de genre face.
@ IK_Edge
Entité de maillage de genre arête.
std::int16_t Int16
Type entier signé sur 16 bits.
IItemGroupObserver * newItemGroupObserverT(T *object, typename IItemGroupObserver::FuncTraits< T >::FuncPtr funcptr)
Utilitaire pour création simplifié de ItemGroupObserverT.
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.