Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
AnyItemLinkFamily.h
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/* AnyItemLinkFamily.h (C) 2000-2025 */
9/* */
10/* Link family between any items. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_CORE_ANYITEM_ANYITEMLINKFAMILY_H
13#define ARCANE_CORE_ANYITEM_ANYITEMLINKFAMILY_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/core/anyitem/AnyItemGlobal.h"
18
19/*---------------------------------------------------------------------------*/
20/*---------------------------------------------------------------------------*/
21
22namespace Arcane::AnyItem
23{
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
31template <typename U, typename V>
32class PairT
33{
34 public:
35
36 PairT(U u, V v)
37 : m_u(u)
38 , m_v(v)
39 {}
40 U m_u;
41 V m_v;
42};
43
44template <typename U, typename V>
45inline PairT<U, V> Pair(U u, V v)
46{
47 return PairT<U, V>(u, v);
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
69{
70 public:
71
75 class LinkData
76 {
77 friend class LinkFamilyInternal;
78
79#ifdef ARCANE_ANYITEM_USEPACKEDDATA
80 public:
81
82 LinkData()
83 : m_packed_data(0)
84 {}
86 Integer groupIndex() const { return m_packed_data >> m_group_shift; }
88 Integer varIndex() const { return m_packed_data & m_integer_mask; }
90 Integer localId() const { return (m_packed_data >> m_local_id_shift) & m_integer_mask; }
92 bool operator==(const LinkData& data) const { return m_packed_data == data.m_packed_data; }
93
94 private:
95
96 static const Integer m_integer_size = 26;
97 static const Int64 m_integer_mask = (Int64(1) << m_integer_size) - 1;
98 static const Integer m_short_size = 8;
99 static const Int64 m_short_mask = (Int64(1) << m_short_size) - 1;
100 static const Integer m_group_shift = 52;
101 static const Int64 m_group_mask = m_short_mask << m_group_shift;
102 static const Integer m_local_id_shift = m_integer_size;
103 static const Int64 m_local_id_mask = m_integer_mask << m_local_id_shift;
104
105 inline void setGroupIndex(Integer group_index)
106 {
107 ARCANE_ASSERT(((group_index & ~m_short_mask) == 0), ("Too large group index %d", group_index));
108 m_packed_data = (m_packed_data & ~m_group_mask) | (Int64(group_index) << m_group_shift);
109 ARCANE_ASSERT((groupIndex() == group_index), ("Corrupted data write detected"));
110 }
111 inline void setLocalId(Integer local_id)
112 {
113 ARCANE_ASSERT(((local_id & ~m_integer_mask) == 0), ("Too large local id %d", local_id));
114 m_packed_data = (m_packed_data & ~m_local_id_mask) | (Int64(local_id) << m_local_id_shift);
115 ARCANE_ASSERT((localId() == local_id), ("Corrupted data write detected"));
116 }
117 inline void setVarIndex(Integer item_local_id)
118 {
119 ARCANE_ASSERT(((item_local_id & ~m_integer_mask) == 0), ("Too large item local id %d", item_local_id));
120 m_packed_data = (m_packed_data & ~m_integer_mask) | item_local_id;
121 ARCANE_ASSERT((varIndex() == item_local_id), ("Corrupted data write detected"));
122 }
123
124 private:
125
126 Int64 m_packed_data;
127#else /* ARCANE_ANYITEM_USEPACKEDDATA */
128 public:
129
130 LinkData()
131 : m_group_index(0)
132 , m_local_id(0)
133 , m_var_index(0)
134 {}
136 Integer groupIndex() const { return m_group_index; }
138 Integer varIndex() const { return m_var_index; }
140 Integer localId() const { return m_local_id; }
142 bool operator==(const LinkData& data) const
143 {
144 return m_group_index == data.m_group_index && m_local_id == data.m_local_id && m_var_index == data.m_var_index;
145 }
146
147 private:
148
149 inline void setGroupIndex(Integer group_index) { m_group_index = group_index; }
150 inline void setLocalId(Integer local_id) { m_local_id = local_id; }
151 inline void setVarIndex(Integer item_local_id) { m_var_index = item_local_id; }
152
153 private:
154
155 unsigned m_group_index;
156 unsigned m_local_id;
158#endif /* ARCANE_ANYITEM_USEPACKEDDATA */
159 };
160
165 class LinkIndex
166 {
167 public:
168
169 LinkIndex()
170 : m_index(0)
171 {}
172 LinkIndex(Integer index)
173 : m_index(index)
174 {}
175 inline Integer index() const { return m_index; }
176
177 protected:
178
179 Integer m_index;
180 };
181
185 class Enumerator
186 : public LinkIndex
187 {
188 public:
189
190 Enumerator(const Arcane::Array<LinkData>& sources,
191 const Arcane::Array<LinkData>& targets)
192 : LinkIndex()
193 , m_sources(sources)
194 , m_targets(targets)
195 {}
196 Enumerator(const Enumerator& e)
197 : LinkIndex()
200 {}
201 inline bool hasNext() const { return m_sources.size() != m_index; }
202 inline void operator++() { m_index++; }
204 inline const LinkData& back() const
205 {
206 return m_sources[m_index];
207 }
208
209 inline const LinkData& front() const
210 {
211 return m_targets[m_index];
212 }
213
214 private:
215
220 };
221
225 class Link
226 : public LinkIndex
227 {
228 public:
229
233 template <typename U, typename V>
234 struct LinkAdder
235 {
236 // Adder for a group pair
237 LinkAdder(LinkFamilyInternal& family, ItemGroupT<U> a, ItemGroupT<V> b)
238 : m_family(family)
239 , m_a(a)
240 , m_b(b)
241 , m_used(false)
242 {}
243 ~LinkAdder()
244 {
245 ARCANE_ASSERT((m_used == true), ("LinkAdder never used"));
246 }
247
249 template <typename R, typename S>
250 inline void operator<<(const PairT<R, S>& p)
251 {
252 ARCANE_ASSERT((m_used == false), ("VariableAdder already used"));
253 m_family.addSourceNode(p.m_u, m_a);
254 m_family.addTargetNode(p.m_v, m_b);
255 m_used = true;
256 }
257
258 private:
259
262
265
268
270 bool m_used;
271 };
272
273 public:
274
275 Link(LinkFamilyInternal& family, Integer index)
276 : LinkIndex(index)
277 , m_family(family)
278 , m_used(false)
279 {}
280 ~Link()
281 {
282 ARCANE_ASSERT((m_used == true), ("Link never used"));
283 }
284
286 template <typename U, typename V>
288 {
289 m_used = true;
290 return LinkAdder<U, V>(m_family, a, b);
291 }
292
293 private:
294
297
299 bool m_used;
300 };
301
302 private:
303
304 typedef std::set<ILinkFamilyObserver*> LinkFamilyObservers;
305
306 public:
307
310 : m_family(family)
311 , m_nb_link(0)
312 {
313 m_family.registerObserver(*this);
314 }
315
317 {
319 }
320
322 inline Link newLink()
323 {
324 if (m_nb_link >= capacity()) {
325 m_source_nodes.reserve(2 * capacity());
326 m_target_nodes.reserve(2 * capacity());
327 _notifyFamilyIsReserved();
328 }
329 m_nb_link++;
332 return Link(*this, m_nb_link - 1);
333 }
334
336 inline void reserve(Integer size)
337 {
338 m_source_nodes.reserve(size);
339 m_target_nodes.reserve(size);
340 _notifyFamilyIsReserved();
341 }
342
345
347 inline Integer capacity() const
348 {
349 return m_source_nodes.capacity();
350 }
351
353 void clear()
354 {
355 m_nb_link = 0;
356 m_source_nodes.clear();
357 m_target_nodes.clear();
358 _notifyFamilyIsInvalidate();
359 }
360
363 {
364 LinkFamilyObservers::const_iterator it = m_observers.find(&observer);
365 if (it != m_observers.end())
366 throw FatalErrorException("LinkFamilyObserver already registered");
367 m_observers.insert(&observer);
368 }
369
372 {
373 LinkFamilyObservers::const_iterator it = m_observers.find(&observer);
374 if (it == m_observers.end())
375 throw FatalErrorException("LinkFamilyObserver not registered");
376 m_observers.erase(it);
377 }
378
381 {
382 // If the family changes, the link family is invalidated
383 clear();
384 _notifyFamilyIsInvalidate();
385 }
386
387 // Notifies that the family is increased
389 {
390 // Do nothing in this case
391 }
392
393 public:
394
395 template <typename T, typename V>
396 inline void addSourceNode(const T& t, ItemGroupT<V> group)
397 {
398 //_addNode(t, group, m_source_nodes);
399 initLinkData(m_source_nodes.back(), t, group);
400 }
401
402 template <typename T, typename V>
403 inline void addTargetNode(const T& t, ItemGroupT<V> group)
404 {
405 //_addNode(t, group, m_target_nodes);
406 initLinkData(m_target_nodes.back(), t, group);
407 }
408
409 const LinkData& source(const LinkIndex& link) const
410 {
411 return m_source_nodes[link.index()];
412 }
413
414 const LinkData& target(const LinkIndex& link) const
415 {
416 return m_target_nodes[link.index()];
417 }
418
419 public:
420
421 const Family& family() const
422 {
423 return m_family;
424 }
425
426 private:
427
428 // //! Adding link nodes by item type
429 // // not optimal for partial variables, one must go look up the
430 // // position of the item in the group
431 // template<typename T>
432 // inline void _addNode(const T& t, ItemGroupT<T> group, Arcane::Array<LinkData>& nodes) {
433 // LinkData& data = nodes.back();
434 // const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
435 // ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
436 // data.setGroupIndex(info->group_index);
437 // const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
438 // data.setLocalId(info->local_id_offset + local_index);
439 // if(info->is_partial) {
440 // const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
441 // data.setVarIndex(local_index);
442 // } else {
443 // data.setVarIndex(t.localId());
444 // }
445 // }
446
447 // //! Adding link nodes by enumerators
448 // // optimal for partial variables
449 // template<typename T>
450 // inline void _addNode(const ItemEnumeratorT<T>& t, ItemGroupT<T> group, Arcane::Array<LinkData>& nodes) {
451 // LinkData& data = nodes.back();
452 // const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
453 // ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
454 // data.setGroupIndex(info->group_index);
455 // const Integer local_index = t.index();
456 // data.setLocalId(info->local_id_offset + local_index);
457 // if(info->is_partial) {
458 // data.setVarIndex(local_index);
459 // } else {
460 // data.setVarIndex(t.localId());
461 // }
462 // }
463
464 public:
465
467 // not optimal for partial variables, one must go look up the
468 // position of the item in the group
469 template <typename T>
470 void initLinkData(LinkData& data, const T& t, ItemGroupT<T> group) const
471 {
472 const Private::GroupIndexInfo* info = m_family.internal()->findGroupInfo(group);
473 ARCANE_ASSERT((info != 0), ("Inconsistent group info while adding new node"));
474 data.setGroupIndex(info->group_index);
475 const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
476 data.setLocalId(info->local_id_offset + local_index);
477 if (info->is_partial) {
478 const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
479 data.setVarIndex(local_index);
480 }
481 else {
482 data.setVarIndex(t.localId());
483 }
484 }
485
487 // optimal for partial variables
488 template <typename T>
489 void initLinkData(LinkData& data, const ItemEnumeratorT<T>& t, ItemGroupT<T> group) const
490 {
491 const Private::GroupIndexInfo* info = m_family.internal()->findGroupInfo(group);
492 ARCANE_ASSERT((info != 0), ("Inconsistent group info while adding new node"));
493 data.setGroupIndex(info->group_index);
494 const Integer local_index = t.index();
495 data.setLocalId(info->local_id_offset + local_index);
496 if (info->is_partial) {
497 data.setVarIndex(local_index);
498 }
499 else {
500 data.setVarIndex(t.localId());
501 }
502 }
503
505 Item item(const LinkData& link_data) const
506 {
507 return m_family.item(link_data);
508 }
509
510 private:
511
512 void _notifyFamilyIsInvalidate()
513 {
514 for (LinkFamilyObservers::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
515 (*it)->notifyFamilyIsInvalidate();
516 }
517
518 void _notifyFamilyIsReserved()
519 {
520 for (LinkFamilyObservers::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
521 (*it)->notifyFamilyIsReserved();
522 }
523
524 private:
525
528
531
534
537
539 // So that objects built on the family cannot modify it
540 mutable LinkFamilyObservers m_observers;
541};
542
543/*---------------------------------------------------------------------------*/
544/*---------------------------------------------------------------------------*/
545
549class LinkFamily
550: public IFamilyObserver
551{
552 public:
553
554 typedef LinkFamilyInternal::Enumerator Enumerator;
555 typedef LinkFamilyInternal::Link Link;
556 typedef LinkFamilyInternal::LinkIndex LinkIndex;
557 typedef LinkFamilyInternal::LinkData LinkData;
558
559 public:
560
561 LinkFamily(const Family& f)
563 {}
564
565 LinkFamily(const LinkFamily& f)
567 {}
568
569 ~LinkFamily() {}
570
572 inline Link newLink()
573 {
574 return m_internal->newLink();
575 }
576
578 inline void reserve(Integer size)
579 {
580 m_internal->reserve(size);
581 }
582
584 inline Enumerator enumerator() const { return m_internal->enumerator(); }
585
587 inline Integer capacity() const
588 {
589 return m_internal->capacity();
590 }
591
593 void clear()
594 {
595 m_internal->clear();
596 }
597
600 {
601 m_internal->registerObserver(observer);
602 }
603
606 {
607 m_internal->removeObserver(observer);
608 }
609
612 {
613 m_internal->notifyFamilyIsInvalidate();
614 }
615
618 {
619 m_internal->notifyFamilyIsIncreased();
620 }
621
622 public:
623
624 template <typename T, typename V>
625 inline void addSourceNode(const T& t, ItemGroupT<V> group)
626 {
627 m_internal->addSourceNode(t, group);
628 }
629
630 template <typename T, typename V>
631 inline void addTargetNode(const T& t, ItemGroupT<V> group)
632 {
633 m_internal->addTargetNode(t, group);
634 }
635
636 public:
637
638 LinkFamilyInternal* internal() const
639 {
640 return m_internal.get();
641 }
642
643 private:
644
647};
648
649/*---------------------------------------------------------------------------*/
650/*---------------------------------------------------------------------------*/
651
652} // namespace Arcane::AnyItem
653
654/*---------------------------------------------------------------------------*/
655/*---------------------------------------------------------------------------*/
656
657#endif /* ARCANE_ANYITEM_ANYITEMLINKFAMILY_H */
AnyItem family (flyweight pattern) Aggregation of groups to describe variables / partial variables Co...
SharedPtrT< FamilyInternal > m_internal
Internal family.
void removeObserver(IFamilyObserver &observer) const
Remove an observer.
AnyItem family observer interface.
AnyItem link family observer interface.
const LinkData & front() const
Front link data.
const LinkData & back() const
Back link data.
const Arcane::Array< LinkData > & m_targets
All front data.
const Arcane::Array< LinkData > & m_sources
All back data.
Integer groupIndex() const
Identifier of the group associated with the item referenced by this LinkData.
Integer localId() const
LocalId identifier of the item referenced in its AnyItemFamily.
bool operator==(const LinkData &data) const
Comparison operator.
Integer varIndex() const
LocalId identifier of the item referenced in its original IItemFamily.
unsigned m_group_index
Index of the group from which this item comes.
Integer m_var_index
Index for partials, localId otherwise.
unsigned m_local_id
Identifier in the global indexing of AnyItem::Family.
Internal AnyItem Link Family The stored data are the local IDs of the items and the group offset with...
LinkFamilyObservers m_observers
Family observers.
void initLinkData(LinkData &data, const ItemEnumeratorT< T > &t, ItemGroupT< T > group) const
Adding link nodes by enumerators.
Arcane::UniqueArray< LinkData > m_source_nodes
Back data.
Integer capacity() const
returns the capacity
void notifyFamilyIsInvalidate()
Notifies that the family is invalidated.
void removeObserver(ILinkFamilyObserver &observer) const
Removes a family observer.
Enumerator enumerator() const
Link enumerators.
void reserve(Integer size)
Reserves a capacity of links.
void initLinkData(LinkData &data, const T &t, ItemGroupT< T > group) const
Adding link nodes by item type.
LinkFamilyInternal(const Family &family)
Link family for an anyitem family.
Arcane::UniqueArray< LinkData > m_target_nodes
Front data.
Link newLink()
Creation of a new empty link.
Item item(const LinkData &link_data) const
Returns the concrete item associated with this AnyItem.
void notifyFamilyIsIncreased()
Notifies the observer that the family has been increased.
void registerObserver(ILinkFamilyObserver &observer) const
Registers a family observer.
const Family m_family
AnyItem family.
void notifyFamilyIsInvalidate()
Notifies that the family is invalidated.
Enumerator enumerator() const
Link enumerators.
void clear()
Clears the family.
void notifyFamilyIsIncreased()
Notifies that the family is increased.
void registerObserver(ILinkFamilyObserver &observer) const
Registers a family observer.
void removeObserver(ILinkFamilyObserver &observer) const
Removes a family observer.
SharedPtrT< LinkFamilyInternal > m_internal
Internal link family.
Integer capacity() const
returns the capacity
Link newLink()
Creation of a new empty link.
void reserve(Integer size)
Reserves a capacity of links.
Tool to create a pair of items.
Base class for 1D data vectors.
Int32 localId() const
localId() of the current entity.
constexpr Integer index() const
Current index of the enumerator.
Enumerator over a typed list of entities of type ItemType.
Reference to a group of a given kind.
Definition ItemGroup.h:420
SharedPtrT< GroupIndexTable > localIdToIndex() const
Table of local ids to a position for all entities in the group.
Definition ItemGroup.h:312
Base class for a mesh element.
Definition Item.h:84
1D data vector with value semantics (STL style).
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)
Calls the function function and calls std::terminate() if an exception occurs.