AMDiS  0.3
The Adaptive Multi-Dimensional Simulation Toolbox
Traversal.hpp
1 #pragma once
2 
3 #include <dune/common/rangeutilities.hh>
4 
5 #include <dune/typetree/nodetags.hh>
6 #include <dune/typetree/treepath.hh>
7 
8 #include <amdis/common/ForEach.hpp>
9 #include <amdis/common/TypeTraits.hpp>
10 
11 // NOTE: backport of dune/typetree/traversal.hh from Dune 2.7
12 
13 namespace AMDiS {
14 namespace Traversal {
15 namespace Impl_ {
16 
18 
27  template <bool dynamic = true, class Tree>
28  auto traversalDegree(Tree const& tree)
29  {
30  if constexpr (dynamic && Tree::isPower)
31  return std::size_t(tree.degree());
32  else if constexpr (Tree::isPower || Tree::isComposite)
33  return std::integral_constant<std::size_t, Tree::degree()>{};
34  else
35  return tree.degree();
36  }
37 
38 } // end namespace Impl_
39 
40 
45 template <class Tree, class TreePath, class Pre, class Leaf, class Post>
46 void forEachNode(Tree&& tree, TreePath treePath, Pre&& preFunc, Leaf&& leafFunc, Post&& postFunc)
47 {
48  using TreeType = std::decay_t<Tree>;
49  if constexpr (TreeType::isLeaf) {
50  // For leaf nodes just visit using the leaf function.
51  leafFunc(tree, treePath);
52  } else {
53  preFunc(tree, treePath);
54  const auto degree = Impl_::traversalDegree(tree);
55  if constexpr (std::is_integral_v<TYPEOF(degree)>) {
56  // Specialization for dynamic traversal
57  for (std::size_t i = 0; i < std::size_t(degree); ++i) {
58  auto childTreePath = Dune::TypeTree::push_back(treePath, i);
59  forEachNode(tree.child(i), childTreePath, preFunc, leafFunc, postFunc);
60  }
61  } else {
62  // Specialization for static traversal
63  const auto indices = std::make_index_sequence<VALUE(degree)>{};
64  Ranges::forIndices(indices, [&](auto i) {
65  auto childTreePath = Dune::TypeTree::push_back(treePath, i);
66  forEachNode(tree.child(i), childTreePath, preFunc, leafFunc, postFunc);
67  });
68  }
69  postFunc(tree, treePath);
70  }
71 }
72 
73 
75 
84 template <class Tree, class Pre, class Leaf, class Post>
85 void forEachNode(Tree&& tree, Pre&& preFunc, Leaf&& leafFunc, Post&& postFunc)
86 {
87  auto root = Dune::TypeTree::hybridTreePath();
88  forEachNode(tree, root, preFunc, leafFunc, postFunc);
89 }
90 
92 
100 template <class Tree, class Inner, class Leaf>
101 void forEachNode(Tree&& tree, Inner&& innerFunc, Leaf&& leafFunc)
102 {
103  auto root = Dune::TypeTree::hybridTreePath();
104  forEachNode(tree, root, innerFunc, leafFunc, NoOp{});
105 }
106 
108 
115 template <class Tree, class NodeFunc>
116 void forEachNode(Tree&& tree, NodeFunc&& nodeFunc)
117 {
118  auto root = Dune::TypeTree::hybridTreePath();
119  forEachNode(tree, root, nodeFunc, nodeFunc, NoOp{});
120 }
121 
123 
130 template <class Tree, class Leaf>
131 void forEachLeafNode(Tree&& tree, Leaf&& leafFunc)
132 {
133  auto root = Dune::TypeTree::hybridTreePath();
134  forEachNode(tree, root, NoOp{}, leafFunc, NoOp{});
135 }
136 
137 }} // end namespace AMDiS::Traversal
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6