Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ItemGroupImpl.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/* ItemGroupImpl.cc (C) 2000-2025 */
9/* */
10/* Implementation of a mesh entity group. */
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
46class ItemGroupImplNull
47: public ItemGroupImpl
48{
49 public:
50
51 ItemGroupImplNull()
53 {}
54
55 public:
56
58 const String& name() const { return m_name; }
59 const String& fullName() const { return m_name; }
60
61 public:
62
63 virtual void convert(NodeGroup& g) { g = NodeGroup(); }
64 virtual void convert(EdgeGroup& g) { g = EdgeGroup(); }
65 virtual void convert(FaceGroup& g) { g = FaceGroup(); }
66 virtual void convert(CellGroup& g) { g = CellGroup(); }
67
68 private:
69
70 String m_name;
71};
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
75
76ItemGroupImpl* ItemGroupImpl::shared_null = nullptr;
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80
81class ItemGroupImplItemGroupComputeFunctor
82: public ItemGroupComputeFunctor
83{
84 private:
85
86 typedef void (ItemGroupImpl::*FuncPtr)();
87
88 public:
89
90 ItemGroupImplItemGroupComputeFunctor(ItemGroupImpl* parent, FuncPtr funcPtr)
91 : ItemGroupComputeFunctor()
92 , m_parent(parent)
93 , m_function(funcPtr)
94 {}
95
96 public:
97
98 void executeFunctor() override
99 {
100 (m_parent->*m_function)();
101 }
102
103 private:
104
105 ItemGroupImpl* m_parent;
106 FuncPtr m_function;
107};
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111
112ItemGroupImpl* ItemGroupImpl::
113checkSharedNull()
114{
115 // Normally this test is only true if we have a global instance
116 // of 'ItemGroup' which is discouraged. Otherwise, _buildSharedNull() was
117 // automatically called during initialization (in arcaneInitialize()).
118 if (!shared_null)
120 return shared_null;
121}
122
123/*---------------------------------------------------------------------------*/
124/*---------------------------------------------------------------------------*/
125
127ItemGroupImpl(IItemFamily* family, const String& name)
128: m_p(new ItemGroupInternal(family, name))
129{
130 m_p->m_sub_parts_by_type.setImpl(this);
131}
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
138: m_p(new ItemGroupInternal(family, parent, name))
139{
140 m_p->m_sub_parts_by_type.setImpl(this);
141}
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
148: m_p(new ItemGroupInternal())
149{
150 m_p->m_sub_parts_by_type.setImpl(this);
151}
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
158{
159 delete m_p;
160}
161
162/*---------------------------------------------------------------------------*/
163/*---------------------------------------------------------------------------*/
164
166name() const
167{
168 return m_p->name();
169}
170
171/*---------------------------------------------------------------------------*/
172/*---------------------------------------------------------------------------*/
173
175fullName() const
176{
177 return m_p->fullName();
178}
179
180/*---------------------------------------------------------------------------*/
181/*---------------------------------------------------------------------------*/
182
184size() const
185{
186 return m_p->itemsLocalId().size();
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
193empty() const
194{
195 return m_p->itemsLocalId().empty();
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
202itemsLocalId() const
203{
204 return m_p->itemsLocalId();
205}
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
209
212{
213 if (m_p->m_transaction_mode)
214 ARCANE_FATAL("Transaction mode already started");
215 m_p->m_transaction_mode = true;
216}
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
220
223{
224 if (!m_p->m_transaction_mode)
225 ARCANE_FATAL("Transaction mode not started");
226 m_p->m_transaction_mode = false;
227 if (m_p->m_need_recompute) {
228 m_p->m_need_recompute = false;
229 m_p->m_need_invalidate_on_recompute = false;
230 m_p->notifyInvalidateObservers();
231 }
232}
233
234/*---------------------------------------------------------------------------*/
235/*---------------------------------------------------------------------------*/
236
238unguardedItemsLocalId(const bool self_invalidate)
239{
240 ITraceMng* trace = m_p->m_mesh->traceMng();
241 trace->debug(Trace::Medium) << "ItemGroupImpl::unguardedItemsLocalId on group " << name()
242 << " with self_invalidate=" << self_invalidate;
243
244 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
245 ARCANE_FATAL("Direct access for computed group in only available during a transaction");
246
247 _forceInvalidate(self_invalidate);
248 return m_p->mutableItemsLocalId();
249}
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
255parent() const
256{
257 return m_p->m_parent;
258}
259
260/*---------------------------------------------------------------------------*/
261/*---------------------------------------------------------------------------*/
262
264mesh() const
265{
266 return m_p->mesh();
267}
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
271
273itemFamily() const
274{
275 return m_p->m_item_family;
276}
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
282null() const
283{
284 return m_p->null();
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
291isOwn() const
292{
293 return m_p->m_is_own;
294}
295
296/*---------------------------------------------------------------------------*/
297/*---------------------------------------------------------------------------*/
298
300setOwn(bool v)
301{
302 const bool is_own = m_p->m_is_own;
303 if (is_own == v)
304 return;
305 if (!is_own) {
306 if (m_p->m_own_group)
307 ARCANE_THROW(NotSupportedException, "Setting Own with 'Own' sub-group already defined");
308 }
309 else {
310 // We are allowed to reset setOwn() to 'false' for the group of all
311 // entities. This is necessary during recovery if the number of mesh parts
312 // is different from the IParallelMng associated with the family
313 if (!isAllItems())
314 ARCANE_THROW(NotSupportedException, "Un-setting Own on a own group");
315 }
316 m_p->m_is_own = v;
317 // (HP) TODO: Should we notify observers?
318}
319
320/*---------------------------------------------------------------------------*/
321/*---------------------------------------------------------------------------*/
322
324itemKind() const
325{
326 return m_p->kind();
327}
328
329/*---------------------------------------------------------------------------*/
330/*---------------------------------------------------------------------------*/
331
333ownGroup()
334{
335 ItemGroupImpl* ii = m_p->m_own_group;
336 // The flag is already set in ItemGroupInternal::_init or ItemGroupImpl::setOwn
337 if (!ii) {
338 if (m_p->m_is_own) {
339 ii = this;
340 m_p->m_own_group = ii;
341 }
342 else {
343 ii = createSubGroup("Own", m_p->m_item_family, new OwnItemGroupComputeFunctor());
344 m_p->m_own_group = ii;
345 ii->setOwn(true);
346 }
347 }
348 return ii;
349}
350
351/*---------------------------------------------------------------------------*/
352/*---------------------------------------------------------------------------*/
353
356{
357 ItemGroupImpl* ii = m_p->m_ghost_group;
358 if (!ii) {
359 ii = createSubGroup("Ghost", m_p->m_item_family, new GhostItemGroupComputeFunctor());
360 m_p->m_ghost_group = ii;
361 }
362 return ii;
363}
364
365/*---------------------------------------------------------------------------*/
366/*---------------------------------------------------------------------------*/
367
368ItemGroupImpl* ItemGroupImpl::
369interfaceGroup()
370{
371 if (itemKind() != IK_Face)
372 return checkSharedNull();
374 if (!ii) {
377 }
378 return ii;
379}
380
381/*---------------------------------------------------------------------------*/
382/*---------------------------------------------------------------------------*/
383
385nodeGroup()
386{
387 if (itemKind() == IK_Node)
388 return this;
389 ItemGroupImpl* ii = m_p->m_node_group;
390 if (!ii) {
391 ii = createSubGroup("Nodes", m_p->m_mesh->nodeFamily(), new ItemItemGroupComputeFunctor<Node>());
392 m_p->m_node_group = ii;
393 }
394 return ii;
395}
396
397/*---------------------------------------------------------------------------*/
398/*---------------------------------------------------------------------------*/
399
401edgeGroup()
402{
403 if (itemKind() == IK_Edge)
404 return this;
405 ItemGroupImpl* ii = m_p->m_edge_group;
406 if (!ii) {
407 ii = createSubGroup("Edges", m_p->m_mesh->edgeFamily(), new ItemItemGroupComputeFunctor<Edge>());
408 m_p->m_edge_group = ii;
409 }
410 return ii;
411}
412
413/*---------------------------------------------------------------------------*/
414/*---------------------------------------------------------------------------*/
415
417faceGroup()
418{
419 if (itemKind() == IK_Face)
420 return this;
421 ItemGroupImpl* ii = m_p->m_face_group;
422 if (!ii) {
423 ii = createSubGroup("Faces", m_p->m_mesh->faceFamily(), new ItemItemGroupComputeFunctor<Face>());
424 m_p->m_face_group = ii;
425 }
426 return ii;
427}
428
429/*---------------------------------------------------------------------------*/
430/*---------------------------------------------------------------------------*/
431
433cellGroup()
434{
435 if (itemKind() == IK_Cell)
436 return this;
437 ItemGroupImpl* ii = m_p->m_cell_group;
438 if (!ii) {
439 ii = createSubGroup("Cells", m_p->m_mesh->cellFamily(), new ItemItemGroupComputeFunctor<Cell>());
440 m_p->m_cell_group = ii;
441 }
442 return ii;
443}
444
445/*---------------------------------------------------------------------------*/
446/*---------------------------------------------------------------------------*/
447
450{
451 if (itemKind() != IK_Cell)
452 return checkSharedNull();
453 ItemGroupImpl* ii = m_p->m_inner_face_group;
454 if (!ii) {
455 ii = createSubGroup("InnerFaces", m_p->m_mesh->faceFamily(),
457 m_p->m_inner_face_group = ii;
458 }
459 return ii;
460}
461
462/*---------------------------------------------------------------------------*/
463/*---------------------------------------------------------------------------*/
464
467{
468 if (itemKind() != IK_Cell)
469 return checkSharedNull();
470 ItemGroupImpl* ii = m_p->m_outer_face_group;
471 if (!ii) {
472 ii = createSubGroup("OuterFaces", m_p->m_mesh->faceFamily(),
474 m_p->m_outer_face_group = ii;
475 }
476 return ii;
477}
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
481
482/*---------------------------------------------------------------------------*/
483/*---------------------------------------------------------------------------*/
484
487{
488 if (itemKind() != IK_Cell)
489 return checkSharedNull();
490 ItemGroupImpl* ii = m_p->m_active_cell_group;
491
492 if (!ii) {
493 ii = createSubGroup("ActiveCells", m_p->m_mesh->cellFamily(),
495 m_p->m_active_cell_group = ii;
496 }
497 return ii;
498}
499
500/*---------------------------------------------------------------------------*/
501/*---------------------------------------------------------------------------*/
502
505{
506 if (itemKind() != IK_Cell)
507 return checkSharedNull();
508 ItemGroupImpl* ii = m_p->m_own_active_cell_group;
509 // The flag is already set in ItemGroupInternal::_init or ItemGroupImpl::setOwn
510 if (!ii) {
511 ii = createSubGroup("OwnActiveCells", m_p->m_mesh->cellFamily(),
513 m_p->m_own_active_cell_group = ii;
514 ii->setOwn(true);
515 }
516 return ii;
517}
518/*---------------------------------------------------------------------------*/
519/*---------------------------------------------------------------------------*/
520
522levelCellGroup(const Integer& level)
523{
524 if (itemKind() != IK_Cell)
525 return checkSharedNull();
526 ItemGroupImpl* ii = m_p->m_level_cell_group[level];
527 if (!ii) {
528 ii = createSubGroup(String::format("LevelCells{0}", level),
529 m_p->m_mesh->cellFamily(),
531 m_p->m_level_cell_group[level] = ii;
532 }
533 return ii;
534}
535
536/*---------------------------------------------------------------------------*/
537/*---------------------------------------------------------------------------*/
538
540ownLevelCellGroup(const Integer& level)
541{
542 if (itemKind() != IK_Cell)
543 return checkSharedNull();
544 ItemGroupImpl* ii = m_p->m_own_level_cell_group[level];
545 // The flag is already set in ItemGroupInternal::_init or ItemGroupImpl::setOwn
546 if (!ii) {
547 ii = createSubGroup(String::format("OwnLevelCells{0}", level),
548 m_p->m_mesh->cellFamily(),
550 m_p->m_own_level_cell_group[level] = ii;
551 ii->setOwn(true);
552 }
553 return ii;
554}
555/*---------------------------------------------------------------------------*/
556/*---------------------------------------------------------------------------*/
557
560{
561 if (itemKind() != IK_Cell)
562 return checkSharedNull();
563 ItemGroupImpl* ii = m_p->m_active_face_group;
564 if (!ii) {
565 ii = createSubGroup("ActiveFaces", m_p->m_mesh->faceFamily(),
567 m_p->m_active_face_group = ii;
568 }
569 return ii;
570}
571
572/*---------------------------------------------------------------------------*/
573/*---------------------------------------------------------------------------*/
574
577{
578 if (itemKind() != IK_Cell)
579 return checkSharedNull();
580 ItemGroupImpl* ii = m_p->m_own_active_face_group;
581 if (!ii) {
582 ii = createSubGroup("OwnActiveFaces", m_p->m_mesh->faceFamily(),
584 m_p->m_own_active_face_group = ii;
585 }
586 return ii;
587}
588/*---------------------------------------------------------------------------*/
589/*---------------------------------------------------------------------------*/
590
593{
594 if (itemKind() != IK_Cell)
595 return checkSharedNull();
596 ItemGroupImpl* ii = m_p->m_inner_active_face_group;
597 if (!ii) {
598 ii = createSubGroup("InnerActiveFaces", m_p->m_mesh->faceFamily(),
600 m_p->m_inner_active_face_group = ii;
601 }
602 return ii;
603}
604
605/*---------------------------------------------------------------------------*/
606/*---------------------------------------------------------------------------*/
607
610{
611 if (itemKind() != IK_Cell)
612 return checkSharedNull();
613 ItemGroupImpl* ii = m_p->m_outer_active_face_group;
614 if (!ii) {
615 ii = createSubGroup("OuterActiveFaces", m_p->m_mesh->faceFamily(),
617 m_p->m_outer_active_face_group = ii;
618 }
619 return ii;
620}
621/*---------------------------------------------------------------------------*/
622/*---------------------------------------------------------------------------*/
623
625createSubGroup(const String& suffix, IItemFamily* family, ItemGroupComputeFunctor* functor)
626{
627 String sub_name = name() + "_" + suffix;
628 auto finder = m_p->m_sub_groups.find(sub_name);
629 if (finder != m_p->m_sub_groups.end()) {
630 ARCANE_FATAL("Cannot create already existing sub-group ({0}) in group ({1})",
631 suffix, name());
632 }
633 ItemGroup ig = family->createGroup(sub_name, ItemGroup(this));
634 ItemGroupImpl* ii = ig.internal();
635 ii->setComputeFunctor(functor);
636 functor->setGroup(ii);
637 // Default observer: the subgroup is not interested in detailed transition information
639 m_p->m_sub_groups[sub_name] = ii;
640 ii->invalidate(false);
641 return ii;
642}
643
644/*---------------------------------------------------------------------------*/
645/*---------------------------------------------------------------------------*/
646
648findSubGroup(const String& suffix)
649{
650 String sub_name = name() + "_" + suffix;
651 auto finder = m_p->m_sub_groups.find(sub_name);
652 if (finder != m_p->m_sub_groups.end()) {
653 return finder->second.get();
654 }
655 else {
656 // or an error?
657 return checkSharedNull();
658 }
659}
660
661/*---------------------------------------------------------------------------*/
662/*---------------------------------------------------------------------------*/
663
665changeIds(Int32ConstArrayView old_to_new_ids)
666{
667 ITraceMng* trace = m_p->m_mesh->traceMng();
668 if (m_p->m_compute_functor) {
669 trace->debug(Trace::High) << "ItemGroupImpl::changeIds on "
670 << name() << " : skip computed group";
671 return;
672 }
673
674 // ItemGroupImpl usually does not perform the checkNeedUpdate itself, rather the ItemGroup
676 if (isAllItems()) {
677 // Int32ArrayView items_lid = m_p->itemsLocalId();
678 // for( Integer i=0, is=items_lid.size(); i<is; ++i ) {
679 // Integer lid = items_lid[i];
680 // ARCANE_ASSERT((lid = old_to_new_ids[lid]),("Non uniform order on allItems"));;
681 // }
682 // m_p->notifyCompactObservers(&old_to_new_ids);
683 m_p->notifyInvalidateObservers();
684 return;
685 }
686
687 Int32ArrayView items_lid = m_p->itemsLocalId();
688 for (Integer i = 0, is = items_lid.size(); i < is; ++i) {
689 Integer old_id = items_lid[i];
690 items_lid[i] = old_to_new_ids[old_id];
691 }
692
693 m_p->updateTimestamp();
694 // For now, the entities of the variables should not be sorted
695 // partial because the corresponding values of the variables are not
696 // updated (changeGroupIds must be implemented for this)
697 // NOTE: is it useful to do this?
698 // NOTE: should it be done for others too? As far as I know, this is
699 // only useful to guarantee the same parallel/sequential result
700 if (m_p->m_observer_need_info) {
701 m_p->notifyCompactObservers(&old_to_new_ids);
702 }
703 else {
704 // No need for info, we can change their order arbitrarily
705 // TODO: #warning "(HP) Connection of this item sorting with the family?"
706 std::sort(std::begin(items_lid), std::end(items_lid));
707 m_p->notifyCompactObservers(nullptr);
708 }
709}
710
711/*---------------------------------------------------------------------------*/
712/*---------------------------------------------------------------------------*/
713
715invalidate(bool force_recompute)
716{
717#ifdef ARCANE_DEBUG
718 // if (force_recompute){
719 ITraceMng* msg = m_p->m_mesh->traceMng();
720 msg->debug(Trace::High) << "ItemGroupImpl::invalidate(force=" << force_recompute << ")"
721 << " name=" << name();
722// }
723#endif
724
725 m_p->updateTimestamp();
726 m_p->setNeedRecompute();
727 if (force_recompute)
729 m_p->notifyInvalidateObservers();
730}
731
732/*---------------------------------------------------------------------------*/
733/*---------------------------------------------------------------------------*/
734
736itemsInternal() const
737{
738 return m_p->items();
739}
740
741/*---------------------------------------------------------------------------*/
742/*---------------------------------------------------------------------------*/
743
745itemInfoListView() const
746{
747 return m_p->itemInfoListView();
748}
749
750/*---------------------------------------------------------------------------*/
751/*---------------------------------------------------------------------------*/
752
754isLocalToSubDomain() const
755{
756 return m_p->m_is_local_to_sub_domain;
757}
758
759/*---------------------------------------------------------------------------*/
760/*---------------------------------------------------------------------------*/
761
764{
765 m_p->m_is_local_to_sub_domain = v;
766}
767
768/*---------------------------------------------------------------------------*/
769/*---------------------------------------------------------------------------*/
770
772addItems(Int32ConstArrayView items_local_id, bool check_if_present)
773{
774 ARCANE_ASSERT(((!m_p->m_need_recompute && !isAllItems()) || (m_p->m_transaction_mode && isAllItems())),
775 ("Operation on invalid group"));
776 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
777 ARCANE_FATAL("Cannot add items on computed group ({0})", name());
778 IMesh* amesh = mesh();
779 if (!amesh)
780 throw ArgumentException(A_FUNCINFO, "null group");
781 ITraceMng* trace = amesh->traceMng();
782
783 Integer nb_item_to_add = items_local_id.size();
784 if (nb_item_to_add == 0)
785 return;
786
787 Int32Array& items_lid = m_p->mutableItemsLocalId();
788 const Integer current_size = items_lid.size();
789 Integer nb_added = 0;
790
791 if (isAllItems()) {
792 // Adds the new items to the end.
793 Integer nb_items_id = current_size;
794 m_p->m_items_index_in_all_group.resize(m_p->maxLocalId());
795 for (Integer i = 0, is = nb_item_to_add; i < is; ++i) {
796 Int32 local_id = items_local_id[i];
797 items_lid.add(local_id);
798 m_p->m_items_index_in_all_group[local_id] = nb_items_id + i;
799 }
800 nb_added = nb_item_to_add;
801 }
802 else if (check_if_present) {
803 // Checks that the entities to be added are not already present
804 UniqueArray<bool> presence_checks(m_p->maxLocalId());
805 presence_checks.fill(false);
806 for (Integer i = 0, is = items_lid.size(); i < is; ++i) {
807 presence_checks[items_lid[i]] = true;
808 }
809
810 for (Integer i = 0; i < nb_item_to_add; ++i) {
811 const Integer lid = items_local_id[i];
812 if (!presence_checks[lid]) {
813 items_lid.add(lid);
814 // Sets to true like this if the entity is present multiple times
815 // in \a items_local_id it still works.
816 presence_checks[lid] = true;
817 ++nb_added;
818 }
819 }
820 }
821 else {
822 nb_added = nb_item_to_add;
823 MemoryUtils::checkResizeArrayWithCapacity(items_lid, current_size + nb_added, false);
824 SmallSpan<Int32> ptr = items_lid.subView(current_size, nb_added);
825 MemoryUtils::copy<Int32>(ptr, items_local_id);
826 }
827
828 if (arcaneIsCheck()) {
829 trace->info(5) << "ItemGroupImpl::addItems() group <" << name() << "> "
830 << " checkpresent=" << check_if_present
831 << " nb_current=" << current_size
832 << " want_to_add=" << nb_item_to_add
833 << " effective_added=" << nb_added;
834 checkValid();
835 }
836
837 if (nb_added != 0) {
838 m_p->updateTimestamp();
839 Int32ConstArrayView observation_info(nb_added, items_lid.unguardedBasePointer() + current_size);
840 m_p->notifyExtendObservers(&observation_info);
841 }
842}
843
844/*---------------------------------------------------------------------------*/
845/*---------------------------------------------------------------------------*/
846
848removeItems(Int32ConstArrayView items_local_id, [[maybe_unused]] bool check_if_present)
849{
850 m_p->_removeItems(items_local_id);
851}
852
853/*---------------------------------------------------------------------------*/
854/*---------------------------------------------------------------------------*/
855
857removeAddItems(Int32ConstArrayView removed_items_lids,
858 Int32ConstArrayView added_items_lids,
859 bool check_if_present)
860{
861 ARCANE_ASSERT(((!m_p->m_need_recompute && !isAllItems()) || (m_p->m_transaction_mode && isAllItems())),
862 ("Operation on invalid group"));
863 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
864 ARCANE_FATAL("Cannot remove items on computed group ({0})", name());
865 IMesh* amesh = mesh();
866 if (!amesh)
867 throw ArgumentException(A_FUNCINFO, "null group");
868 ITraceMng* trace = amesh->traceMng();
869 if (isOwn() && amesh->meshPartInfo().nbPart() != 1) {
870 ARCANE_THROW(NotSupportedException, "Cannot remove items if isOwn() is true");
871 }
872
873 Int32Array& items_lid = m_p->mutableItemsLocalId();
874
875 if (isAllItems()) {
876 ItemInternalList internals = itemsInternal();
877 const Integer internal_size = internals.size();
878 const Integer new_size = m_p->m_item_family->nbItem();
879 items_lid.resize(new_size);
880 m_p->m_items_index_in_all_group.resize(m_p->maxLocalId());
881 if (new_size == internal_size) {
882 // There are no gaps in the numbering
883 for (Integer i = 0; i < internal_size; ++i) {
884 Int32 local_id = internals[i]->localId();
885 items_lid[i] = local_id;
886 m_p->m_items_index_in_all_group[local_id] = i;
887 }
888 }
889 else {
890 Integer index = 0;
891 for (Integer i = 0; i < internal_size; ++i) {
892 ItemInternal* item = internals[i];
893 if (!item->isSuppressed()) {
894 Int32 local_id = item->localId();
895 items_lid[index] = local_id;
896 m_p->m_items_index_in_all_group[local_id] = index;
897 ++index;
898 }
899 }
900 if (index != new_size)
901 ARCANE_FATAL("Inconsistent number of elements in the generation of the group '{0}' expected={1} present={2}",
902 name(), new_size, index);
903 }
904
905 // We cannot know what has changed, so out of doubt we
906 // increment the timestamp.
907 m_p->updateTimestamp();
908 }
909 else {
910 removeItems(removed_items_lids, check_if_present);
911 addItems(added_items_lids, check_if_present);
912 }
913
914 if (arcaneIsCheck()) {
915 trace->info(5) << "ItemGroupImpl::removeAddItems() group <" << name() << "> "
916 << " old_size=" << m_p->m_item_family->nbItem()
917 << " new_size=" << size()
918 << " nb_removed=" << removed_items_lids.size()
919 << " nb_added=" << added_items_lids.size();
920 checkValid();
921 }
922}
923
924/*---------------------------------------------------------------------------*/
925/*---------------------------------------------------------------------------*/
926
928setItems(Int32ConstArrayView items_local_id)
929{
930 if (m_p->m_compute_functor && !m_p->m_transaction_mode)
931 ARCANE_FATAL("Cannot set items on computed group ({0})", name());
932 Int32Array& buf = m_p->mutableItemsLocalId();
933 buf.resize(items_local_id.size());
934 Int32ArrayView buf_view(buf);
935 buf_view.copy(items_local_id);
936 m_p->updateTimestamp();
937 m_p->m_need_recompute = false;
938 if (arcaneIsCheck()) {
939 ITraceMng* trace = m_p->mesh()->traceMng();
940 trace->debug(Trace::High) << "ItemGroupImpl::setItems() group <" << name() << "> "
941 << " size=" << size();
942 checkValid();
943 }
944
945 // We still tolerate the initial setItems by converting it to an addItems
946 if (size() != 0)
947 m_p->notifyInvalidateObservers();
948 else
949 m_p->notifyExtendObservers(&items_local_id);
950}
951
952/*---------------------------------------------------------------------------*/
953/*---------------------------------------------------------------------------*/
954
956{
957 public:
958
959 ItemSorter(ItemInfoListView items)
960 : m_items(items)
961 {}
962
963 public:
964
965 void sort(Int32ArrayView local_ids) const
966 {
967 std::sort(std::begin(local_ids), std::end(local_ids), *this);
968 }
969 bool operator()(Int32 lid1, Int32 lid2) const
970 {
971 return m_items[lid1].uniqueId() < m_items[lid2].uniqueId();
972 }
973
974 private:
975
976 ItemInfoListView m_items;
977};
978
979/*---------------------------------------------------------------------------*/
980/*---------------------------------------------------------------------------*/
981
983setItems(Int32ConstArrayView items_local_id, bool do_sort)
984{
985 if (!do_sort) {
986 setItems(items_local_id);
987 return;
988 }
989 UniqueArray<Int32> sorted_lid(items_local_id);
991 sorter.sort(sorted_lid);
992 setItems(sorted_lid);
993}
994
995/*---------------------------------------------------------------------------*/
996/*---------------------------------------------------------------------------*/
997
1000{
1001 m_p->m_is_all_items = true;
1002}
1003
1004/*---------------------------------------------------------------------------*/
1005/*---------------------------------------------------------------------------*/
1006
1008isAllItems() const
1009{
1010 return m_p->m_is_all_items;
1011}
1012
1013/*---------------------------------------------------------------------------*/
1014/*---------------------------------------------------------------------------*/
1015
1016class ItemCheckSuppressedFunctor
1017{
1018 public:
1019
1020 ItemCheckSuppressedFunctor(ItemInternalList items)
1021 : m_items(items)
1022 {
1023 }
1024
1025 public:
1026
1027 bool operator()(Integer item_lid)
1028 {
1029 return m_items[item_lid]->isSuppressed();
1030 }
1031
1032 private:
1033
1034 ItemInternalList m_items;
1035};
1036
1037/*---------------------------------------------------------------------------*/
1038/*---------------------------------------------------------------------------*/
1039
1042{
1043 // TODO: (HP) Assertion need fix"
1044 // ARCANE_ASSERT((!m_p->m_need_recompute),("Operation on invalid group"));
1045 ITraceMng* trace = m_p->mesh()->traceMng();
1046 if (m_p->m_compute_functor) {
1047 trace->debug(Trace::High) << "ItemGroupImpl::removeSuppressedItems on " << name() << " : skip computed group";
1048 return;
1049 }
1050
1051 ItemInternalList items = m_p->items();
1052 Integer nb_item = items.size();
1053 Int32Array& items_lid = m_p->mutableItemsLocalId();
1054 Integer current_size = items_lid.size();
1055 if (arcaneIsCheck()) {
1056 for (Integer i = 0; i < current_size; ++i) {
1057 if (items_lid[i] >= nb_item) {
1058 trace->fatal() << "ItemGroupImpl::removeSuppressedItems(): bad range "
1059 << " name=" << name()
1060 << " i=" << i << " lid=" << items_lid[i]
1061 << " max=" << nb_item;
1062 }
1063 }
1064 }
1065
1066 Int32UniqueArray removed_ids, removed_lids;
1067 Int32ConstArrayView* observation_info = NULL;
1068 Int32ConstArrayView* observation_info2 = NULL;
1069 Integer new_size;
1070 // If the group has observers needing information, they must be calculated
1071 if (m_p->m_observer_need_info) {
1072 removed_ids.reserve(current_size); // preparation for max size
1073 Integer index = 0;
1074 for (Integer i = 0; i < current_size; ++i) {
1075 if (!items[items_lid[i]]->isSuppressed()) {
1076 items_lid[index] = items_lid[i];
1077 ++index;
1078 }
1079 else {
1080 // trace->debug(Trace::Highest) << "Remove from group " << name() << " item " << i << " " << items_lid[i] << " " << ItemPrinter(items[items_lid[i]]);
1081 removed_lids.add(items_lid[i]);
1082 }
1083 }
1084 new_size = index;
1085 if (new_size != current_size) {
1086 items_lid.resize(new_size);
1087 observation_info = new Int32ConstArrayView(removed_lids.size(), removed_lids.unguardedBasePointer());
1088 }
1089 }
1090 else {
1091 ItemCheckSuppressedFunctor f(m_p->items());
1092 auto ibegin = std::begin(items_lid);
1093 auto new_end = std::remove_if(ibegin, std::end(items_lid), f);
1094 new_size = (Integer)(new_end - ibegin);
1095 items_lid.resize(new_size);
1096 }
1097
1098 if (arcaneIsCheck()) {
1099 trace->debug(Trace::High) << "ItemGroupImpl::removeSupressedItems() group <" << name()
1100 << "> NEW SIZE=" << new_size << " OLD=" << current_size;
1101 checkValid();
1102 }
1103
1104 // Only update if the group has been modified
1105 if (current_size != new_size) {
1106 m_p->updateTimestamp();
1107 m_p->notifyReduceObservers(observation_info);
1108 delete observation_info;
1109 delete observation_info2;
1110 }
1111}
1112
1113/*---------------------------------------------------------------------------*/
1114/*---------------------------------------------------------------------------*/
1115
1117checkValid()
1118{
1119 m_p->checkValid();
1120}
1121
1122/*---------------------------------------------------------------------------*/
1123/*---------------------------------------------------------------------------*/
1124
1125bool ItemGroupImpl::
1126_checkNeedUpdate(bool do_padding)
1127{
1128 // NOTE: the use of locks is currently experimental (June 2025)
1129 // We put the lock on the entire method to keep it simpler, but
1130 // we could only do it after checking that the update
1131 // is truly useful.
1133
1134 // In case of problems with very nested recalculations, a proposal is
1135 // to disable lines #A to enable lines #B
1136 bool has_recompute = false;
1137 if (m_p->m_need_recompute) {
1138 m_p->m_need_recompute = false;
1139 // bool need_invalidate_on_recompute = m_p->m_need_invalidate_on_recompute; // #B
1140 // m_p->m_need_invalidate_on_recompute = false; // #B
1141 if (m_p->m_compute_functor) {
1143 }
1144 // if (need_invalidate_on_recompute) { // #B
1145 // m_p->notifyInvalidateObservers(); // #B
1146 // } // #B
1147
1149 m_p->m_need_invalidate_on_recompute = false; // #A
1150 m_p->notifyInvalidateObservers(); // #A
1151 } // #A
1152 has_recompute = true;
1153 }
1154 if (do_padding)
1155 _checkUpdateSimdPadding();
1156 return has_recompute;
1157}
1158
1159/*---------------------------------------------------------------------------*/
1160/*---------------------------------------------------------------------------*/
1161
1162bool ItemGroupImpl::
1163_checkNeedUpdateNoPadding()
1164{
1165 return _checkNeedUpdate(false);
1166}
1167
1168/*---------------------------------------------------------------------------*/
1169/*---------------------------------------------------------------------------*/
1170
1171bool ItemGroupImpl::
1172_checkNeedUpdateWithPadding()
1173{
1174 return _checkNeedUpdate(true);
1175}
1176
1177/*---------------------------------------------------------------------------*/
1178/*---------------------------------------------------------------------------*/
1179
1182{
1183 return _checkNeedUpdate(false);
1184}
1185
1186/*---------------------------------------------------------------------------*/
1187/*---------------------------------------------------------------------------*/
1188
1189void ItemGroupImpl::
1190_checkUpdateSimdPadding()
1191{
1193}
1194
1195/*---------------------------------------------------------------------------*/
1196/*---------------------------------------------------------------------------*/
1197
1199clear()
1200{
1201 Int32Array& items_lid = m_p->mutableItemsLocalId();
1202 if (!items_lid.empty())
1203 // Increment only if the group is not already empty
1204 m_p->updateTimestamp();
1205 items_lid.clear();
1206 m_p->m_need_recompute = false;
1207 for (const auto& i : m_p->m_sub_groups)
1208 i.second->clear();
1209 m_p->notifyInvalidateObservers();
1210}
1211
1212/*---------------------------------------------------------------------------*/
1213/*---------------------------------------------------------------------------*/
1214
1217{
1218 if (m_p->m_parent)
1219 return ItemGroup(m_p->m_parent);
1220 return ItemGroup();
1221}
1222
1223/*---------------------------------------------------------------------------*/
1224/*---------------------------------------------------------------------------*/
1225
1228{
1229 ARCANE_ASSERT((!m_p->m_need_recompute), ("Operation on invalid group"));
1230 m_p->m_sub_parts_by_type.applyOperation(operation);
1231}
1232
1233void ItemGroupSubPartsByType::
1234applyOperation(IItemOperationByBasicType* operation)
1235{
1236 bool is_verbose = m_is_debug_apply_operation;
1237
1238 ITraceMng* tm = m_group_internal->mesh()->traceMng();
1239 if (is_verbose)
1240 tm->info() << "applyOperation name=" << m_group_internal->name() << " nb_item=" << m_group_internal->nbItem();
1241 if (isUseV2ForApplyOperation()) {
1242 if (m_children_by_type_ids.empty()) {
1243 _initChildrenByTypeV2();
1244 }
1245 Int64 t = m_group_internal->timestamp();
1246 if (is_verbose)
1247 tm->info() << "applyOperation timestamp=" << t << " last=" << m_children_by_type_ids_computed_timestamp;
1249 _computeChildrenByTypeV2();
1251 }
1252 }
1253 else {
1254 if (m_children_by_type.empty())
1255 _initChildrenByTypeV1();
1256 }
1257 IItemFamily* family = m_group_internal->m_item_family;
1258 const bool has_only_one_type = (m_unique_children_type != IT_NullType);
1259 if (is_verbose)
1260 tm->info() << "applyOperation has_only_one_type=" << has_only_one_type << " value=" << m_unique_children_type;
1261 // TODO: Remove the macro and replace it with a function.
1262
1263#define APPLY_OPERATION_ON_TYPE(ITEM_TYPE) \
1264 if (isUseV2ForApplyOperation()) { \
1265 Int16 type_id = IT_##ITEM_TYPE; \
1266 Int32ConstArrayView sub_ids = m_children_by_type_ids[type_id]; \
1267 if (has_only_one_type && type_id == m_unique_children_type) \
1268 sub_ids = m_group_internal->itemsLocalId(); \
1269 if (is_verbose && sub_ids.size() > 0) \
1270 tm->info() << "Type=" << (int)IT_##ITEM_TYPE << " nb=" << sub_ids.size(); \
1271 if (sub_ids.size() != 0) { \
1272 operation->apply##ITEM_TYPE(family->view(sub_ids)); \
1273 } \
1274 } \
1275 else { \
1276 ItemGroup group(m_children_by_type[IT_##ITEM_TYPE]); \
1277 if (!group.empty()) \
1278 operation->apply##ITEM_TYPE(group.view()); \
1279 }
1280
1281 APPLY_OPERATION_ON_TYPE(Vertex);
1282 APPLY_OPERATION_ON_TYPE(Line2);
1283 APPLY_OPERATION_ON_TYPE(Triangle3);
1284 APPLY_OPERATION_ON_TYPE(Quad4);
1285 APPLY_OPERATION_ON_TYPE(Pentagon5);
1286 APPLY_OPERATION_ON_TYPE(Hexagon6);
1287 APPLY_OPERATION_ON_TYPE(Tetraedron4);
1288 APPLY_OPERATION_ON_TYPE(Pyramid5);
1289 APPLY_OPERATION_ON_TYPE(Pentaedron6);
1290 APPLY_OPERATION_ON_TYPE(Hexaedron8);
1291 APPLY_OPERATION_ON_TYPE(Heptaedron10);
1292 APPLY_OPERATION_ON_TYPE(Octaedron12);
1293 APPLY_OPERATION_ON_TYPE(HemiHexa7);
1294 APPLY_OPERATION_ON_TYPE(HemiHexa6);
1295 APPLY_OPERATION_ON_TYPE(HemiHexa5);
1296 APPLY_OPERATION_ON_TYPE(HemiHexa7);
1297 APPLY_OPERATION_ON_TYPE(AntiWedgeLeft6);
1298 APPLY_OPERATION_ON_TYPE(AntiWedgeRight6);
1299 APPLY_OPERATION_ON_TYPE(DiTetra5);
1300 APPLY_OPERATION_ON_TYPE(DualNode);
1301 APPLY_OPERATION_ON_TYPE(DualEdge);
1302 APPLY_OPERATION_ON_TYPE(DualFace);
1303 APPLY_OPERATION_ON_TYPE(DualCell);
1304 APPLY_OPERATION_ON_TYPE(Link);
1305
1306#undef APPLY_OPERATION_ON_TYPE
1307}
1308
1309/*---------------------------------------------------------------------------*/
1310/*---------------------------------------------------------------------------*/
1311
1313needSynchronization() const
1314{
1315 return !(m_p->m_compute_functor != 0 ||
1316 m_p->m_is_local_to_sub_domain ||
1317 m_p->m_is_own);
1318}
1319
1320/*---------------------------------------------------------------------------*/
1321/*---------------------------------------------------------------------------*/
1322
1324timestamp() const
1325{
1326 return m_p->timestamp();
1327}
1328
1329/*---------------------------------------------------------------------------*/
1330/*---------------------------------------------------------------------------*/
1331
1333attachObserver(const void* ref, IItemGroupObserver* obs)
1334{
1335 auto finder = m_p->m_observers.find(ref);
1336 auto end = m_p->m_observers.end();
1337 if (finder != end) {
1338 delete finder->second;
1339 finder->second = obs;
1340 return;
1341 }
1342 else {
1343 m_p->m_observers[ref] = obs;
1344 }
1345
1346 // Update the info request flag
1347 _updateNeedInfoFlag(m_p->m_observer_need_info | obs->needInfo());
1348}
1349
1350/*---------------------------------------------------------------------------*/
1351/*---------------------------------------------------------------------------*/
1352
1354detachObserver(const void* ref)
1355{
1356 auto finder = m_p->m_observers.find(ref);
1357 auto end = m_p->m_observers.end();
1358
1359 if (finder == end)
1360 return;
1361
1362 IItemGroupObserver* obs = finder->second;
1363 delete obs;
1364 m_p->m_observers.erase(finder);
1365 // Update the info request flag
1366 bool new_observer_need_info = false;
1367 auto i = m_p->m_observers.begin();
1368 for (; i != end; ++i) {
1369 IItemGroupObserver* obs = i->second;
1370 new_observer_need_info |= obs->needInfo();
1371 }
1372 _updateNeedInfoFlag(new_observer_need_info);
1373
1374 // We invalidate the potential hash table of partial variables
1375 // if there are no references left.
1376 if (m_p->m_group_index_table.isUsed() && m_p->m_group_index_table.isUnique()) {
1377 m_p->m_group_index_table.reset();
1378 m_p->m_synchronizer.reset();
1379 }
1380}
1381
1382/*---------------------------------------------------------------------------*/
1383/*---------------------------------------------------------------------------*/
1384
1386hasInfoObserver() const
1387{
1388 return m_p->m_observer_need_info;
1389}
1390
1391/*---------------------------------------------------------------------------*/
1392/*---------------------------------------------------------------------------*/
1393
1396{
1397 delete m_p->m_compute_functor;
1398 m_p->m_compute_functor = functor;
1399}
1400
1401/*---------------------------------------------------------------------------*/
1402/*---------------------------------------------------------------------------*/
1403
1405hasComputeFunctor() const
1406{
1407 return (m_p->m_compute_functor);
1408}
1409
1410/*---------------------------------------------------------------------------*/
1411/*---------------------------------------------------------------------------*/
1412
1415{
1416 m_p->m_sub_parts_by_type._computeChildrenByTypeV1();
1417}
1418
1419/*---------------------------------------------------------------------------*/
1420/*---------------------------------------------------------------------------*/
1421
1422void ItemGroupSubPartsByType::
1423_computeChildrenByTypeV1()
1424{
1425 ItemGroup that_group(m_group_impl);
1426 ITraceMng* trace = that_group.mesh()->traceMng();
1427 trace->debug(Trace::High) << "ItemGroupImpl::_computeChildrenByType for " << m_group_internal->name();
1428
1429 Integer nb_basic_item_type = ItemTypeMng::nbBasicItemType();
1430
1431 UniqueArray<SharedArray<Int32>> items_by_type(nb_basic_item_type);
1432 for (Integer i = 0; i < nb_basic_item_type; ++i) {
1434 impl->beginTransaction();
1435 }
1436
1437 ENUMERATE_ (Item, iitem, that_group) {
1438 Item item = *iitem;
1439 Integer item_type = item.type();
1440 if (item_type < nb_basic_item_type)
1441 items_by_type[item_type].add(iitem.itemLocalId());
1442 }
1443
1444 for (Integer i = 0; i < nb_basic_item_type; ++i) {
1445 ItemGroupImpl* impl = m_children_by_type[i];
1446 impl->setItems(items_by_type[i]);
1447 impl->endTransaction();
1448 }
1449}
1450
1451/*---------------------------------------------------------------------------*/
1452/*---------------------------------------------------------------------------*/
1453
1454/*---------------------------------------------------------------------------*/
1455/*---------------------------------------------------------------------------*/
1456
1459{
1460 ARCANE_UNUSED(info);
1461 // We do not yet know how to calculate/apply transformations to computed groups.
1462 // We choose systematic invalidation.
1463 m_p->notifyInvalidateObservers();
1464}
1465
1466/*---------------------------------------------------------------------------*/
1467/*---------------------------------------------------------------------------*/
1468
1471{
1472 ARCANE_UNUSED(info);
1473 // We do not yet know how to calculate/apply transformations to computed groups.
1474 // We choose systematic invalidation.
1475 m_p->notifyInvalidateObservers();
1476}
1477
1478/*---------------------------------------------------------------------------*/
1479/*---------------------------------------------------------------------------*/
1480
1483{
1484 ARCANE_UNUSED(info);
1485 // We do not yet know how to calculate/apply transformations to computed groups.
1486 // We choose deferred systematic invalidation (evaluated during the next checkNeedUpdate).
1487 m_p->notifyInvalidateObservers();
1488}
1489
1490/*---------------------------------------------------------------------------*/
1491/*---------------------------------------------------------------------------*/
1492
1495{
1496 m_p->setNeedRecompute();
1497 m_p->notifyInvalidateObservers();
1498}
1499
1500/*---------------------------------------------------------------------------*/
1501/*---------------------------------------------------------------------------*/
1502
1504_updateNeedInfoFlag(const bool flag)
1505{
1506 if (m_p->m_observer_need_info == flag)
1507 return;
1508 m_p->m_observer_need_info = flag;
1509 // If changed, also change the parent observer so it adapts the transition info needs
1510 ItemGroupImpl* parent = m_p->m_parent;
1511 if (parent) {
1512 parent->detachObserver(this);
1513 if (m_p->m_observer_need_info) {
1515 }
1516 else {
1517 parent->attachObserver(this, newItemGroupObserverT(this, &ItemGroupImpl::_executeInvalidate));
1518 }
1519 }
1520}
1521
1522/*---------------------------------------------------------------------------*/
1523/*---------------------------------------------------------------------------*/
1524
1526_forceInvalidate(const bool self_invalidate)
1527{
1528 // (HP) TODO: Should we put a forceInvalidate observer to warn everyone?
1529 // With forceInvalidate, we must invalidate but calculate nothing
1530 if (self_invalidate) {
1531 m_p->setNeedRecompute();
1532 m_p->m_need_invalidate_on_recompute = true;
1533 }
1534
1535 for (const auto& i : m_p->m_sub_groups)
1536 i.second->_forceInvalidate(true);
1537}
1538
1539/*---------------------------------------------------------------------------*/
1540/*---------------------------------------------------------------------------*/
1541
1543destroy()
1544{
1545 // Detach the observers. This modifies m_observers so we must make a copy
1546 {
1547 std::vector<const void*> ptrs;
1548 for (const auto& i : m_p->m_observers)
1549 ptrs.push_back(i.first);
1550 for (const void* i : ptrs)
1551 detachObserver(i);
1552 }
1553
1554 // The group of all entities is special. It must never be truly destroyed.
1555 if (m_p->m_is_all_items)
1556 m_p->resetSubGroups();
1557 else {
1558 delete m_p;
1559 m_p = new ItemGroupInternal();
1560 }
1561}
1562
1563/*---------------------------------------------------------------------------*/
1564/*---------------------------------------------------------------------------*/
1565
1568{
1569 if (!m_p->m_group_index_table.isUsed()) {
1570 m_p->m_group_index_table = SharedPtrT<GroupIndexTable>(new GroupIndexTable(this));
1571 ITraceMng* trace = m_p->m_mesh->traceMng();
1572 trace->debug(Trace::High) << "** CREATION OF LOCAL ID TO INDEX TABLE OF GROUP : " << m_p->m_name;
1573 m_p->m_group_index_table->update();
1574 }
1575 return m_p->m_group_index_table;
1576}
1577
1578/*---------------------------------------------------------------------------*/
1579/*---------------------------------------------------------------------------*/
1580
1583{
1584 if (!m_p->m_synchronizer.get()) {
1585 IParallelMng* pm = m_p->m_mesh->parallelMng();
1586 ItemGroup this_group(this);
1587 m_p->m_synchronizer = ParallelMngUtils::createSynchronizerRef(pm, this_group);
1588 ITraceMng* trace = m_p->m_mesh->traceMng();
1589 trace->debug(Trace::High) << "** CREATION OF SYNCHRONIZER OF GROUP : " << m_p->m_name;
1590 m_p->m_synchronizer->compute();
1591 }
1592 return m_p->m_synchronizer.get();
1593}
1594
1595/*---------------------------------------------------------------------------*/
1596/*---------------------------------------------------------------------------*/
1597
1600{
1601 return m_p->m_synchronizer.get();
1602}
1603
1604/*---------------------------------------------------------------------------*/
1605/*---------------------------------------------------------------------------*/
1606
1608checkIsSorted() const
1609{
1610 if (null())
1611 return true;
1612
1613 // TODO: store the info in a flag and only re-run the test if
1614 // the list of entities has changed (use timestamp()).
1615 ItemInternalList items(m_p->items());
1616 Int32ConstArrayView items_lid(m_p->itemsLocalId());
1617 Integer nb_item = items_lid.size();
1618 // We are always sorted if there is only one entity or less.
1619 if (nb_item <= 1)
1620 return true;
1621 // Compare each uniqueId() with the previous one and verify that it is
1622 // greater.
1623 ItemUniqueId last_uid = items[items_lid[0]]->uniqueId();
1624 for (Integer i = 1; i < nb_item; ++i) {
1625 ItemUniqueId uid = items[items_lid[i]]->uniqueId();
1626 if (uid < last_uid)
1627 return false;
1628 last_uid = uid;
1629 }
1630 return true;
1631}
1632
1633/*---------------------------------------------------------------------------*/
1634/*---------------------------------------------------------------------------*/
1635
1637deleteMe()
1638{
1639 // If it is 'shared_null'. It must be set to nullptr so that it
1640 // can potentially be reallocated by _buildSharedNull().
1641 if (this == shared_null) {
1642 shared_null = nullptr;
1643 }
1644 delete this;
1645}
1646
1647/*---------------------------------------------------------------------------*/
1648/*---------------------------------------------------------------------------*/
1649
1652{
1653 if (!shared_null) {
1654 shared_null = new ItemGroupImplNull();
1655 shared_null->addRef();
1656 }
1657}
1658
1659/*---------------------------------------------------------------------------*/
1660/*---------------------------------------------------------------------------*/
1661
1664{
1665 // Decrements a reference to 'shared_null'. If the reference count
1666 // becomes 0, the 'shared_null' instance is destroyed.
1667 if (shared_null)
1668 shared_null->removeRef();
1669}
1670
1671/*---------------------------------------------------------------------------*/
1672/*---------------------------------------------------------------------------*/
1673
1676{
1677 return m_p->isContiguous();
1678}
1679
1680/*---------------------------------------------------------------------------*/
1681/*---------------------------------------------------------------------------*/
1682
1685{
1686 m_p->checkIsContiguous();
1687}
1688
1689/*---------------------------------------------------------------------------*/
1690/*---------------------------------------------------------------------------*/
1691
1693capacity() const
1694{
1695 Int32Array& items_lid = m_p->mutableItemsLocalId();
1696 return items_lid.capacity();
1697}
1698
1699/*---------------------------------------------------------------------------*/
1700/*---------------------------------------------------------------------------*/
1701
1704{
1705 if (hasComputeFunctor()) {
1706 // Computed group. We invalidate it and remove its elements
1707 invalidate(false);
1708 m_p->mutableItemsLocalId().clear();
1709 }
1710
1711 if (m_p->variableItemsLocalid())
1712 m_p->variableItemsLocalid()->variable()->shrinkMemory();
1713 else
1714 m_p->mutableItemsLocalId().shrink();
1715
1716 m_p->applySimdPadding();
1717}
1718
1719/*---------------------------------------------------------------------------*/
1720/*---------------------------------------------------------------------------*/
1721
1723_internalApi() const
1724{
1725 return &m_p->m_internal_api;
1726}
1727
1728/*---------------------------------------------------------------------------*/
1729/*---------------------------------------------------------------------------*/
1730
1731//TODO to be removed when V1 is no longer available
1732void ItemGroupSubPartsByType::
1733_initChildrenByTypeV1()
1734{
1735 IItemFamily* family = m_group_internal->m_item_family;
1736 ItemTypeMng* type_mng = family->mesh()->itemTypeMng();
1737 Integer nb_basic_item_type = ItemTypeMng::nbBasicItemType(); //NB_BASIC_ITEM_TYPE
1738 m_children_by_type.resize(nb_basic_item_type);
1739 for (Integer i = 0; i < nb_basic_item_type; ++i) {
1740 String child_name(type_mng->typeName(i));
1742 ItemGroupImpl* igi = m_group_impl->createSubGroup(child_name, family, functor);
1743 m_children_by_type[i] = igi;
1744 }
1745}
1746
1747/*---------------------------------------------------------------------------*/
1748/*---------------------------------------------------------------------------*/
1749
1750} // End namespace Arcane
1751
1752/*---------------------------------------------------------------------------*/
1753/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
Integer capacity() const
Capacity (number of allocated elements) of the vector.
Integer size() const
Number of elements in the vector.
bool empty() const
Capacity (number of allocated elements) of the vector.
void copy(const U &copy_array)
Copies the array copy_array into the instance.
constexpr Integer size() const noexcept
Returns the size of the array.
void fill(ConstReferenceType value)
Fills the array with the value value.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sub-view starting from element abegin and containing asize elements.
constexpr Integer size() const noexcept
Number of elements in the array.
Base class of a hash table between group items and their positions in the table.
virtual void executeFunctor()=0
Executes the associated method.
Interface of an entity family.
Definition IItemFamily.h:83
virtual ItemGroup createGroup(const String &name, Int32ConstArrayView local_ids, bool do_override=false)=0
Creates an entity group named name containing the entities local_ids.
virtual IMesh * mesh() const =0
Associated mesh.
virtual bool needInfo() const =0
Indicates whether the observer will need transition information.
Interface of an operator on entities sorted by type.
virtual ITraceMng * traceMng()=0
Associated message manager.
virtual ItemTypeMng * itemTypeMng() const =0
Associated entity type manager.
virtual const MeshPartInfo & meshPartInfo() const =0
Mesh part information.
Interface of the parallelism manager for a subdomain.
virtual TraceMessage fatal()=0
Stream for a fatal error message.
virtual TraceMessage info()=0
Stream for an information message.
virtual TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium)=0
Stream for a debug message.
Interface of a variable synchronization service.
bool isSuppressed() const
True if the entity is suppressed.
Int32 localId() const
Local number (in the subdomain) of the entity.
Functor for calculating elements of a group.
Internal API of ItemGroupImpl in Arcane.
void executeFunctor() override
Executes the associated method.
const String & name() const
Returns the group name.
Brief: Implementation of a mesh entity group.
void removeItems(Int32ConstArrayView items_local_id, bool check_if_present)
Removes the entities items_local_id from the group.
bool checkNeedUpdate()
Updates the group if necessary.
ItemGroupImpl * activeCellGroup()
AMR.
void removeAddItems(Int32ConstArrayView removed_local_id, Int32ConstArrayView added_local_id, bool check_if_present)
Removes and adds the entities removed_local_id and added_local_id from the group.
ItemGroupImplInternal * _internalApi() const
Internal Arcane API.
void setItems(Int32ConstArrayView items_local_id)
Positions the group entities at items_local_id.
void setOwn(bool v)
Sets whether the group property is local or not.
Int64 timestamp() const
Returns the group's timestamp. This time is incremented after every modification.
ItemInternalList itemsInternal() const
List of entities that the group relies on.
void endTransaction()
Ends a transaction.
void invalidate(bool force_recompute)
Invalidates the group.
ItemGroupImpl * nodeGroup()
Group of nodes of the elements of this group.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present)
Adds entities with local IDs items_local_id.
bool isAllItems() const
Indicates if the group is the group of all entities.
void _executeExtend(const Int32ConstArrayView *info)
Sub-group invalidation.
ItemGroupImpl * parent() const
Parent group (0 if none).
Int32Array & unguardedItemsLocalId(const bool self_invalidate=true)
List of local IDs of the entities in this group.
ItemGroupImpl * cellGroup()
Group of cells of the elements of this group.
ItemGroupImpl * innerFaceGroup()
Brief: Group of internal faces of the elements of this group.
eItemKind itemKind() const
Type of the group. It is the type of its elements.
ItemGroupImpl * createSubGroup(const String &suffix, IItemFamily *family, ItemGroupComputeFunctor *functor)
Creates a calculated subgroup.
void checkLocalIdsAreContiguous() const
Checks if the group entities have contiguous localIds().
virtual ~ItemGroupImpl()
Releases resources.
ItemGroupImpl * edgeGroup()
Group of edges of the elements of this group.
bool null() const
Returns true if the group is null.
void clear()
Removes the entities from the group.
ItemGroupImpl * faceGroup()
Group of faces of the elements of this group.
void destroy()
Destroys the group. After this call, the group becomes a null group.
void setLocalToSubDomain(bool v)
Sets the boolean indicating if the group is local to the subdomain.
void setIsAllItems()
Indicates to this group that it is the group of all entities in the family.
void _executeReduce(const Int32ConstArrayView *info)
Sub-group invalidation.
void removeSuppressedItems()
Removes entities from the group whose isSuppressed() flag is true.
const String & fullName() const
Full group name (with mesh + family).
ItemGroupImpl * ownGroup()
Group of entities owned by the entities of this group.
void _updateNeedInfoFlag(const bool flag)
Forced update of the restructuring information flag.
IMesh * mesh() const
Mesh to which the group belongs (0 for the null group).
bool checkIsSorted() const
Checks and returns whether the group is sorted by increasing uniqueId().
void checkValid()
Checks that the group is valid.
IVariableSynchronizer * synchronizer()
Group synchronizer.
Integer size() const
Number of entities in the group.
Int32ConstArrayView itemsLocalId() const
List of local IDs of the entities in this group.
bool needSynchronization() const
Indicates if the group structurally needs parallel synchronization.
ItemGroupImpl * ownActiveCellGroup()
Brief: Group of own active cells of this group.
SharedPtrT< GroupIndexTable > localIdToIndex()
Table of local IDs to a position for all entities in the group.
ItemInfoListView itemInfoListView() const
List of entities that the group relies on.
void attachObserver(const void *ref, IItemGroupObserver *obs)
Attaches an observer.
ItemGroupImpl * outerActiveFaceGroup()
Brief: Group of active external faces of the elements of this group.
void detachObserver(const void *ref)
Detaches an observer.
IItemFamily * itemFamily() const
Family to which the group belongs (or 0 if none).
void _executeInvalidate()
Sub-group invalidation.
virtual void deleteMe()
Notification from SharedReference indicating that the instance must be destroyed.
void _executeCompact(const Int32ConstArrayView *info)
Sub-group invalidation.
bool isLocalToSubDomain() const
AMR OFF.
ItemGroupImpl * ghostGroup()
Items in the group not owned by the subdomain.
ItemGroupImpl * ownLevelCellGroup(const Integer &level)
Brief: Group of own active cells of this group.
Int64 capacity() const
Number of allocated elements.
bool isContiguousLocalIds() const
Indicates if the group entities have contiguous localIds().
static void _buildSharedNull()
Internal.
ItemGroupImpl * innerActiveFaceGroup()
Brief: Group of active internal faces of the elements of this group.
void applyOperation(IItemOperationByBasicType *operation)
Applies the operation operation to the group entities.
void beginTransaction()
Starts a transaction.
ItemGroupImpl * levelCellGroup(const Integer &level)
Brief: Group of active cells of this group.
bool hasComputeFunctor() const
Indicates if the group is calculated.
bool hasSynchronizer()
Indicates if this group has a synchronizer.
bool hasInfoObserver() const
Indicates if the content of this group is observed.
void setComputeFunctor(IFunctor *functor)
Defines a group calculation function.
ItemGroupImpl * ownActiveFaceGroup()
Brief: Group of active external faces of the elements of this group.
bool isOwn() const
Returns whether the group contains only elements specific to the subdomain.
ItemGroupImpl()
Constructs a null group.
ItemGroup parentGroup()
Parent group.
bool empty() const
True if the group is empty.
void _forceInvalidate(const bool self_invalidate)
Recursive forced invalidation.
ItemGroupInternal * m_p
Group implementation.
static void _destroySharedNull()
Internal.
ItemGroupImpl * activeFaceGroup()
Brief: Group of domain-specific active faces.
const String & name() const
Group name.
void _computeChildrenByType()
Method for calculating sub-groups by type.
ItemGroupImpl * outerFaceGroup()
Brief: Group of external faces of the elements of this group.
void shrinkMemory()
Limits the maximum memory used by the group.
ItemGroupImpl * findSubGroup(const String &suffix)
Accesses a calculated subgroup.
void changeIds(Int32ConstArrayView old_to_new_ids)
Changes the indices of the group entities.
Implementation of the ItemGroupImpl class.
ItemGroupImpl * m_interface_group
Items on the boundary of two subdomains.
bool m_need_invalidate_on_recompute
True if invalidate observers must be activated upon recalculation.
bool m_need_recompute
True if the group needs to be recalculated.
void checkUpdateSimdPadding()
Fills the last elements of the group to have a complete SIMD vector.
IItemFamily * m_item_family
Associated family.
IFunctor * m_compute_functor
Group computation function.
CheckNeedUpdateMutex m_check_need_update_mutex
Mutex to protect updates.
ItemGroupImpl * m_group_impl
To be deleted when version V1 is removed.
UniqueArray< UniqueArray< Int32 > > m_children_by_type_ids
List of localIds by entity type.
Int64 m_children_by_type_ids_computed_timestamp
Timestamp indicating when the list of child ids was calculated.
UniqueArray< ItemGroupImpl * > m_children_by_type
List of children of this group by entity type.
ItemTypeId m_unique_children_type
Indicates the type of the entities in the group.
Mesh entity group.
Definition ItemGroup.h:51
ItemGroupImpl * internal() const
Returns the group implementation.
Definition ItemGroup.h:125
View of a list to obtain information about entities.
Internal structure of a mesh entity.
Mesh entity type manager.
Definition ItemTypeMng.h:66
static Integer nbBasicItemType()
number of available types
String typeName(Integer id) const
Name of the type corresponding to the number id.
Unique identifier of an entity.
View of an array of elements of type T.
Definition Span.h:805
1D data vector with value semantics (STL style).
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
ItemGroupT< Face > FaceGroup
Group of faces.
Definition ItemTypes.h:179
ItemGroupT< Edge > EdgeGroup
Group of edges.
Definition ItemTypes.h:174
ItemGroupT< Node > NodeGroup
Group of nodes.
Definition ItemTypes.h:168
Int32 checkResizeArrayWithCapacity(Array< DataType > &array, Int64 new_size, bool force_resize)
Resizes an array by adding a memory reserve.
void copy(MutableMemoryView destination, eMemoryResource destination_mem, ConstMemoryView source, eMemoryResource source_mem, const RunQueue *queue=nullptr)
Copies source to destination using the queue queue.
Ref< IVariableSynchronizer > createSynchronizerRef(IParallelMng *pm, IItemFamily *family)
Returns an interface to synchronize variables on the group of the family family.
@ Medium
Medium level (default).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482
ConstArrayView< ItemInternal * > ItemInternalList
Type of the internal list of entities.
Definition ItemTypes.h:466
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
eItemKind
Mesh entity type.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Face
Face mesh entity.
@ IK_Edge
Edge mesh entity.
IItemGroupObserver * newItemGroupObserverT(T *object, typename IItemGroupObserver::FuncTraits< T >::FuncPtr funcptr)
Utility for simplified creation of ItemGroupObserverT.
Array< Int32 > Int32Array
Dynamic one-dimensional array of 32-bit integers.
Definition UtilsTypes.h:127
std::int32_t Int32
Signed integer type of 32 bits.