Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
IncrementalItemConnectivity.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/* IncrementalItemConnectivity.cc (C) 2000-2024 */
9/* */
10/* Incremental connectivity of entities. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/IncrementalItemConnectivity.h"
15
16#include "arcane/utils/StringBuilder.h"
17#include "arcane/utils/ArgumentException.h"
18#include "arcane/utils/PlatformUtils.h"
19
20#include "arcane/core/IMesh.h"
21#include "arcane/core/IItemFamily.h"
22#include "arcane/core/ConnectivityItemVector.h"
24#include "arcane/core/ObserverPool.h"
25#include "arcane/core/Properties.h"
26#include "arcane/core/IndexedItemConnectivityView.h"
27#include "arcane/core/internal/IDataInternal.h"
28#include "arcane/core/internal/IItemFamilyInternal.h"
29#include "arcane/core/internal/IIncrementalItemConnectivityInternal.h"
30
31#include "arcane/mesh/IndexedItemConnectivityAccessor.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane::mesh
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42IndexedItemConnectivityAccessor::
43IndexedItemConnectivityAccessor(IndexedItemConnectivityViewBase view, IItemFamily* target_item_family)
44: IndexedItemConnectivityViewBase(view)
45, m_item_shared_info(target_item_family->_internalApi()->commonItemSharedInfo())
46{}
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51IndexedItemConnectivityAccessor::
52IndexedItemConnectivityAccessor(IIncrementalItemConnectivity* connectivity)
53: m_item_shared_info(connectivity->targetFamily()->_internalApi()->commonItemSharedInfo())
54{
55 auto* ptr = dynamic_cast<mesh::IncrementalItemConnectivityBase*>(connectivity);
56 if (ptr)
57 IndexedItemConnectivityViewBase::set(ptr->connectivityView());
58}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63AbstractIncrementalItemConnectivity::
64AbstractIncrementalItemConnectivity(IItemFamily* source_family,
65 IItemFamily* target_family,
66 const String& connectivity_name)
67: TraceAccessor(source_family->traceMng())
68, m_source_family(source_family)
69, m_target_family(target_family)
70, m_name(connectivity_name)
71{
72 m_families.add(m_source_family);
73 m_families.add(m_target_family);
74
75 //TODO: these references must be removed upon destruction.
76 source_family->_internalApi()->addSourceConnectivity(this);
77 target_family->_internalApi()->addTargetConnectivity(this);
78}
79
80/*---------------------------------------------------------------------------*/
81/*---------------------------------------------------------------------------*/
82
83Ref<IIncrementalItemSourceConnectivity> AbstractIncrementalItemConnectivity::
84toSourceReference()
85{
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
91
92Ref<IIncrementalItemTargetConnectivity> AbstractIncrementalItemConnectivity::
93toTargetReference()
94{
96}
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
104class IncrementalItemConnectivityContainer
105{
106 public:
107
108 IncrementalItemConnectivityContainer(IMesh* mesh, const String& var_name)
109 : m_var_name(var_name)
110 , m_connectivity_nb_item_variable(VariableBuildInfo(mesh, var_name + "Nb", IVariable::PPrivate))
111 , m_connectivity_index_variable(VariableBuildInfo(mesh, var_name + "Index", IVariable::PPrivate))
112 , m_connectivity_list_variable(VariableBuildInfo(mesh, var_name + "List", IVariable::PPrivate))
113 , m_connectivity_nb_item_array(m_connectivity_nb_item_variable._internalTrueData()->_internalDeprecatedValue())
114 , m_connectivity_index_array(m_connectivity_index_variable._internalTrueData()->_internalDeprecatedValue())
115 , m_connectivity_list_array(m_connectivity_list_variable._internalTrueData()->_internalDeprecatedValue())
116 {
117 // Adds a tag to indicate that these variables are associated with connectivity.
118 // For now, this is only used for display statistics.
119
120 String tag_name = "ArcaneConnectivity";
121 m_connectivity_nb_item_variable.addTag(tag_name, "1");
122 m_connectivity_index_variable.addTag(tag_name, "1");
123 m_connectivity_list_variable.addTag(tag_name, "1");
124 }
125
126 String m_var_name;
127
128 VariableArrayInt32 m_connectivity_nb_item_variable;
129 VariableArrayInt32 m_connectivity_index_variable;
130 VariableArrayInt32 m_connectivity_list_variable;
131
132 VariableArrayInt32::ContainerType& m_connectivity_nb_item_array;
133 VariableArrayInt32::ContainerType& m_connectivity_index_array;
134 VariableArrayInt32::ContainerType& m_connectivity_list_array;
135
136 ObserverPool m_observers;
137
146
147 public:
148
149 Integer size() const { return m_connectivity_nb_item_array.size(); }
150
151 bool isAllocated() const { return size() > 0; }
152
153 void _checkResize(Int32 lid)
154 {
155 //TODO: reuse the code from ItemFamily::_setUniqueId().
156 Integer size = m_connectivity_nb_item_array.size();
157 Integer wanted_size = lid + 1;
158 if (wanted_size < size)
159 return;
160 Integer capacity = m_connectivity_nb_item_array.capacity();
161 if (wanted_size < capacity) {
162 // No need to increase capacity.
163 }
164 else {
165 Integer reserve_size = 1000;
166 while (lid > reserve_size) {
167 reserve_size *= 2;
168 }
169 m_connectivity_nb_item_array.reserve(reserve_size);
170 m_connectivity_index_array.reserve(reserve_size);
171 }
172 m_connectivity_nb_item_array.resize(wanted_size);
173 m_connectivity_index_array.resize(wanted_size);
174 }
175
176 void reserveForItems(Int32 capacity)
177 {
178 m_connectivity_nb_item_array.reserve(capacity);
179 m_connectivity_index_array.reserve(capacity);
180 }
181
182 public:
183};
184
185/*---------------------------------------------------------------------------*/
186/*---------------------------------------------------------------------------*/
187
190{
191 public:
192
193 explicit InternalApi(IncrementalItemConnectivityBase* v)
194 : m_internal_api(v)
195 {}
196
197 public:
198
199 void shrinkMemory() override { return m_internal_api->_shrinkMemory(); }
201 {
202 m_internal_api->_addMemoryInfos(mem_info);
203 }
204
205 private:
206
207 IncrementalItemConnectivityBase* m_internal_api = nullptr;
208};
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
213IncrementalItemConnectivityBase::
214IncrementalItemConnectivityBase(IItemFamily* source_family, IItemFamily* target_family,
215 const String& aname)
216: AbstractIncrementalItemConnectivity(source_family, target_family, aname)
217, m_internal_api(std::make_unique<InternalApi>(this))
218{
219 StringBuilder var_name("Connectivity");
220 var_name += aname;
221 var_name += source_family->name();
222 var_name += target_family->name();
223
224 IMesh* mesh = source_family->mesh();
225 m_p = new IncrementalItemConnectivityContainer(mesh, var_name);
226
227 using ThatClass = IncrementalItemConnectivityBase;
228 // Get read events to indicate that the views must be updated.
229 m_p->m_observers.addObserver(this, &ThatClass::_notifyConnectivityNbItemChangedFromObservable,
230 m_p->m_connectivity_nb_item_variable.variable()->readObservable());
231
232 m_p->m_observers.addObserver(this, &ThatClass::_notifyConnectivityIndexChanged,
233 m_p->m_connectivity_index_variable.variable()->readObservable());
234
235 m_p->m_observers.addObserver(this, &ThatClass::_notifyConnectivityListChanged,
236 m_p->m_connectivity_list_variable.variable()->readObservable());
237
238 // Update the views from the associated arrays.
239 // This must be done whenever the size of an array changes because then
240 // the array might be reallocated and thus the associated view might become invalid.
241 _notifyConnectivityListChanged();
242 _notifyConnectivityIndexChanged();
244}
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
249IncrementalItemConnectivityBase::
250~IncrementalItemConnectivityBase()
251{
252 delete m_p;
253}
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
259reserveMemoryForNbSourceItems(Int32 n, bool pre_alloc_connectivity)
260{
261 if (n <= 0)
262 return;
263
264 m_p->reserveForItems(n);
265 _notifyConnectivityIndexChanged();
266 _notifyConnectivityNbItemChanged();
267
268 if (pre_alloc_connectivity) {
269 Int32 pre_alloc_size = preAllocatedSize();
270 if (pre_alloc_size > 0) {
271 m_p->m_connectivity_list_array.reserve(n * pre_alloc_size);
272 _notifyConnectivityListChanged();
273 }
274 }
275}
276
277/*---------------------------------------------------------------------------*/
278/*---------------------------------------------------------------------------*/
279
280void IncrementalItemConnectivityBase::
281_notifyConnectivityListChanged()
282{
283 m_connectivity_list = m_p->m_connectivity_list_array.view();
284 if (m_item_connectivity_list)
285 m_item_connectivity_list->_setConnectivityList(m_item_connectivity_index, m_connectivity_list);
286}
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
291void IncrementalItemConnectivityBase::
292_notifyConnectivityIndexChanged()
293{
294 m_connectivity_index = m_p->m_connectivity_index_array.view();
295 if (m_item_connectivity_list)
296 m_item_connectivity_list->_setConnectivityIndex(m_item_connectivity_index, m_connectivity_index);
297}
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
301
302void IncrementalItemConnectivityBase::
303_notifyConnectivityNbItemChanged()
304{
305 m_connectivity_nb_item = m_p->m_connectivity_nb_item_array.view();
306 if (m_item_connectivity_list)
307 m_item_connectivity_list->_setConnectivityNbItem(m_item_connectivity_index, m_connectivity_nb_item);
308}
309
310/*---------------------------------------------------------------------------*/
311/*---------------------------------------------------------------------------*/
312
313void IncrementalItemConnectivityBase::
314_setMaxNbConnectedItemsInConnectivityList()
315{
316 if (m_item_connectivity_list)
317 m_item_connectivity_list->_setMaxNbConnectedItem(m_item_connectivity_index, m_p->m_max_nb_item);
318}
319
320/*---------------------------------------------------------------------------*/
321/*---------------------------------------------------------------------------*/
328{
329 _notifyConnectivityNbItemChanged();
330 _computeMaxNbConnectedItem();
331}
332
333/*---------------------------------------------------------------------------*/
334/*---------------------------------------------------------------------------*/
335
336void IncrementalItemConnectivityBase::
337_setNewMaxNbConnectedItems(Int32 new_max)
338{
339 if (new_max > m_p->m_max_nb_item) {
340 m_p->m_max_nb_item = new_max;
341 _setMaxNbConnectedItemsInConnectivityList();
342 }
343}
344
345/*---------------------------------------------------------------------------*/
346/*---------------------------------------------------------------------------*/
347
348void IncrementalItemConnectivityBase::
349_computeMaxNbConnectedItem()
350{
351 // Force reset to ensure it is updated
352 m_p->m_max_nb_item = -1;
353 Int32 max_nb_item = 0;
354 for (Int32 x : m_connectivity_nb_item)
355 if (x > max_nb_item)
356 max_nb_item = x;
357 _setNewMaxNbConnectedItems(max_nb_item);
358}
359
360/*---------------------------------------------------------------------------*/
361/*---------------------------------------------------------------------------*/
362
364maxNbConnectedItem() const
365{
366 return m_p->m_max_nb_item;
367}
368
369/*---------------------------------------------------------------------------*/
370/*---------------------------------------------------------------------------*/
380{
381 info(4) << "setItemConnectivityList name=" << name() << " ilist=" << ilist << " index=" << index;
382 m_item_connectivity_list = ilist;
383 m_item_connectivity_index = index;
384 _notifyConnectivityListChanged();
385 _notifyConnectivityIndexChanged();
386 _notifyConnectivityNbItemChanged();
387 _setMaxNbConnectedItemsInConnectivityList();
388}
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
395{
396 if (m_p->isAllocated()) {
397 m_p->m_connectivity_nb_item_variable.variable()->compact(new_to_old_ids);
398 m_p->m_connectivity_index_variable.variable()->compact(new_to_old_ids);
399 _notifyConnectivityNbItemChanged();
400 _notifyConnectivityIndexChanged();
401 }
402}
403
404/*---------------------------------------------------------------------------*/
405/*---------------------------------------------------------------------------*/
406
409{
410 Int32ArrayView ids = m_connectivity_list;
411 const Integer n = ids.size();
412 for (Integer i = 0; i < n; ++i)
413 if (ids[i] != NULL_ITEM_LOCAL_ID)
414 ids[i] = old_to_new_ids[ids[i]];
415}
416
417/*---------------------------------------------------------------------------*/
418/*---------------------------------------------------------------------------*/
419
421_connectedItems(ItemLocalId item, ConnectivityItemVector& con_items) const
422{
423 return con_items.resizeAndCopy(_connectedItemsLocalId(item));
424}
425
426/*---------------------------------------------------------------------------*/
427/*---------------------------------------------------------------------------*/
428
429ItemConnectivityContainerView IncrementalItemConnectivityBase::
430connectivityContainerView() const
431{
432 return { m_connectivity_list, m_connectivity_index, m_connectivity_nb_item };
433}
434
435/*---------------------------------------------------------------------------*/
436/*---------------------------------------------------------------------------*/
437
438IndexedItemConnectivityViewBase IncrementalItemConnectivityBase::
439connectivityView() const
440{
441 return { connectivityContainerView(), _sourceFamily()->itemKind(), _targetFamily()->itemKind() };
442}
443
444/*---------------------------------------------------------------------------*/
445/*---------------------------------------------------------------------------*/
446
447IndexedItemConnectivityAccessor IncrementalItemConnectivityBase::
448connectivityAccessor() const
449{
450 return IndexedItemConnectivityAccessor(connectivityView(), _targetFamily());
451}
452
453/*---------------------------------------------------------------------------*/
454/*---------------------------------------------------------------------------*/
455
461
462/*---------------------------------------------------------------------------*/
463/*---------------------------------------------------------------------------*/
464
465void IncrementalItemConnectivityBase::
466dumpInfos()
467{
468 info() << "Infos index=" << m_connectivity_index;
469 info() << "Infos nb_item=" << m_connectivity_nb_item;
470 info() << "Infos list=" << m_connectivity_list;
471}
472
473/*---------------------------------------------------------------------------*/
474/*---------------------------------------------------------------------------*/
475
476/*---------------------------------------------------------------------------*/
477/*---------------------------------------------------------------------------*/
478
479IncrementalItemConnectivity::
480IncrementalItemConnectivity(IItemFamily* source_family, IItemFamily* target_family,
481 const String& aname)
482: IncrementalItemConnectivityBase(source_family, target_family, aname)
483, m_nb_add(0)
484, m_nb_remove(0)
485, m_nb_memcopy(0)
486, m_pre_allocated_size(0)
487{
488 m_pre_allocated_size = _sourceFamily()->properties()->getIntegerWithDefault(name() + "PreallocSize", 0);
489 info(4) << "PreallocSize1 var=" << m_p->m_var_name << " v=" << m_pre_allocated_size;
490
491 // Checks if the null entity needs to be added at the beginning of the list.
492 _checkAddNullItem();
493}
494
495/*---------------------------------------------------------------------------*/
496/*---------------------------------------------------------------------------*/
497
498IncrementalItemConnectivity::
499~IncrementalItemConnectivity()
500{
501 info(4) << " connectivity name=" << name()
502 << " prealloc_size=" << m_pre_allocated_size
503 << " nb_add=" << m_nb_add
504 << " nb_remove=" << m_nb_remove
505 << " nb_memcopy=" << m_nb_memcopy;
506}
507
508/*---------------------------------------------------------------------------*/
509/*---------------------------------------------------------------------------*/
510
511inline Integer IncrementalItemConnectivity::
512_increaseConnectivityList(Int32 new_lid)
513{
514 Integer pos_in_list = m_connectivity_list.size();
515 m_p->m_connectivity_list_array.add(new_lid);
516 _notifyConnectivityListChanged();
517 return pos_in_list;
518}
519
520/*---------------------------------------------------------------------------*/
521/*---------------------------------------------------------------------------*/
522
523inline Integer IncrementalItemConnectivity::
524_increaseConnectivityList(Int32 new_lid, Integer nb_value)
525{
526 Integer pos_in_list = m_connectivity_list.size();
527 m_p->m_connectivity_list_array.addRange(new_lid, nb_value);
528 _notifyConnectivityListChanged();
529 return pos_in_list;
530}
531
532/*---------------------------------------------------------------------------*/
533/*---------------------------------------------------------------------------*/
534
535void IncrementalItemConnectivity::
536_resetConnectivityList()
537{
538 m_p->m_connectivity_list_array.clear();
539 _notifyConnectivityListChanged();
540 _checkAddNullItem();
541}
542
543/*---------------------------------------------------------------------------*/
544/*---------------------------------------------------------------------------*/
545
546void IncrementalItemConnectivity::
547_increaseIndexList(Int32 lid, Integer size, Int32 target_lid)
548{
549 Integer added_range = (m_pre_allocated_size > 0) ? m_pre_allocated_size : 1;
550 ++m_nb_memcopy;
551 Integer pos_in_index = m_connectivity_index[lid];
552 Integer new_pos_in_list = _increaseConnectivityList(NULL_ITEM_LOCAL_ID, size + added_range);
553 ArrayView<Int32> current_list(size, &(m_connectivity_list[pos_in_index]));
554 ArrayView<Int32> new_list(size + 1, &(m_connectivity_list[new_pos_in_list]));
555 new_list.copy(current_list);
556 // Adds the new entity to the end of the connectivity list
557 // TODO: look into sorting by increasing uid().
558 new_list[size] = target_lid;
559 m_connectivity_index[lid] = new_pos_in_list;
560}
561
562/*---------------------------------------------------------------------------*/
563/*---------------------------------------------------------------------------*/
564
566addConnectedItem(ItemLocalId source_item, ItemLocalId target_item)
567{
568 ++m_nb_add;
569 const Int32 lid = source_item.localId();
570 const Int32 target_lid = target_item.localId();
571 Integer size = m_connectivity_nb_item[lid];
572 // Adds a connected item.
573 // For now, the functionality is basic.
574 // The items are always added to the end of m_p->m_connectivity_list.
575 // If there are none, it is enough to add to the end.
576 // If there are already some, it is necessary to allocate at the end of
577 // m_p->m_connectivity_list enough \a size+1 elements and
578 // we copy the previous connectivity to the new location.
579 // Naturally, over time the list will always grow
580 // because the gaps are not reused.
581 if (m_pre_allocated_size != 0) {
582 // In case of preallocation, we allocate in blocks of size 'm_pre_allocated_size'.
583 // We must therefore reallocate if the size is a multiple of m_pre_allocated_size
584 if (size == 0) {
585 Integer new_pos_in_list = _increaseConnectivityList(NULL_ITEM_LOCAL_ID, m_pre_allocated_size);
586 m_connectivity_index[lid] = new_pos_in_list;
587 m_connectivity_list[new_pos_in_list] = target_lid;
588 }
589 else {
590 if (size < m_pre_allocated_size || (size % m_pre_allocated_size) != 0) {
591 Integer index = m_connectivity_index[lid];
592 m_connectivity_list[index + size] = target_lid;
593 }
594 else {
595 _increaseIndexList(lid, size, target_lid);
596 }
597 }
598 }
599 else {
600 if (size == 0) {
601 Integer new_pos_in_list = _increaseConnectivityList(target_lid);
602 m_connectivity_index[lid] = new_pos_in_list;
603 }
604 else {
605 _increaseIndexList(lid, size, target_lid);
606 }
607 }
608 ++(m_connectivity_nb_item[lid]);
609 _setNewMaxNbConnectedItems(m_connectivity_nb_item[lid]);
610}
611
612/*---------------------------------------------------------------------------*/
613/*---------------------------------------------------------------------------*/
614
615Integer IncrementalItemConnectivity::
616_computeAllocSize(Integer nb_item)
617{
618 if (m_pre_allocated_size != 0) {
619 // Allocates a multiple of \a m_pre_allocated_size
620 Integer alloc_size = nb_item / m_pre_allocated_size;
621 if (alloc_size == 0)
622 return m_pre_allocated_size;
623 if ((nb_item % m_pre_allocated_size) == 0)
624 return nb_item;
625 return m_pre_allocated_size * (alloc_size + 1);
626 }
627 return nb_item;
628}
629
630/*---------------------------------------------------------------------------*/
631/*---------------------------------------------------------------------------*/
632
633void IncrementalItemConnectivity::
634addConnectedItems(ItemLocalId source_item, Integer nb_item)
635{
636 const Int32 lid = source_item.localId();
637 Integer size = m_connectivity_nb_item[lid];
638 if (size != 0)
639 ARCANE_FATAL("source_item already have connected items");
640 Integer alloc_size = _computeAllocSize(nb_item);
641 Integer new_pos_in_list = _increaseConnectivityList(NULL_ITEM_LOCAL_ID, alloc_size);
642 m_connectivity_index[lid] = new_pos_in_list;
643 m_connectivity_nb_item[lid] += nb_item;
644 _setNewMaxNbConnectedItems(m_connectivity_nb_item[lid]);
645}
646
647/*---------------------------------------------------------------------------*/
648/*---------------------------------------------------------------------------*/
649
651setConnectedItems(ItemLocalId source_item, Int32ConstArrayView target_local_ids)
652{
653 removeConnectedItems(source_item);
654 addConnectedItems(source_item, target_local_ids.size());
655 replaceConnectedItems(source_item, target_local_ids);
656}
657
658/*---------------------------------------------------------------------------*/
659/*---------------------------------------------------------------------------*/
660
663{
664 Int32 lid = source_item.localId();
665 m_connectivity_nb_item[lid] = 0;
666}
667
668/*---------------------------------------------------------------------------*/
669/*---------------------------------------------------------------------------*/
670
672removeConnectedItem(ItemLocalId source_item, ItemLocalId target_item)
673{
674 ++m_nb_remove;
675 Int32 lid = source_item.localId();
676 Int32 target_lid = target_item.localId();
677 Integer size = m_connectivity_nb_item[lid];
678 Int32* items = &(m_connectivity_list[m_connectivity_index[lid]]);
679 mesh_utils::removeItemAndKeepOrder(Int32ArrayView(size, items), target_lid);
680 --(m_connectivity_nb_item[lid]);
681}
682
683/*---------------------------------------------------------------------------*/
684/*---------------------------------------------------------------------------*/
685
687replaceConnectedItem(ItemLocalId source_item, Integer index, ItemLocalId target_item)
688{
689 Int32 lid = source_item.localId();
690 Int32 target_lid = target_item.localId();
691 ARCANE_CHECK_AT(index, m_connectivity_nb_item[lid]);
692 m_connectivity_list[m_connectivity_index[lid] + index] = target_lid;
693}
694
695/*---------------------------------------------------------------------------*/
696/*---------------------------------------------------------------------------*/
697
699replaceConnectedItems(ItemLocalId source_item, Int32ConstArrayView target_local_ids)
700{
701 Int32 lid = source_item.localId();
702 Int32 n = target_local_ids.size();
703 if (n > 0) {
704 ARCANE_CHECK_AT(n - 1, m_connectivity_nb_item[lid]);
705 const Int32 pos = m_connectivity_index[lid];
706 for (Integer i = 0; i < n; ++i)
707 m_connectivity_list[pos + i] = target_local_ids[i];
708 }
709}
710
711/*---------------------------------------------------------------------------*/
712/*---------------------------------------------------------------------------*/
713
715hasConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id) const
716{
717 bool has_connection = false;
718 auto connected_items = _connectedItemsLocalId(source_item);
719 if (std::find(connected_items.begin(), connected_items.end(), target_local_id) != connected_items.end())
720 has_connection = true;
721 return has_connection;
722}
723
724/*---------------------------------------------------------------------------*/
725/*---------------------------------------------------------------------------*/
726
729{
730 Int32 lid = item.localId();
731 m_p->_checkResize(lid);
732 _notifyConnectivityIndexChanged();
733 _notifyConnectivityNbItemChanged();
734
735 m_connectivity_nb_item[lid] = 0;
736 m_connectivity_index[lid] = 0;
737}
738
739/*---------------------------------------------------------------------------*/
740/*---------------------------------------------------------------------------*/
741
742void IncrementalItemConnectivity::
743_internalNotifySourceItemsAdded(ConstArrayView<Int32> local_ids)
744{
745 // Pre-calculates the maximum of the local_ids for resizing.
746 Int32 nb_item = local_ids.size();
747 if (nb_item <= 0)
748 return;
749 Int32 max_lid = local_ids[0];
750 for (Int32 lid : local_ids)
751 max_lid = math::max(max_lid, lid);
752
753 m_p->_checkResize(max_lid);
754 _notifyConnectivityIndexChanged();
755 _notifyConnectivityNbItemChanged();
756
757 for (Int32 lid : local_ids) {
758 m_connectivity_nb_item[lid] = 0;
759 m_connectivity_index[lid] = 0;
760 }
761}
762
763/*---------------------------------------------------------------------------*/
764/*---------------------------------------------------------------------------*/
765
768{
769 m_pre_allocated_size = _sourceFamily()->properties()->getIntegerWithDefault(name() + "PreallocSize", 0);
770 info(4) << "PreallocSize2 var=" << m_p->m_var_name << " v=" << m_pre_allocated_size;
771
772 // There is practically nothing to do for the variables because the views are correctly updated via the observables on the variables.
773}
774
775/*---------------------------------------------------------------------------*/
776/*---------------------------------------------------------------------------*/
777
779setPreAllocatedSize(Integer prealloc_size)
780{
781 if (m_pre_allocated_size < 0)
782 throw ArgumentException(A_FUNCINFO,
783 String::format("Invalid prealloc_size v={0}",
784 prealloc_size));
785
786 // Does nothing if we have already allocated entities, otherwise it would make
787 // the allocations inconsistent.
788 // NOTE: we could allow it, but that would require rebuilding
789 // the connectivity indices. A call to compactConnectivityList()
790 // would suffice.
791 if (m_connectivity_nb_item.size() != 0)
792 return;
793
794 m_pre_allocated_size = prealloc_size;
795 _sourceFamily()->properties()->setInteger(name() + "PreallocSize", prealloc_size);
796
797 // Even if there are no entities, m_p->m_connectivity_list_array is not
798 // empty because we called _checkkAddNulItem() in the constructor. We must
799 // now reallocate it with the new pre-allocation value.
800 _resetConnectivityList();
801}
802
803/*---------------------------------------------------------------------------*/
804/*---------------------------------------------------------------------------*/
805
807dumpStats(std::ostream& out) const
808{
809 Int64 mem1 = m_p->m_connectivity_list_array.capacity();
810 Int64 mem2 = m_p->m_connectivity_index_array.capacity();
811 Int64 mem3 = m_p->m_connectivity_nb_item_array.capacity();
812 Int64 allocated_size = mem1 + mem2 + mem3;
813 allocated_size *= sizeof(Int32);
814
815 out << " connectiviy name=" << name()
816 << " prealloc_size=" << m_pre_allocated_size
817 << " nb_add=" << m_nb_add
818 << " nb_remove=" << m_nb_remove
819 << " nb_memcopy=" << m_nb_memcopy
820 << " list_size=" << m_connectivity_list.size()
821 << " list_capacity=" << mem1
822 << " index_size=" << m_connectivity_index.size()
823 << " index_capacity=" << mem2
824 << " nb_item_size=" << m_connectivity_nb_item.size()
825 << " nb_item_capacity=" << mem3
826 << " allocated_size=" << allocated_size;
827}
828
829/*---------------------------------------------------------------------------*/
830/*---------------------------------------------------------------------------*/
831
832void IncrementalItemConnectivityBase::
833_shrinkMemory()
834{
835 m_p->m_connectivity_list_array.shrink();
836 m_p->m_connectivity_index_array.shrink();
837 m_p->m_connectivity_nb_item_array.shrink();
838 _notifyConnectivityIndexChanged();
839 _notifyConnectivityNbItemChanged();
840 _notifyConnectivityListChanged();
841}
842
843/*---------------------------------------------------------------------------*/
844/*---------------------------------------------------------------------------*/
845
846void IncrementalItemConnectivityBase::
847_addMemoryInfos(ItemConnectivityMemoryInfo& mem_info)
848{
849 Int64 s1 = m_p->m_connectivity_list_array.size();
850 Int64 s2 = m_p->m_connectivity_index_array.size();
851 Int64 s3 = m_p->m_connectivity_nb_item_array.size();
852 mem_info.m_total_size += s1 + s2 + s3;
853
854 Int64 c1 = m_p->m_connectivity_list_array.capacity();
855 Int64 c2 = m_p->m_connectivity_index_array.capacity();
856 Int64 c3 = m_p->m_connectivity_nb_item_array.capacity();
857 mem_info.m_total_capacity += c1 + c2 + c3;
858}
859
860/*---------------------------------------------------------------------------*/
861/*---------------------------------------------------------------------------*/
862
863void IncrementalItemConnectivity::
864_checkAddNullItem()
865{
866 // If the connectivity list is empty, create an element
867 // (or several if m_pre_allocated_size>0) to contain the null entity.
868 // This allows retrieving the list of connectivities for an entity even if
869 // it is empty.
870 if (m_connectivity_list.size() == 0) {
871 if (m_pre_allocated_size > 0) {
872 _increaseConnectivityList(NULL_ITEM_LOCAL_ID, m_pre_allocated_size);
873 }
874 else {
875 _increaseConnectivityList(NULL_ITEM_LOCAL_ID);
876 }
877 }
878}
879
880/*---------------------------------------------------------------------------*/
881/*---------------------------------------------------------------------------*/
894{
895 info(4) << "Begin Compacting IncrementalItemConnectivity name=" << name()
896 << " new_size=" << m_connectivity_list.size()
897 << " prealloc_size=" << m_pre_allocated_size;
898 // TODO: try to find a way to only compact if
899 // it is necessary. One way would be to count the number of calls to
900 // _increaseIndexList() since the last compaction.
901 UniqueArray<Int32> old_connectivity_list(m_connectivity_list);
902 Integer old_size = old_connectivity_list.size();
903 Integer nb_item = m_connectivity_nb_item.size();
904 m_p->m_connectivity_list_array.clear();
905 _notifyConnectivityListChanged();
906 _checkAddNullItem();
907 Integer new_pos_in_list = m_p->m_connectivity_list_array.size();
908 Int32 pre_allocated_size = m_pre_allocated_size;
909 for (Integer i = 0; i < nb_item; ++i) {
910 Int32 lid = i;
911 Int32 nb = m_connectivity_nb_item[lid];
912 if (nb == 0) {
913 m_connectivity_index[lid] = 0;
914 continue;
915 }
916 Int32 index = m_connectivity_index[lid];
917 Int32ConstArrayView con_list(nb, old_connectivity_list.data() + index);
918 Integer alloc_size = _computeAllocSize(nb);
919 m_connectivity_index[lid] = new_pos_in_list;
920 new_pos_in_list += alloc_size;
921 //info() << "NEW_POS_IN_LIST=" << new_pos_in_list << " nb=" << nb << " alloc_size=" << alloc_size;
922 // Checks that the position is indeed a multiple of pre_allocated_size.
923 if (pre_allocated_size != 0) {
924 Int32 pos_modulo = new_pos_in_list % pre_allocated_size;
925 if (pos_modulo != 0)
926 ARCANE_FATAL("Bad position i={0} pos={1} pre_alloc_size={2} modulo={3}",
927 i, new_pos_in_list, pre_allocated_size, pos_modulo);
928 }
929 m_p->m_connectivity_list_array.addRange(con_list);
930 // If pre-allocation, fill the remaining elements with the null entity..
931 if (alloc_size != nb)
932 m_p->m_connectivity_list_array.addRange(NULL_ITEM_LOCAL_ID, alloc_size - nb);
933 if (m_pre_allocated_size == 0 && nb == 0)
934 m_connectivity_index[lid] = 0;
935 }
936 _notifyConnectivityListChanged();
937 _computeMaxNbConnectedItem();
938 info(4) << "Compacting IncrementalItemConnectivity name=" << name()
939 << " nb_item=" << nb_item << " old_size=" << old_size
940 << " new_size=" << m_connectivity_list.size()
941 << " prealloc_size=" << m_pre_allocated_size;
942}
943
944/*---------------------------------------------------------------------------*/
945/*---------------------------------------------------------------------------*/
946
947/*---------------------------------------------------------------------------*/
948/*---------------------------------------------------------------------------*/
949
950/*---------------------------------------------------------------------------*/
951/*---------------------------------------------------------------------------*/
952
953OneItemIncrementalItemConnectivity::
954OneItemIncrementalItemConnectivity(IItemFamily* source_family, IItemFamily* target_family,
955 const String& aname)
956: IncrementalItemConnectivityBase(source_family, target_family, aname)
957{
958 info(4) << "Using fixed OneItem connectivity for name=" << name();
959}
960
961/*---------------------------------------------------------------------------*/
962/*---------------------------------------------------------------------------*/
963
964OneItemIncrementalItemConnectivity::
965~OneItemIncrementalItemConnectivity()
966{
967}
968
969/*---------------------------------------------------------------------------*/
970/*---------------------------------------------------------------------------*/
971
973addConnectedItem(ItemLocalId source_item, ItemLocalId target_item)
974{
975 Int32 lid = source_item.localId();
976 Integer size = m_connectivity_nb_item[lid];
977 if (size != 0)
978 ARCANE_FATAL("source_item already have connected items");
979 Int32 target_lid = target_item.localId();
980 m_connectivity_list[lid] = target_lid;
981 m_connectivity_nb_item[lid] = 1;
982 _setNewMaxNbConnectedItems(1);
983}
984
985/*---------------------------------------------------------------------------*/
986/*---------------------------------------------------------------------------*/
987
990{
991 Int32 lid = source_item.localId();
992 m_connectivity_nb_item[lid] = 0;
993}
994
995/*---------------------------------------------------------------------------*/
996/*---------------------------------------------------------------------------*/
997
999removeConnectedItem(ItemLocalId source_item, ItemLocalId target_item)
1000{
1001 Int32 lid = source_item.localId();
1002 Int32 target_local_id = target_item.localId();
1003 Integer size = m_connectivity_nb_item[lid];
1004 if (size != 1)
1005 ARCANE_FATAL("source_item has no connected item");
1006 Int32 target_lid = m_connectivity_list[lid];
1007 if (target_lid != target_local_id)
1008 ARCANE_FATAL("source_item is not connected to item with wanted_lid={0} current_lid={1}",
1009 target_local_id, target_lid);
1010 m_connectivity_nb_item[lid] = 0;
1011 m_connectivity_list[lid] = NULL_ITEM_LOCAL_ID;
1012}
1013
1014/*---------------------------------------------------------------------------*/
1015/*---------------------------------------------------------------------------*/
1016
1018replaceConnectedItem(ItemLocalId source_item, Integer index, ItemLocalId target_item)
1019{
1020 if (index != 0)
1021 ARCANE_FATAL("index has to be '0'");
1022 Int32 lid = source_item.localId();
1023 Int32 target_lid = target_item.localId();
1024 m_connectivity_list[lid] = target_lid;
1025}
1026
1027/*---------------------------------------------------------------------------*/
1028/*---------------------------------------------------------------------------*/
1029
1031replaceConnectedItems(ItemLocalId source_item, Int32ConstArrayView target_local_ids)
1032{
1033 Int32 lid = source_item.localId();
1034 Integer n = target_local_ids.size();
1035 if (n == 0)
1036 return;
1037 if (n != 1)
1038 ARCANE_FATAL("Invalid size for target_list. value={0} (expected 1)", n);
1039 m_connectivity_list[lid] = target_local_ids[0];
1040}
1041
1042/*---------------------------------------------------------------------------*/
1043/*---------------------------------------------------------------------------*/
1044
1046hasConnectedItem(ItemLocalId source_item,
1047 ItemLocalId target_local_id) const
1048{
1049 if (m_connectivity_list[source_item.localId()] == target_local_id.localId())
1050 return true;
1051 else
1052 return false;
1053}
1054
1055/*---------------------------------------------------------------------------*/
1056/*---------------------------------------------------------------------------*/
1057
1058void OneItemIncrementalItemConnectivity::
1059_checkResizeConnectivityList()
1060{
1061 // Resizes the connectivity list with the same number of elements
1062 // as the number of entities.
1063 Integer wanted_size = m_connectivity_nb_item.size();
1064 Integer list_size = m_connectivity_list.size();
1065 if (list_size == wanted_size)
1066 return;
1067 Integer capacity = m_p->m_connectivity_list_array.capacity();
1068 if (wanted_size >= capacity) {
1069 m_p->m_connectivity_list_array.reserve(m_p->m_connectivity_nb_item_array.capacity());
1070 }
1071 m_p->m_connectivity_list_array.resize(wanted_size);
1072 _notifyConnectivityListChanged();
1073}
1074
1075/*---------------------------------------------------------------------------*/
1076/*---------------------------------------------------------------------------*/
1077
1080{
1081 Int32 lid = item.localId();
1082 m_p->_checkResize(lid);
1083 _notifyConnectivityIndexChanged();
1084 _notifyConnectivityNbItemChanged();
1085 _checkResizeConnectivityList();
1086
1087 m_connectivity_nb_item[lid] = 0;
1088 m_connectivity_index[lid] = lid;
1089 m_connectivity_list[lid] = NULL_ITEM_LOCAL_ID;
1090}
1091
1092/*---------------------------------------------------------------------------*/
1093/*---------------------------------------------------------------------------*/
1094
1097{
1098 // For this implementation, the indices should not be updated
1099 // because otherwise we won't have m_connectivity_index[lid] = lid.
1100 // TODO: since m_connectivity_nb_item is originally 1 everywhere, it's
1101 // not useful to do it on this variable either, but
1102 // since there might be entities for which nb_item is 0 if
1103 // no connected entity was added, it is better to perform the compaction.
1104
1105 m_p->m_connectivity_nb_item_variable.variable()->compact(new_to_old_ids);
1106 _notifyConnectivityNbItemChanged();
1107
1108 // Since with this implementation the connectivity list is indexed
1109 // by the localId() of the source entity, it must be compacted
1110 // m_p->m_connectivity_list_variable.
1111 m_p->m_connectivity_list_variable.variable()->compact(new_to_old_ids);
1112 _notifyConnectivityListChanged();
1113
1114 // Does not compact the indices but still updates the size
1115 // of the array.
1116 m_p->m_connectivity_index_array.resize(m_connectivity_nb_item.size());
1117 _notifyConnectivityIndexChanged();
1118}
1119
1120/*---------------------------------------------------------------------------*/
1121/*---------------------------------------------------------------------------*/
1122
1127
1128/*---------------------------------------------------------------------------*/
1129/*---------------------------------------------------------------------------*/
1130
1132dumpStats(std::ostream& out) const
1133{
1134 size_t allocated_size = m_p->m_connectivity_list_array.capacity() + m_p->m_connectivity_index_array.capacity() + m_p->m_connectivity_nb_item_array.capacity();
1135 allocated_size *= sizeof(Int32);
1136
1137 out << " connectiviy name=" << name()
1138 << " list_size=" << m_connectivity_list.size()
1139 << " index_size=" << m_connectivity_index.size()
1140 << " nb_item_size=" << m_connectivity_nb_item.size()
1141 << " allocated_size=" << allocated_size;
1142}
1143
1144/*---------------------------------------------------------------------------*/
1145/*---------------------------------------------------------------------------*/
1146
1147void OneItemIncrementalItemConnectivity::
1148compactConnectivityList()
1149{
1150 _computeMaxNbConnectedItem();
1151}
1152
1153/*---------------------------------------------------------------------------*/
1154/*---------------------------------------------------------------------------*/
1155
1156} // End namespace Arcane::mesh
1157
1158/*---------------------------------------------------------------------------*/
1159/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Utility functions for the mesh.
void removeItemAndKeepOrder(Int32ArrayView items, Int32 local_id)
Removes an entity while preserving order.
Integer capacity() const
Capacity (number of allocated elements) of the vector.
Integer size() const
Number of elements in the vector.
constexpr Integer size() const noexcept
Returns the size of the array.
void shrink()
Reallocates to free unused memory.
void resize(Int64 s)
Changes the number of elements in the array to s.
const T * data() const
Access to the root of the array without any protection.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
ArrayView< T > view() const
Mutable view of this array.
ItemVectorView resizeAndCopy(Int32ConstArrayView ids)
Positions the connectivity list with the entities specified by ids.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
Internal Arcane API for IIncrementalItemConnectivity.
virtual Integer preAllocatedSize() const =0
Number of entities pre-allocated for the connectivity of each entity.
Interface of an entity family.
Definition IItemFamily.h:83
virtual String name() const =0
Family name.
virtual eItemKind itemKind() const =0
Entity kind.
virtual IMesh * mesh() const =0
Associated mesh.
virtual Properties * properties()=0
Properties associated with this family.
@ PPrivate
Indicates that the variable is private.
Definition IVariable.h:103
Views of containers holding connectivity. This class allows the containers used to be opaque outside ...
Memory usage information for connectivities.
Int64 m_total_capacity
Total number of Int32 allocated (corresponds to the sum of capacity()).
Int64 m_total_size
Total number of Int32 used (corresponds to the sum of size()).
Connectivity information, for an entity family, allowing transition between old and new connectivity ...
void _setConnectivityNbItem(Int32 item_kind, ConstArrayView< Int32 > v)
Positions the array containing the number of connected entities.
void _setConnectivityList(Int32 item_kind, ArrayView< Int32 > v)
Positions the array containing the connectivity list.
void _setConnectivityIndex(Int32 item_kind, ConstArrayView< Int32 > v)
Positions the connectivity index array.
Index of an Item in a variable.
Definition ItemLocalId.h:42
View on a vector of entities.
List of observers.
Integer getIntegerWithDefault(const String &name, Integer default_value) const
Value of the property named name.
Reference to an instance.
Unicode character string constructor.
TraceMessage info() const
Flow for an information message.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
Abstract class for managing connectivities.
String name() const final
Name of the connectivity.
void addMemoryInfos(ItemConnectivityMemoryInfo &mem_info) override
Adds the instance's memory information to mem_info.
void shrinkMemory() override
Minimally reduces memory usage for connectivities.
Base class for incremental item->item[] connectivities.
void notifySourceFamilyLocalIdChanged(Int32ConstArrayView new_to_old_ids) override
Notifies the connectivity that the source family has been compacted.
Int32 maxNbConnectedItem() const override
Maximum number of entities connected to a source entity.
void setItemConnectivityList(ItemInternalConnectivityList *ilist, Int32 index)
Indicates that this connectivity is associated with one of the connectivities of ItemInternal.
void reserveMemoryForNbSourceItems(Int32 n, bool pre_alloc_connectivity) override
Reserves memory for n source entities.
ItemVectorView _connectedItems(ItemLocalId item, ConnectivityItemVector &con_items) const final
Fills con_items with the entities connected to item.
IIncrementalItemConnectivityInternal * _internalApi() override
Internal Arcane API.
void notifyTargetFamilyLocalIdChanged(Int32ConstArrayView old_to_new_ids) override
Notifies the connectivity that the target family has been compacted.
bool hasConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id) const override
Tests the existence of a connectivity between source_item and the entity with localId() target_local_...
void setConnectedItems(ItemLocalId source_item, Int32ConstArrayView target_local_ids) override
Allocates and positions entities connected to source_item.
void compactConnectivityList()
Compresses the connectivity list.
void removeConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id) override
Removes the entity with localId() target_local_id from the connectivity of source_item.
void notifySourceItemAdded(ItemLocalId item) override
Notifies the connectivity that an entity has been added to the source family.
void addConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id) override
Adds the entity with localId() target_local_id to the connectivity of source_item.
void removeConnectedItems(ItemLocalId source_item) override
Removes all entities connected to source_item.
void notifyReadFromDump() override
Notifies the connectivity that a read has been performed from a dump.
void dumpStats(std::ostream &out) const override
Dumps statistics on usage and memory used to the stream out.
void replaceConnectedItems(ItemLocalId source_item, Int32ConstArrayView target_local_ids) override
Replaces the entities of source_item with the entities with localId() target_local_ids.
void replaceConnectedItem(ItemLocalId source_item, Integer index, ItemLocalId target_local_id) override
Replaces the entity at index index of source_item with the entity with localId() target_local_id.
void setPreAllocatedSize(Integer value) final
Sets the number of entities to pre-allocate for the connectivity of each entity.
void removeConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id) override
Removes the entity with localId() target_local_id from the connectivity of source_item.
void replaceConnectedItems(ItemLocalId source_item, Int32ConstArrayView target_local_ids) override
Replaces the entities of source_item with the entities with localId() target_local_ids.
void addConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id) override
Adds the entity with localId() target_local_id to the connectivity of source_item.
void notifyReadFromDump() override
Notifies the connectivity that a read has been performed from a dump.
bool hasConnectedItem(ItemLocalId source_item, ItemLocalId target_local_id) const override
Tests the existence of a connectivity between source_item and the entity with localId() target_local_...
void notifySourceFamilyLocalIdChanged(Int32ConstArrayView new_to_old_ids) override
Notifies the connectivity that the source family has been compacted.
void replaceConnectedItem(ItemLocalId source_item, Integer index, ItemLocalId target_local_id) override
Replaces the entity at index index of source_item with the entity with localId() target_local_id.
void notifySourceItemAdded(ItemLocalId item) override
Notifies the connectivity that an entity has been added to the source family.
void removeConnectedItems(ItemLocalId source_item) override
Removes all entities connected to source_item.
void dumpStats(std::ostream &out) const override
Dumps statistics on usage and memory used to the stream out.
T max(const T &a, const T &b, const T &c)
Returns the maximum of three elements.
Definition MathUtils.h:407
VariableRefArrayT< Int32 > VariableArrayInt32
Array variable of 32-bit integer type.
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
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
std::int32_t Int32
Signed integer type of 32 bits.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.