AMDiS  0.3
The Adaptive Multi-Dimensional Simulation Toolbox
Traversal.hpp
1 #pragma once
2 
3 #include <dune/common/version.hh>
4 #include <dune/common/rangeutilities.hh>
5 #include <dune/common/std/type_traits.hh>
6 
7 #include <dune/typetree/nodetags.hh>
8 #include <dune/typetree/treepath.hh>
9 
10 #include <amdis/common/ForEach.hpp>
11 #include <amdis/common/TypeTraits.hpp>
12 
13 // NOTE: backport of dune/typetree/traversal.hh from Dune 2.7
14 
15 namespace AMDiS {
16 namespace Traversal {
17 
18  template <class Tree>
19  using HasDynamicChildAccess = decltype(std::declval<Tree>().child(0u));
20 
21 
26 template <class Tree, class TreePath, class Pre, class Leaf, class Post>
27 void forEachNode(Tree&& tree, TreePath treePath, Pre&& preFunc, Leaf&& leafFunc, Post&& postFunc)
28 {
29  using TreeType = std::decay_t<Tree>;
30  if constexpr (TreeType::isLeaf) {
31  // For leaf nodes just visit using the leaf function.
32  leafFunc(tree, treePath);
33  } else {
34  preFunc(tree, treePath);
35  if constexpr(Dune::Std::is_detected_v<HasDynamicChildAccess,TreeType>) {
36  // Specialization for dynamic traversal
37  for (std::size_t i = 0; i < tree.degree(); ++i) {
38  auto childTreePath = Dune::TypeTree::push_back(treePath, i);
39  forEachNode(tree.child(i), childTreePath, preFunc, leafFunc, postFunc);
40  }
41  } else {
42  // Specialization for static traversal
43  const auto indices = std::make_index_sequence<std::size_t(TreeType::degree())>{};
44  Ranges::forIndices(indices, [&](auto i) {
45  auto childTreePath = Dune::TypeTree::push_back(treePath, i);
46  forEachNode(tree.child(i), childTreePath, preFunc, leafFunc, postFunc);
47  });
48  }
49  postFunc(tree, treePath);
50  }
51 }
52 
53 
55 
64 template <class Tree, class Pre, class Leaf, class Post>
65 void forEachNode(Tree&& tree, Pre&& preFunc, Leaf&& leafFunc, Post&& postFunc)
66 {
67  auto root = Dune::TypeTree::hybridTreePath();
68  forEachNode(tree, root, preFunc, leafFunc, postFunc);
69 }
70 
72 
80 template <class Tree, class Inner, class Leaf>
81 void forEachNode(Tree&& tree, Inner&& innerFunc, Leaf&& leafFunc)
82 {
83  auto root = Dune::TypeTree::hybridTreePath();
84  forEachNode(tree, root, innerFunc, leafFunc, NoOp{});
85 }
86 
88 
95 template <class Tree, class NodeFunc>
96 void forEachNode(Tree&& tree, NodeFunc&& nodeFunc)
97 {
98  auto root = Dune::TypeTree::hybridTreePath();
99  forEachNode(tree, root, nodeFunc, nodeFunc, NoOp{});
100 }
101 
103 
110 template <class Tree, class Leaf>
111 void forEachLeafNode(Tree&& tree, Leaf&& leafFunc)
112 {
113  auto root = Dune::TypeTree::hybridTreePath();
114  forEachNode(tree, root, NoOp{}, leafFunc, NoOp{});
115 }
116 
117 }} // end namespace AMDiS::Traversal
Definition: AdaptBase.hpp:6