AMDiS  0.3
The Adaptive Multi-Dimensional Simulation Toolbox
GlobalIdSet.hpp
1 #pragma once
2 
3 #include <tuple>
4 #include <utility>
5 #include <vector>
6 
7 #include <dune/common/exceptions.hh>
8 #include <dune/common/hybridutilities.hh>
9 #include <dune/common/version.hh>
10 #include <dune/functions/functionspacebases/nodes.hh>
11 #include <dune/functions/functionspacebases/lagrangebasis.hh>
12 #include <dune/grid/common/gridenums.hh>
13 #include <dune/localfunctions/common/localkey.hh>
14 
15 #include <amdis/Output.hpp>
16 #include <amdis/common/Apply.hpp>
17 #include <amdis/common/ConceptsBase.hpp>
18 #include <amdis/common/ForEach.hpp>
19 #include <amdis/common/TupleUtility.hpp>
20 #include <amdis/functions/Nodes.hpp>
21 #include <amdis/utility/Twist.hpp>
22 
23 namespace Dune
24 {
25  namespace Functions
26  {
27  // forward declarations...
28  template <class GV, int k, class MI>
29  class LagrangeDGPreBasis;
30 
31  template<typename GV, class MI, bool HI>
32  class TaylorHoodPreBasis;
33  }
34 }
35 
36 
37 namespace AMDiS
38 {
39  // forward declaration
40  template <class PreBasis, class TP, class NodeTag = typename Node_t<PreBasis,TP>::NodeTag>
41  class NodeIdSet;
42 
44 
48  template <class EntityIdType>
49  class GlobalIdType : public std::pair<EntityIdType, std::size_t>
50  {
51  using Super = std::pair<EntityIdType, std::size_t>;
52 
53  public:
54  GlobalIdType(std::size_t i = 0)
55  : Super(EntityIdType{}, i)
56  {}
57 
58  using Super::Super;
59 
62  {
63  ++this->second;
64  return *this;
65  }
66 
67  // Add to the second index only
68  GlobalIdType operator+(std::size_t shift) const
69  {
70  return GlobalIdType{this->first, this->second + shift};
71  }
72 
73  friend std::ostream& operator<<(std::ostream& os, GlobalIdType const& id)
74  {
75  os << "(" << id.first << "," << id.second << ")";
76  return os;
77  }
78  };
79 
80  template <class Basis>
81  using GlobalIdType_t
83 
84 
86 
106  template <class GB, class = std::void_t<> >
108  {
109  public:
110  using GlobalBasis = GB;
111  using Tree = typename GB::LocalView::Tree;
112  using size_type = std::size_t;
113 
114  using GridView = typename GlobalBasis::GridView;
115  using Grid = typename GridView::Grid;
116  using Element = typename GridView::template Codim<0>::Entity;
117  using EntityIdType = typename Grid::GlobalIdSet::IdType;
118  using PartitionType = Dune::PartitionType;
119  using IdType = GlobalIdType_t<GB>;
120 
121  using PreBasis = typename GlobalBasis::PreBasis;
122  using TreePath = typename GlobalBasis::PrefixPath;
125 
126  public:
127  GlobalBasisIdSet(GlobalBasis const& globalBasis)
128  : tree_(globalBasis.localView().tree())
129  , nodeIdSet_(globalBasis.gridView())
130  , twist_(globalBasis.gridView().grid().globalIdSet())
131  {
132  initializeTree(tree_);
133  }
134 
136 
141  void bind(Element const& element)
142  {
143  bindTree(tree_, element);
144  nodeIdSet_.bind(tree_);
145  twist_.bind(element);
146  data_.resize(size());
147  nodeIdSet_.fillIn(twist_, data_.begin());
148  }
149 
151  void unbind()
152  {
153  nodeIdSet_.unbind();
154  }
155 
157  size_type size() const
158  {
159  return tree_.size();
160  }
161 
164  IdType id(size_type i) const
165  {
166  assert( i < data_.size() );
167  return data_[i].first;
168  }
169 
172  EntityIdType entityId(size_type i) const
173  {
174  return id(i).first;
175  }
176 
179  PartitionType partitionType(size_type i) const
180  {
181  assert( i < data_.size() );
182  return data_[i].second;
183  }
184 
185  protected:
186  Tree tree_;
187  NodeIdSet nodeIdSet_;
188  Twist twist_;
189  using Data = std::pair<IdType, PartitionType>;
190  std::vector<Data> data_;
191  };
192 
193 
194  // Specialization for SubspaceBasis
195  template <class Basis>
196  class GlobalBasisIdSet<Basis, std::void_t<typename Basis::RootBasis>>
197  : public GlobalBasisIdSet<typename Basis::RootBasis>
198  {
199  public:
200  GlobalBasisIdSet(Basis const& basis)
202  {}
203  };
204 
205 
206  template <class PB, class TP, class NodeTag>
207  class NodeIdSet
208  {
209  public:
210  using PreBasis = PB;
211  using Node = Node_t<PreBasis,TP>;
212  using GridView = typename PreBasis::GridView;
213  using size_type = std::size_t;
214 
215  static_assert(Node::isLeaf, "Generic NodeIdSet implemented for LeafNodes only. Provide a specialization for your node!");
216 
217  private:
218  static constexpr int dim = GridView::template Codim<0>::Entity::mydimension;
219 
220  public:
221  NodeIdSet(GridView const& gridView)
222  : gridView_(gridView)
223  , sizes_{}
224  {}
225 
227  void bind(const Node& node)
228  {
229  node_ = &node;
230  size_ = node_->finiteElement().size();
231 
232  std::fill(std::begin(sizes_), std::end(sizes_), 0u);
233  for (size_type i = 0; i < size_ ; ++i) {
234  Dune::LocalKey const& localKey = node_->finiteElement().localCoefficients().localKey(i);
235  sizes_[localKey.codim()]++;
236  }
237  auto refElem = Dune::referenceElement<double,GridView::dimension>(node_->element().type());
238  for (size_type c = 0; c <= GridView::dimension ; ++c)
239  sizes_[c] /= refElem.size(c);
240  }
241 
243  void unbind()
244  {
245  node_ = nullptr;
246  }
247 
249  size_type size() const
250  {
251  return size_;
252  }
253 
255  template <class Twist, class It>
256  It fillIn(Twist const& twist, It it, size_type shift = 0) const
257  {
258  assert(node_ != nullptr);
259  const auto& gridIdSet = gridView_.grid().globalIdSet();
260 
261  for (size_type i = 0; i < size_ ; ++i, ++it) {
262  Dune::LocalKey localKey = node_->finiteElement().localCoefficients().localKey(i);
263  unsigned int s = localKey.subEntity();
264  unsigned int c = localKey.codim();
265  it->first = {gridIdSet.subId(node_->element(), s, c), shift + twist.get(localKey,sizes_[c])};
266 
267  it->second = Dune::Hybrid::switchCases(std::make_index_sequence<dim+1>{}, c,
268  [&](auto codim) { return node_->element().template subEntity<codim>(s).partitionType(); },
269  [&]() {
270  error_exit("Invalid codimension c = {}", c);
271  return Dune::PartitionType{};
272  });
273  }
274 
275  return it;
276  }
277 
278  protected:
279  GridView gridView_;
280  const Node* node_ = nullptr;
281  size_type size_ = 0;
282  std::array<unsigned int,GridView::dimension+1> sizes_;
283  };
284 
285 
286  // Specialization for PowerBasis
287  template <class PreBasis, class TP>
288  class NodeIdSet<PreBasis, TP, Dune::TypeTree::PowerNodeTag>
289  {
290  public:
291  using Node = Node_t<PreBasis,TP>;
292  using GridView = typename PreBasis::GridView;
293  using size_type = std::size_t;
294 
295  protected:
296  using SubPreBasis = typename PreBasis::SubPreBasis;
297  using SubTreePath = decltype(Dune::TypeTree::push_back(std::declval<TP>(), std::size_t(0)));
298  using SubNodeIdSet = NodeIdSet<SubPreBasis, SubTreePath>;
299  static const std::size_t children = Node::CHILDREN;
300 
301  public:
302  NodeIdSet(GridView const& gridView)
303  : subIds_(gridView)
304  {}
305 
307  void bind(const Node& node)
308  {
309  node_ = &node;
310  subIds_.bind(node.child(0));
311  }
312 
314  void unbind()
315  {
316  node_ = nullptr;
317  subIds_.unbind();
318  }
319 
321  size_type size() const
322  {
323  return node_->size();
324  }
325 
327  template <class Twist, class It>
328  It fillIn(Twist const& twist, It it, size_type shift = 0) const
329  {
330  assert(node_ != nullptr);
331  for (std::size_t child = 0; child < children; ++child)
332  {
333  size_type subTreeSize = subIds_.size();
334  it = subIds_.fillIn(twist, it, shift);
335  shift += subTreeSize;
336  }
337  return it;
338  }
339 
340  protected:
341  SubNodeIdSet subIds_;
342  const Node* node_ = nullptr;
343  };
344 
345 
346  // Specialization for CompositePreBasis
347  template <class PreBasis, class TP>
348  class NodeIdSet<PreBasis, TP, Dune::TypeTree::CompositeNodeTag>
349  {
350  public:
351  using Node = Node_t<PreBasis,TP>;
352  using GridView = typename PreBasis::GridView;
353  using size_type = std::size_t;
354 
355  protected:
356  static const std::size_t children = Node::CHILDREN;
357  using ChildIndices = std::make_index_sequence<children>;
358 
359  // The I'th SubPreBasis
360  template <std::size_t I>
361  using SubPreBasis = typename PreBasis::template SubPreBasis<I>;
362 
363  template <std::size_t I>
364  using SubTreePath = decltype(Dune::TypeTree::push_back(std::declval<TP>(), Dune::index_constant<I>{}));
365 
366  template <std::size_t I>
367  using SubNodeIdSet = NodeIdSet<SubPreBasis<I>, SubTreePath<I>>;
368 
369  // A tuple of NodeIdSets for the SubPreBases
370  using IdsTuple = IndexMapTuple_t<std::make_index_sequence<children>, SubNodeIdSet>;
371 
372  public:
373  NodeIdSet(GridView const& gridView)
374  : idsTuple_(Ranges::applyIndices<children>([&](auto... i) {
375  return std::make_tuple(SubNodeIdSet<VALUE(i)>(gridView)...);
376  }))
377  {}
378 
380  void bind(const Node& node)
381  {
382  node_ = &node;
383  Ranges::forIndices<0,children>([&](auto i) {
384  std::get<VALUE(i)>(idsTuple_).bind(node.child(i));
385  });
386  }
387 
389  void unbind()
390  {
391  node_ = nullptr;
392  Ranges::forEach(idsTuple_, [](auto& ids) {
393  ids.unbind();
394  });
395  }
396 
398  size_type size() const
399  {
400  return node_->size();
401  }
402 
404  template <class Twist, class It>
405  It fillIn(Twist const& twist, It it, size_type shift = 0) const
406  {
407  assert(node_ != nullptr);
408  Ranges::forEach(idsTuple_, [&](auto const& ids)
409  {
410  size_type subTreeSize = ids.size();
411  it = ids.fillIn(twist, it, shift);
412  shift += subTreeSize;
413  });
414  return it;
415  }
416 
417  private:
418  IdsTuple idsTuple_;
419  const Node* node_ = nullptr;
420  };
421 
422 
423  template <class GV, class MI, bool HI, class TP>
424  class NodeIdSet<Dune::Functions::TaylorHoodPreBasis<GV,MI,HI>, TP, Dune::TypeTree::CompositeNodeTag>
425  {
426  public:
427  using PreBasis = Dune::Functions::TaylorHoodPreBasis<GV,MI,HI>;
428  using Node = Node_t<PreBasis,TP>;
429  using GridView = typename PreBasis::GridView;
430  using size_type = std::size_t;
431 
432  private:
433  using PTP = decltype(Dune::TypeTree::push_back(std::declval<TP>(), Dune::index_constant<1>{}));
434  using VTP = decltype(Dune::TypeTree::push_back(std::declval<TP>(), Dune::index_constant<0>{}));
435  using V0TP = decltype(Dune::TypeTree::push_back(std::declval<VTP>(), std::size_t(0)));
436 
437  // Note: PreBasis::PQ1PreBasis is private
438  using PQ1PreBasis = typename NodeIndexSet_t<PreBasis,TP>::PQ1NodeIndexSet::PreBasis;
439  using PQ2PreBasis = typename NodeIndexSet_t<PreBasis,TP>::PQ2NodeIndexSet::PreBasis;
440 
441  using PQ1NodeIdSet = NodeIdSet<PQ1PreBasis, PTP>; // pressure
442  using PQ2NodeIdSet = NodeIdSet<PQ2PreBasis, V0TP>; // velocity
443 
444  private:
445  static constexpr int dow = GridView::dimensionworld;
446 
447  public:
448  NodeIdSet(GridView const& gridView)
449  : pq1NodeIdSet_(gridView)
450  , pq2NodeIdSet_(gridView)
451  {}
452 
454  void bind(const Node& node)
455  {
456  node_ = &node;
457  using namespace Dune::Indices;
458  pq1NodeIdSet_.bind(node.child(_1));
459  pq2NodeIdSet_.bind(node.child(_0, 0));
460  }
461 
463  void unbind()
464  {
465  pq1NodeIdSet_.unbind();
466  pq2NodeIdSet_.unbind();
467  node_ = nullptr;
468  }
469 
471  size_type size() const
472  {
473  return node_->size();
474  }
475 
477  template <class Twist, class It>
478  It fillIn(Twist const& twist, It it, size_type shift = 0) const
479  {
480  assert(node_ != nullptr);
481  for (int child = 0; child < dow; ++child) {
482  size_type subTreeSize = pq2NodeIdSet_.size();
483  it = pq2NodeIdSet_.fillIn(twist, it, shift);
484  shift += subTreeSize;
485  }
486  it = pq1NodeIdSet_.fillIn(twist, it, shift);
487  return it;
488  }
489 
490  protected:
491  PQ1NodeIdSet pq1NodeIdSet_;
492  PQ2NodeIdSet pq2NodeIdSet_;
493  const Node* node_ = nullptr;
494  };
495 
496 
497  template <class GV, int k, class MI, class TP>
498  class NodeIdSet<Dune::Functions::LagrangeDGPreBasis<GV, k, MI>, TP>
499  {
500  public:
501  using PreBasis = Dune::Functions::LagrangeDGPreBasis<GV, k, MI>;
502  using Node = Node_t<PreBasis, TP>;
503  using GridView = typename PreBasis::GridView;
504  using size_type = std::size_t;
505 
506  NodeIdSet(GridView const& gridView)
507  : gridView_(gridView)
508  {}
509 
511  void bind(const Node& node)
512  {
513  node_ = &node;
514  size_ = node_->finiteElement().size();
515  }
516 
518  void unbind()
519  {
520  node_ = nullptr;
521  }
522 
524  size_type size() const
525  {
526  return size_;
527  }
528 
530  template <class Twist, class It>
531  It fillIn(Twist const& /*twist*/, It it, size_type shift = 0) const
532  {
533  assert(node_ != nullptr);
534  const auto& gridIdSet = gridView_.grid().globalIdSet();
535  auto elementId = gridIdSet.id(node_->element());
536 
537  for (size_type i = 0; i < size_; ++i, ++it)
538  {
539  it->first = {elementId, shift + i};
540  it->second = node_->element().partitionType();
541  }
542 
543  return it;
544  }
545 
546  protected:
547  GridView gridView_;
548  const Node* node_ = nullptr;
549  size_type size_ = 0;
550  };
551 
552 
553 } // end namespace AMDiS
IdType id(size_type i) const
Return the global unique ID of the ith DOF on the currently bound element in the basis tree...
Definition: GlobalIdSet.hpp:164
unsigned int get(Dune::LocalKey const &localKey, unsigned int size) const
Get the permutated local dof index, living on a subEntity of the bound element.
Definition: Twist.hpp:48
Definition: AdaptiveGrid.hpp:373
Definition: FieldMatVec.hpp:12
Definition: GlobalIdSet.hpp:41
Provide global ids for all DOFs in a global basis.
Definition: GlobalIdSet.hpp:107
Definition: AdaptBase.hpp:6
Type of a global used used to represent DOFs uniquely.
Definition: GlobalIdSet.hpp:49
size_type size() const
The number of DOFs on the current element in the basis tree.
Definition: GlobalIdSet.hpp:157
void unbind()
Unbind the idset.
Definition: GlobalIdSet.hpp:243
PB PreBasis
Pre-basis providing the implementation details.
Definition: GlobalBasis.hpp:60
typename PreBasis::GridView GridView
The grid view that the FE space is defined on.
Definition: GlobalBasis.hpp:63
size_type size() const
Number of DOFs in this node.
Definition: GlobalIdSet.hpp:249
GlobalIdType & operator++()
Increment the second index only.
Definition: GlobalIdSet.hpp:61
void unbind()
unbind from the element
Definition: GlobalIdSet.hpp:151
PartitionType partitionType(size_type i) const
Return the partition type of the ith DOF on the currently bound element in the basis tree...
Definition: GlobalIdSet.hpp:179
It fillIn(Twist const &twist, It it, size_type shift=0) const
Maps from subtree index set [0..size-1] to a globally unique id in global basis.
Definition: GlobalIdSet.hpp:256
void bind(Element const &element)
Bind the IdSet to a grid element.
Definition: GlobalIdSet.hpp:141
void bind(const Node &node)
Bind the idset to a tree node.
Definition: GlobalIdSet.hpp:227
EntityIdType entityId(size_type i) const
Return the global unique ID of the entity associated to the ith DOF on the currently bound element in...
Definition: GlobalIdSet.hpp:172