Arcane  v3.16.8.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AnyItemLinkFamily.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* AnyItemLinkFamily.h (C) 2000-2025 */
9/* */
10/* Famille de liens entre 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
22ARCANE_BEGIN_NAMESPACE
23
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
26
27ANYITEM_BEGIN_NAMESPACE
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
35template<typename U, typename V>
36class PairT
37{
38public:
39 PairT(U u, V v) : m_u(u), m_v(v) {}
40 U m_u;
41 V m_v;
42};
43
44template<typename U, typename V>
45inline PairT<U,V> Pair(U u, V v) { return PairT<U,V>(u,v); }
46
47/*---------------------------------------------------------------------------*/
48/*---------------------------------------------------------------------------*/
49
66{
67public:
68
72 class LinkData
73 {
74 friend class LinkFamilyInternal;
75
76#ifdef ARCANE_ANYITEM_USEPACKEDDATA
77 public:
78 LinkData() : m_packed_data(0) {}
80 Integer groupIndex() const { return m_packed_data >> m_group_shift; }
82 Integer varIndex() const { return m_packed_data & m_integer_mask; }
84 Integer localId() const { return (m_packed_data >> m_local_id_shift) & m_integer_mask; }
86 bool operator==(const LinkData& data) const { return m_packed_data == data.m_packed_data; }
87private:
88 static const Integer m_integer_size = 26;
89 static const Int64 m_integer_mask = (Int64(1)<<m_integer_size)-1;
90 static const Integer m_short_size = 8;
91 static const Int64 m_short_mask = (Int64(1)<<m_short_size)-1;
92 static const Integer m_group_shift = 52;
93 static const Int64 m_group_mask = m_short_mask<<m_group_shift;
94 static const Integer m_local_id_shift = m_integer_size;
95 static const Int64 m_local_id_mask = m_integer_mask<<m_local_id_shift;
96
97 inline void setGroupIndex(Integer group_index) {
98 ARCANE_ASSERT(((group_index & ~m_short_mask) == 0),("Too large group index %d", group_index));
99 m_packed_data = (m_packed_data & ~m_group_mask) | (Int64(group_index)<<m_group_shift);
100 ARCANE_ASSERT((groupIndex() == group_index),("Corrupted data write detected"));
101 }
102 inline void setLocalId(Integer local_id) {
103 ARCANE_ASSERT(((local_id & ~m_integer_mask) == 0),("Too large local id %d", local_id));
104 m_packed_data = (m_packed_data & ~m_local_id_mask) | (Int64(local_id)<<m_local_id_shift);
105 ARCANE_ASSERT((localId() == local_id),("Corrupted data write detected"));
106 }
107 inline void setVarIndex(Integer item_local_id) {
108 ARCANE_ASSERT(((item_local_id & ~m_integer_mask) == 0),("Too large item local id %d", item_local_id));
109 m_packed_data = (m_packed_data & ~m_integer_mask) | item_local_id;
110 ARCANE_ASSERT((varIndex() == item_local_id),("Corrupted data write detected"));
111 }
112 private:
113 Int64 m_packed_data;
114#else /* ARCANE_ANYITEM_USEPACKEDDATA */
115 public:
116 LinkData() : m_group_index(0), m_local_id(0), m_var_index(0) {}
118 Integer groupIndex() const { return m_group_index; }
120 Integer varIndex() const { return m_var_index; }
122 Integer localId() const { return m_local_id; }
124 bool operator==(const LinkData& data) const {
125 return m_group_index == data.m_group_index
126 && m_local_id == data.m_local_id
127 && m_var_index == data.m_var_index;
128 }
129 private:
130 inline void setGroupIndex(Integer group_index) { m_group_index = group_index; }
131 inline void setLocalId(Integer local_id) { m_local_id = local_id; }
132 inline void setVarIndex(Integer item_local_id) { m_var_index = item_local_id; }
133 private:
134 unsigned m_group_index;
135 unsigned m_local_id;
137#endif /* ARCANE_ANYITEM_USEPACKEDDATA */
138 };
139
144 class LinkIndex
145 {
146 public:
147 LinkIndex()
148 : m_index(0) {}
149 LinkIndex(Integer index)
150 : m_index(index) {}
151 inline Integer index() const { return m_index; }
152 protected:
153 Integer m_index;
154 };
155
159 class Enumerator
160 : public LinkIndex
161 {
162 public:
163 Enumerator(const Arcane::Array<LinkData>& sources,
164 const Arcane::Array<LinkData>& targets)
165 : LinkIndex(), m_sources(sources), m_targets(targets) {}
166 Enumerator(const Enumerator& e)
167 : LinkIndex(), m_sources(e.m_sources), m_targets(e.m_targets) {}
168 inline bool hasNext() const { return m_sources.size() != m_index; }
169 inline void operator++() { m_index++; }
171 inline const LinkData& back() const {
172 return m_sources[m_index];
173 }
174
175 inline const LinkData& front() const {
176 return m_targets[m_index];
177 }
178 private:
183 };
184
188 class Link
189 : public LinkIndex
190 {
191 public:
192
196 template<typename U, typename V>
197 struct LinkAdder
198 {
199 // Adder pour une pair de groupe
200 LinkAdder(LinkFamilyInternal& family, ItemGroupT<U> a, ItemGroupT<V> b)
201 : m_family(family), m_a(a), m_b(b), m_used(false) {}
202 ~LinkAdder()
203 {
204 ARCANE_ASSERT((m_used == true),("LinkAdder never used"));
205 }
206
208 template<typename R, typename S>
209 inline void operator<<(const PairT<R,S>& p)
210 {
211 ARCANE_ASSERT((m_used == false),("VariableAdder already used"));
212 m_family.addSourceNode(p.m_u,m_a);
213 m_family.addTargetNode(p.m_v,m_b);
214 m_used = true;
215 }
216
217 private:
220
223
226
228 bool m_used;
229 };
230
231 public:
232
233 Link(LinkFamilyInternal& family, Integer index)
234 : LinkIndex(index), m_family(family), m_used(false) {}
235 ~Link()
236 {
237 ARCANE_ASSERT((m_used == true),("Link never used"));
238 }
239
241 template<typename U, typename V>
243 {
244 m_used = true;
245 return LinkAdder<U,V>(m_family,a,b);
246 }
247
248 private:
249
252
254 bool m_used;
255 };
256
257private:
258
259 typedef std::set<ILinkFamilyObserver*> LinkFamilyObservers;
260
261public:
262
264 LinkFamilyInternal(const Family& family)
265 : m_family(family)
266 , m_nb_link(0)
267 {
268 m_family.registerObserver(*this);
269 }
270
272 {
273 arcaneCallFunctionAndTerminateIfThrow([&]() { m_family.removeObserver(*this);});
274 }
275
277 inline Link newLink()
278 {
279 if(m_nb_link >= capacity()) {
280 m_source_nodes.reserve(2 * capacity());
281 m_target_nodes.reserve(2 * capacity());
282 _notifyFamilyIsReserved();
283 }
284 m_nb_link++;
287 return Link(*this,m_nb_link-1);
288 }
289
291 inline void reserve(Integer size) {
292 m_source_nodes.reserve(size);
293 m_target_nodes.reserve(size);
294 _notifyFamilyIsReserved();
295 }
296
299
301 inline Integer capacity() const {
302 return m_source_nodes.capacity();
303 }
304
306 void clear() {
307 m_nb_link = 0;
308 m_source_nodes.clear();
309 m_target_nodes.clear();
310 _notifyFamilyIsInvalidate();
311 }
312
315 {
316 LinkFamilyObservers::const_iterator it = m_observers.find(&observer);
317 if(it != m_observers.end())
318 throw FatalErrorException("LinkFamilyObserver already registered");
319 m_observers.insert(&observer);
320 }
321
324 {
325 LinkFamilyObservers::const_iterator it = m_observers.find(&observer);
326 if(it == m_observers.end())
327 throw FatalErrorException("LinkFamilyObserver not registered");
328 m_observers.erase(it);
329 }
330
333 // Si la famille change, on invalide la famille des liaisons
334 clear();
335 _notifyFamilyIsInvalidate();
336 }
337
338 // Notifie que la famille est agrandie
340 // On ne fait rien dans ce cas
341 }
342
343public:
344
345 template<typename T, typename V>
346 inline void addSourceNode(const T& t, ItemGroupT<V> group) {
347 //_addNode(t, group, m_source_nodes);
348 initLinkData(m_source_nodes.back(), t, group);
349 }
350
351 template<typename T, typename V>
352 inline void addTargetNode(const T& t, ItemGroupT<V> group) {
353 //_addNode(t, group, m_target_nodes);
354 initLinkData(m_target_nodes.back(), t, group);
355 }
356
357 const LinkData& source(const LinkIndex& link) const {
358 return m_source_nodes[link.index()];
359 }
360
361 const LinkData& target(const LinkIndex& link) const {
362 return m_target_nodes[link.index()];
363 }
364
365public:
366
367 const Family& family() const {
368 return m_family;
369 }
370
371private:
372
373 // //! Ajout des noeuds des liaisons par type d'item
374 // // non optimal pour les variables partielles, il faut aller checher la
375 // // position de l'item dans le groupe
376 // template<typename T>
377 // inline void _addNode(const T& t, ItemGroupT<T> group, Arcane::Array<LinkData>& nodes) {
378 // LinkData& data = nodes.back();
379 // const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
380 // ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
381 // data.setGroupIndex(info->group_index);
382 // const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
383 // data.setLocalId(info->local_id_offset + local_index);
384 // if(info->is_partial) {
385 // const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
386 // data.setVarIndex(local_index);
387 // } else {
388 // data.setVarIndex(t.localId());
389 // }
390 // }
391
392 // //! Ajout des noeuds des liaisons par énumerateurs
393 // // optimal pour les variables partielles
394 // template<typename T>
395 // inline void _addNode(const ItemEnumeratorT<T>& t, ItemGroupT<T> group, Arcane::Array<LinkData>& nodes) {
396 // LinkData& data = nodes.back();
397 // const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
398 // ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
399 // data.setGroupIndex(info->group_index);
400 // const Integer local_index = t.index();
401 // data.setLocalId(info->local_id_offset + local_index);
402 // if(info->is_partial) {
403 // data.setVarIndex(local_index);
404 // } else {
405 // data.setVarIndex(t.localId());
406 // }
407 // }
408
409public:
410
412 // non optimal pour les variables partielles, il faut aller checher la
413 // position de l'item dans le groupe
414 template<typename T>
415 void initLinkData(LinkData& data, const T& t, ItemGroupT<T> group) const
416 {
417 const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
418 ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
419 data.setGroupIndex(info->group_index);
420 const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
421 data.setLocalId(info->local_id_offset + local_index);
422 if(info->is_partial) {
423 const Integer local_index = (*(group.localIdToIndex()))[t.localId()];
424 data.setVarIndex(local_index);
425 } else {
426 data.setVarIndex(t.localId());
427 }
428 }
429
431 // optimal pour les variables partielles
432 template<typename T>
433 void initLinkData(LinkData& data, const ItemEnumeratorT<T>& t, ItemGroupT<T> group) const
434 {
435 const Private::GroupIndexInfo * info = m_family.internal()->findGroupInfo(group);
436 ARCANE_ASSERT((info != 0),("Inconsistent group info while adding new node"));
437 data.setGroupIndex(info->group_index);
438 const Integer local_index = t.index();
439 data.setLocalId(info->local_id_offset + local_index);
440 if(info->is_partial) {
441 data.setVarIndex(local_index);
442 } else {
443 data.setVarIndex(t.localId());
444 }
445 }
446
448 Item item(const LinkData& link_data) const {
449 return m_family.item(link_data);
450 }
451
452private:
453
454 void _notifyFamilyIsInvalidate() {
455 for(LinkFamilyObservers::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
456 (*it)->notifyFamilyIsInvalidate();
457 }
458
459 void _notifyFamilyIsReserved() {
460 for(LinkFamilyObservers::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
461 (*it)->notifyFamilyIsReserved();
462 }
463
464private:
465
467 const Family m_family;
468
471
474
477
479 // Pour que les objets construits sur la famille ne puissent pas la modifier
480 mutable LinkFamilyObservers m_observers;
481};
482
483/*---------------------------------------------------------------------------*/
484/*---------------------------------------------------------------------------*/
485
489class LinkFamily
490 : public IFamilyObserver
491{
492public:
493
494 typedef LinkFamilyInternal::Enumerator Enumerator;
495 typedef LinkFamilyInternal::Link Link;
496 typedef LinkFamilyInternal::LinkIndex LinkIndex;
497 typedef LinkFamilyInternal::LinkData LinkData;
498
499public:
500
501 LinkFamily(const Family& f)
502 : m_internal(new LinkFamilyInternal(f)) {}
503
504 LinkFamily(const LinkFamily& f)
505 : m_internal(f.m_internal) {}
506
507 ~LinkFamily() {}
508
510 inline Link newLink()
511 {
512 return m_internal->newLink();
513 }
514
516 inline void reserve(Integer size) {
517 m_internal->reserve(size);
518 }
519
521 inline Enumerator enumerator() const { return m_internal->enumerator(); }
522
524 inline Integer capacity() const {
525 return m_internal->capacity();
526 }
527
529 void clear() {
530 m_internal->clear();
531 }
532
535 {
536 m_internal->registerObserver(observer);
537 }
538
541 {
542 m_internal->removeObserver(observer);
543 }
544
547 m_internal->notifyFamilyIsInvalidate();
548 }
549
552 m_internal->notifyFamilyIsIncreased();
553 }
554
555public:
556
557 template<typename T, typename V>
558 inline void addSourceNode(const T& t, ItemGroupT<V> group) {
559 m_internal->addSourceNode(t,group);
560 }
561
562 template<typename T, typename V>
563 inline void addTargetNode(const T& t, ItemGroupT<V> group) {
564 m_internal->addTargetNode(t,group);
565 }
566
567public:
568
569 LinkFamilyInternal * internal() const {
570 return m_internal.get();
571 }
572
573private:
574
577};
578
579/*---------------------------------------------------------------------------*/
580/*---------------------------------------------------------------------------*/
581
582ANYITEM_END_NAMESPACE
583ARCANE_END_NAMESPACE
584
585/*---------------------------------------------------------------------------*/
586/*---------------------------------------------------------------------------*/
587
588#endif /* ARCANE_ANYITEM_ANYITEMLINKFAMILY_H */
Tableau d'items de types quelconques.
Exception lorsqu'une erreur fatale est survenue.
Interface d'observeurs de famille AnyItem.
Interface d'observeurs de famille de liaisons AnyItem.
Int32 localId() const
localId() de l'entité courante.
constexpr Integer index() const
Indice courant de l'énumérateur.
Enumérateur sur une liste typée d'entités de type ItemType.
Référence à un groupe d'un genre donné.
Definition ItemGroup.h:413
SharedPtrT< GroupIndexTable > localIdToIndex() const
Table des local ids vers une position pour toutes les entités du groupe.
Definition ItemGroup.h:307
Classe de base d'un élément de maillage.
Definition Item.h:83
const Arcane::Array< LinkData > & m_sources
Toutes les données back.
const LinkData & back() const
Données du lien back.
const Arcane::Array< LinkData > & m_targets
Toutes les données front.
const LinkData & front() const
Données du lien front.
unsigned m_group_index
Index du groupe d'où vient cet item.
Integer m_var_index
Index pour les partiels, localId sinon.
bool operator==(const LinkData &data) const
Opérateur de comparaison.
unsigned m_local_id
Identifiant dans l(indexation globale de AnyItem::Family.
Integer varIndex() const
Identifiant localId de l'item référencé dans sa famille IItemFamily d'origine.
Integer localId() const
Identifiant localId de l'item référencé dans sa famille AnyItemFamily.
Integer groupIndex() const
Identifiant du groupe auquel est associé l'item référencé par ce LinkData.
Famille de liens AnyItem partie interne les données stockées sont les localid des items et l'offset d...
void initLinkData(LinkData &data, const ItemEnumeratorT< T > &t, ItemGroupT< T > group) const
Ajout des noeuds des liaisons par énumerateurs.
LinkFamilyInternal(const Family &family)
Famille de liens pour une famille anyitem.
Link newLink()
Création d'un nouveau lien vide.
LinkFamilyObservers m_observers
Observeurs de la famille.
Integer m_nb_link
Nombre de liens.
Arcane::UniqueArray< LinkData > m_source_nodes
Données back.
Enumerator enumerator() const
Enumérateurs des liens.
void clear()
Vide la famille.
void notifyFamilyIsInvalidate()
Notifie que la famille est invalidée.
void removeObserver(ILinkFamilyObserver &observer) const
Détruit un observeur de la famille.
Integer capacity() const
retourne la capacité
void registerObserver(ILinkFamilyObserver &observer) const
Enrgistre un observeur de la famille.
Item item(const LinkData &link_data) const
Retoune l'item concret associé à ce AnyItem.
void initLinkData(LinkData &data, const T &t, ItemGroupT< T > group) const
Ajout des noeuds des liaisons par type d'item.
void reserve(Integer size)
Réserve une capacité de liens.
Arcane::UniqueArray< LinkData > m_target_nodes
Données front.
const Family m_family
Famille AnyItem.
void notifyFamilyIsIncreased()
Notifie à l'observeur que la famille est agrandie.
Integer capacity() const
retourne la capacité
void reserve(Integer size)
Réserve une capacité de liens.
Enumerator enumerator() const
Enumérateurs des liens.
void notifyFamilyIsIncreased()
Notifie que la famille est agrandie.
void registerObserver(ILinkFamilyObserver &observer) const
Enrgistre un observeur de la famille.
SharedPtrT< LinkFamilyInternal > m_internal
Famille de liens interne.
void removeObserver(ILinkFamilyObserver &observer) const
Detruit un observeur de la famille.
void clear()
Vide la famille.
void notifyFamilyIsInvalidate()
Notifie que la famille est invalidée.
Link newLink()
Création d'un nouveau lien vide.
Outil pour créer une pair d'items.
Vecteur 1D de données avec sémantique par valeur (style STL).
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)