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