dune-istl  2.11
hierarchy.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 // vi: set et ts=4 sw=2 sts=2:
5 #ifndef DUNE_AMGHIERARCHY_HH
6 #define DUNE_AMGHIERARCHY_HH
7 
8 #include <list>
9 #include <memory>
10 #include <limits>
11 #include <dune/common/stdstreams.hh>
12 #include <dune/common/timer.hh>
13 #include <dune/common/bigunsignedint.hh>
15 
16 namespace Dune
17 {
18  namespace Amg
19  {
38  template<typename T, typename A=std::allocator<T> >
39  class Hierarchy
40  {
41  public:
45  typedef T MemberType;
46 
47  template<typename T1, typename T2>
49 
50  private:
54  struct Element
55  {
56  friend class LevelIterator<Hierarchy<T,A>, T>;
57  friend class LevelIterator<const Hierarchy<T,A>, const T>;
58 
60  std::weak_ptr<Element> coarser_;
61 
63  std::shared_ptr<Element> finer_;
64 
66  std::shared_ptr<MemberType> element_;
67 
69  std::shared_ptr<MemberType> redistributed_;
70  };
71  public:
72 
76  using Allocator = typename std::allocator_traits<A>::template rebind_alloc<Element>;
77 
79 
84  Hierarchy(const std::shared_ptr<MemberType> & first);
85 
89  Hierarchy() : levels_(0)
90  {}
91 
95  Hierarchy(const Hierarchy& other);
96 
101  void addCoarser(Arguments& args);
102 
104 
109  void addFiner(Arguments& args);
110 
117  template<class C, class T1>
118  class LevelIterator
119  : public BidirectionalIteratorFacade<LevelIterator<C,T1>,T1,T1&>
120  {
121  friend class LevelIterator<typename std::remove_const<C>::type,
122  typename std::remove_const<T1>::type >;
123  friend class LevelIterator<const typename std::remove_const<C>::type,
124  const typename std::remove_const<T1>::type >;
125 
126  public:
128  LevelIterator() = default;
129 
130  LevelIterator(std::shared_ptr<Element> element)
131  : element_(std::move(element))
132  {}
133 
135  template <class C_, class T1_,
136  std::enable_if_t<std::is_same_v<std::remove_const_t<C>, std::remove_const_t<C_>>, int> = 0,
137  std::enable_if_t<std::is_same_v<std::remove_const_t<T1>, std::remove_const_t<T1_>>, int> = 0>
139  : element_(other.element_)
140  {}
141 
142  template <class C_, class T1_,
143  std::enable_if_t<std::is_same_v<std::remove_const_t<C>, std::remove_const_t<C_>>, int> = 0,
144  std::enable_if_t<std::is_same_v<std::remove_const_t<T1>, std::remove_const_t<T1_>>, int> = 0>
146  {
147  element_ = other.element_;
148  return *this;
149  }
150 
154  bool equals(const LevelIterator<typename std::remove_const<C>::type,
155  typename std::remove_const<T1>::type>& other) const
156  {
157  return element_ == other.element_;
158  }
159 
163  bool equals(const LevelIterator<const typename std::remove_const<C>::type,
164  const typename std::remove_const<T1>::type>& other) const
165  {
166  return element_ == other.element_;
167  }
168 
170  T1& dereference() const
171  {
172  return *(element_->element_);
173  }
174 
176  void increment()
177  {
178  element_ = element_->coarser_.lock();
179  }
180 
182  void decrement()
183  {
184  element_ = element_->finer_;
185  }
186 
191  bool isRedistributed() const
192  {
193  return (bool)element_->redistributed_;
194  }
195 
200  T1& getRedistributed() const
201  {
202  assert(element_->redistributed_);
203  return *element_->redistributed_;
204  }
205  void addRedistributed(std::shared_ptr<T1> t)
206  {
207  element_->redistributed_ = t;
208  }
209 
211  {
212  element_->redistributed_ = nullptr;
213  }
214 
215  private:
216  std::shared_ptr<Element> element_ = {};
217  };
218 
220  typedef LevelIterator<Hierarchy<T,A>,T> Iterator;
221 
223  typedef LevelIterator<const Hierarchy<T,A>, const T> ConstIterator;
224 
229  Iterator finest();
230 
235  Iterator coarsest();
236 
237 
242  ConstIterator finest() const;
243 
248  ConstIterator coarsest() const;
249 
254  std::size_t levels() const;
255 
256  private:
262  std::shared_ptr<MemberType> originalFinest_;
264  std::shared_ptr<Element> finest_;
266  std::shared_ptr<Element> coarsest_;
268  Allocator allocator_;
270  int levels_;
271  };
272 
273  template<class T, class A>
274  Hierarchy<T,A>::Hierarchy(const std::shared_ptr<MemberType> & first)
275  : originalFinest_(first)
276  {
277  finest_ = std::allocate_shared<Element>(allocator_);
278  finest_->element_ = originalFinest_;
279  coarsest_ = finest_;
280  levels_ = 1;
281  }
282 
284  //TODO: do we actually want to support this? This might be very expensive?!
285  template<class T, class A>
287  : allocator_(other.allocator_),
288  levels_(other.levels_)
289  {
290  if(!other.finest_)
291  {
292  finest_=coarsest_=nullptr;
293  return;
294  }
295  finest_ = std::allocate_shared<Element>(allocator_);
296  std::shared_ptr<Element> finer_;
297  std::shared_ptr<Element> current_ = finest_;
298  std::weak_ptr<Element> otherWeak_ = other.finest_;
299 
300  while(! otherWeak_.expired())
301  {
302  // create shared_ptr from weak_ptr, we just checked that this is safe
303  std::shared_ptr<Element> otherCurrent_ = std::shared_ptr<Element>(otherWeak_);
304  // clone current level
305  //TODO: should we use the allocator?
306  current_->element_ =
307  std::make_shared<MemberType>(*(otherCurrent_->element_));
308  current_->finer_=finer_;
309  if(otherCurrent_->redistributed_)
310  current_->redistributed_ =
311  std::make_shared<MemberType>(*(otherCurrent_->redistributed_));
312  finer_=current_;
313  if(not otherCurrent_->coarser_.expired())
314  {
315  auto c = std::allocate_shared<Element>(allocator_);
316  current_->coarser_ = c;
317  current_ = c;
318  }
319  // go to coarser level
320  otherWeak_ = otherCurrent_->coarser_;
321  }
322  coarsest_=current_;
323  }
324 
325  template<class T, class A>
326  std::size_t Hierarchy<T,A>::levels() const
327  {
328  return levels_;
329  }
330 
331  template<class T, class A>
333  {
334  coarsest_->redistributed_ = ConstructionTraits<MemberType>::construct(args);
335  }
336 
337  template<class T, class A>
339  {
340  if(!coarsest_) {
341  // we have no levels at all...
342  assert(!finest_);
343  // allocate into the shared_ptr
344  originalFinest_ = ConstructionTraits<MemberType>::construct(args);
345  coarsest_ = std::allocate_shared<Element>(allocator_);
346  coarsest_->element_ = originalFinest_;
347  finest_ = coarsest_;
348  }else{
349  auto old_coarsest = coarsest_;
350  coarsest_ = std::allocate_shared<Element>(allocator_);
351  coarsest_->finer_ = old_coarsest;
352  coarsest_->element_ = ConstructionTraits<MemberType>::construct(args);
353  old_coarsest->coarser_ = coarsest_;
354  }
355  ++levels_;
356  }
357 
358 
359  template<class T, class A>
361  {
362  //TODO: wouldn't it be better to do this in the constructor?'
363  if(!finest_) {
364  // we have no levels at all...
365  assert(!coarsest_);
366  // allocate into the shared_ptr
367  originalFinest_ = ConstructionTraits<MemberType>::construct(args);
368  finest_ = std::allocate_shared<Element>(allocator_);
369  finest_->element = originalFinest_;
370  coarsest_ = finest_;
371  }else{
372  finest_->finer_ = std::allocate_shared<Element>(allocator_);
373  finest_->finer_->coarser_ = finest_;
374  finest_ = finest_->finer_;
375  finest_->element = ConstructionTraits<T>::construct(args);
376  }
377  ++levels_;
378  }
379 
380  template<class T, class A>
382  {
383  return Iterator(finest_);
384  }
385 
386  template<class T, class A>
388  {
389  return Iterator(coarsest_);
390  }
391 
392  template<class T, class A>
394  {
395  return ConstIterator(finest_);
396  }
397 
398  template<class T, class A>
400  {
401  return ConstIterator(coarsest_);
402  }
404  } // namespace Amg
405 } // namespace Dune
406 
407 #endif
const void * Arguments
A type holding all the arguments needed to call the constructor.
Definition: construction.hh:44
A hierarchy of containers (e.g. matrices or vectors)
Definition: hierarchy.hh:39
Helper classes for the construction of classes without empty constructor.
typename std::allocator_traits< A >::template rebind_alloc< Element > Allocator
The allocator to use for the list elements.
Definition: hierarchy.hh:76
void addRedistributed(std::shared_ptr< T1 > t)
Definition: hierarchy.hh:205
ConstructionTraits< T >::Arguments Arguments
Definition: hierarchy.hh:78
LevelIterator & operator=(const LevelIterator< C_, T1_ > &other)
Definition: hierarchy.hh:145
T1 & dereference() const
Dereference the iterator.
Definition: hierarchy.hh:170
STL namespace.
bool equals(const LevelIterator< const typename std::remove_const< C >::type, const typename std::remove_const< T1 >::type > &other) const
Equality check.
Definition: hierarchy.hh:163
LevelIterator(const LevelIterator< C_, T1_ > &other)
Copy constructor.
Definition: hierarchy.hh:138
Traits class for generically constructing non default constructable types.
Definition: novlpschwarz.hh:257
T MemberType
The type of the container we store.
Definition: hierarchy.hh:45
LevelIterator()=default
Constructor.
std::size_t levels() const
Get the number of levels in the hierarchy.
Definition: hierarchy.hh:326
LevelIterator< Hierarchy< T, A >, T > Iterator
Type of the mutable iterator.
Definition: hierarchy.hh:220
Iterator finest()
Get an iterator positioned at the finest level.
Definition: hierarchy.hh:381
void decrement()
Move to the next fine level.
Definition: hierarchy.hh:182
bool isRedistributed() const
Check whether there was a redistribution at the current level.
Definition: hierarchy.hh:191
Iterator coarsest()
Get an iterator positioned at the coarsest level.
Definition: hierarchy.hh:387
void deleteRedistributed()
Definition: hierarchy.hh:210
LevelIterator< const Hierarchy< T, A >, const T > ConstIterator
Type of the const iterator.
Definition: hierarchy.hh:223
void increment()
Move to the next coarser level.
Definition: hierarchy.hh:176
Hierarchy()
Construct an empty hierarchy.
Definition: hierarchy.hh:89
Iterator over the levels in the hierarchy.
Definition: hierarchy.hh:48
void addCoarser(Arguments &args)
Add an element on a coarser level.
Definition: hierarchy.hh:338
bool equals(const LevelIterator< typename std::remove_const< C >::type, typename std::remove_const< T1 >::type > &other) const
Equality check.
Definition: hierarchy.hh:154
T1 & getRedistributed() const
Get the redistributed container.
Definition: hierarchy.hh:200
void addRedistributedOnCoarsest(Arguments &args)
Definition: hierarchy.hh:332
Definition: allocator.hh:11
void addFiner(Arguments &args)
Add an element on a finer level.
Definition: hierarchy.hh:360