AMDiS  0.1
The Adaptive Multi-Dimensional Simulation Toolbox
TreeContainer.hpp
1 #pragma once
2 
3 #include <array>
4 #include <functional>
5 #include <type_traits>
6 #include <utility>
7 
8 #include <dune/common/indices.hh>
9 #include <dune/common/tuplevector.hh>
10 
11 #include <dune/typetree/treepath.hh>
12 
13 #include <amdis/common/Apply.hpp>
14 #include <amdis/common/TypeTraits.hpp>
15 #include <amdis/typetree/TreePath.hpp>
16 
17 // NOTE: backport of dune/typetree/treecontainer.hh
18 
19 namespace AMDiS
20 {
23 
32  template <class Container>
34  {
35  using Self = TreeContainerStorage;
36 
37  template <class C>
38  static constexpr decltype(auto)
39  accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<> const&)
40  {
41  return container.value();
42  }
43 
44  template <class C, class... T>
45  static constexpr decltype(auto)
46  accessByTreePath(C&& container, Dune::TypeTree::HybridTreePath<T...> const& path)
47  {
48  auto head = Dune::TypeTree::treePathEntry(path,Dune::Indices::_0);
49  return accessByTreePath(container[head], pop_front(path));
50  }
51 
52  public:
55  : container_()
56  {}
57 
58  TreeContainerStorage(Container const& container)
59  : container_(container)
60  {}
61 
63  TreeContainerStorage(Container&& container)
64  : container_(std::move(container))
65  {}
66 
68  template <class... T>
69  decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path) const
70  {
71  return accessByTreePath(container_, path);
72  }
73 
75  template <class... T>
76  decltype(auto) operator[](Dune::TypeTree::HybridTreePath<T...> const& path)
77  {
78  return accessByTreePath(container_, path);
79  }
80 
82  Container const& data() const
83  {
84  return container_;
85  }
86 
88  Container& data()
89  {
90  return container_;
91  }
92 
94  bool operator==(TreeContainerStorage const& other) const
95  {
96  return container_ == other.container_;
97  }
98 
100  bool operator!=(TreeContainerStorage const& other) const
101  {
102  return container_ != other.container_;
103  }
104 
105  private:
106  Container container_;
107  };
108 
109 
110  namespace Impl
111  {
112  template <class Value, class Container>
113  class ValueAndContainer
114  {
115  public:
116  template <class V, class C>
117  ValueAndContainer(V&& value, C&& container)
118  : value_(FWD(value))
119  , container_(FWD(container))
120  {}
121 
122  ValueAndContainer()
123  : value_()
124  , container_()
125  {}
126 
127  template <class I>
128  auto& operator[](I const& i) { return container_[i]; }
129 
130  template <class I>
131  auto const& operator[](I const& i) const { return container_[i]; }
132 
133  Value& value() { return value_; }
134  Value const& value() const { return value_; }
135 
136  Container& container() { return container_; }
137  Container const& container() const { return container_; }
138 
139  bool operator==(ValueAndContainer const& other) const
140  {
141  return value_ == other.value_ && container_ == other.container_;
142  }
143 
144  private:
145  Value value_;
146  Container container_;
147  };
148 
149  template <class Value>
150  class ValueAndContainer<Value,void>
151  {
152  public:
153  template <class V, Dune::disableCopyMove<ValueAndContainer,V> = 0>
154  ValueAndContainer(V&& value)
155  : value_(FWD(value))
156  {}
157 
158  ValueAndContainer()
159  : value_()
160  {}
161 
162  Value& value() { return value_; }
163  Value const& value() const { return value_; }
164 
165  bool operator==(ValueAndContainer const& other) const
166  {
167  return value_ == other.value_;
168  }
169 
170  private:
171  Value value_;
172  };
173 
174  struct Ignore{};
175 
176  template <class Container>
177  class ValueAndContainer<Ignore,Container>
178  {
179  public:
180  template <class C>
181  ValueAndContainer(Ignore, C&& container)
182  : container_(FWD(container))
183  {}
184 
185  ValueAndContainer()
186  : container_()
187  {}
188 
189  template <class I>
190  auto& operator[](I const& i) { return container_[i]; }
191 
192  template <class I>
193  auto const& operator[](I const& i) const { return container_[i]; }
194 
195  Ignore value() { return {}; }
196  Ignore value() const { return {}; }
197 
198  Container& container() { return container_; }
199  Container const& container() const { return container_; }
200 
201  bool operator==(ValueAndContainer const& other) const
202  {
203  return container_ == other.container_;
204  }
205 
206  private:
207  Container container_;
208  };
209 
210 
211  template <class Value, class Container>
212  ValueAndContainer(Value const&, Container const&)
213  -> ValueAndContainer<Value,Container>;
214 
215  template <class Value>
216  ValueAndContainer(Value const&)
217  -> ValueAndContainer<Value,void>;
218 
219 
221 
231  template <class NodeToValue, bool leafOnly = false>
232  class ContainerFactory
233  {
234  public:
236 
241  ContainerFactory(NodeToValue nodeToValue)
242  : nodeToValue_(std::move(nodeToValue))
243  {}
244 
246  template <class Node>
247  auto operator()(Node const& node) const
248  {
249  if constexpr (Node::isLeaf)
250  return ValueAndContainer{value(node)};
251  else
252  if constexpr (Node::isPower) {
253  using TransformedChild = decltype((*this)(node.child(0)));
254  return ValueAndContainer{
255  value(node),
256  std::array<TransformedChild, Node::degree()>()};
257  }
258  else
259  if constexpr (Node::isComposite) {
260  return ValueAndContainer{
261  value(node),
262  Tools::apply_indices<Node::degree()>(
263  [&](auto... ii) { return Dune::makeTupleVector((*this)(node.child(ii))...); })};
264  }
265  else {
266  static_assert(Node::isLeaf || Node::isPower || Node::isComposite,
267  "Node must be one of leaf,power,composite.");
268  return;
269  }
270  }
271 
272  template <class Node>
273  decltype(auto) value(Node const& node) const
274  {
275  if constexpr(!Node::isLeaf && leafOnly)
276  return Ignore{};
277  else
278  return nodeToValue_(node);
279  }
280 
281  private:
282  NodeToValue nodeToValue_;
283  };
284 
285  } // end namespace Impl
286 
287 
289 
302  template <bool leafOnly = false, class Tree, class NodeToValue>
303  auto makeTreeContainer(Tree const& tree, NodeToValue&& nodeToValue)
304  {
305  auto f = std::ref(nodeToValue);
306  auto factory = Impl::ContainerFactory<decltype(f),leafOnly>(f);
307  return TreeContainerStorage{factory(tree)};
308  }
309 
310 
312 
326  template <class Value, bool leafOnly = false, class Tree>
327  auto makeTreeContainer(Tree const& tree)
328  {
329  return makeTreeContainer<leafOnly>(tree, [](auto&&) { return Value{}; });
330  }
331 
332  template <template<class> class NodeData, bool leafOnly = false, class Tree>
333  auto makeTreeContainer(Tree const& tree)
334  {
335  return makeTreeContainer<leafOnly>(tree, [](auto&& node) { return NodeData<TYPEOF(node)>{}; });
336  }
337 
340  template <class Value, class Tree, bool leafOnly = false>
342  = TYPEOF(makeTreeContainer<Value,leafOnly>(std::declval<const Tree&>()));
343 
346  template <class Value, class RowTree, class ColTree = RowTree, bool leafOnly = false>
347  using UniformTreeMatrix
349 
352  template <template <class Node> class NodeData, class Tree, bool leafOnly = false>
353  using TreeContainer
354  = TYPEOF(makeTreeContainer<NodeData,leafOnly>(std::declval<const Tree&>()));
355 
356 
357  namespace Impl
358  {
359  template <template <class,class> class NodeData, class Tree, bool leafOnly>
360  struct RowNodeData
361  {
362  template <class RowNode>
363  struct ColNodeData
364  {
365  template <class ColNode>
366  using type = NodeData<RowNode, ColNode>;
367  };
368 
369  template <class RowNode>
370  using type = TreeContainer<ColNodeData<RowNode>::template type, Tree, leafOnly>;
371  };
372 
373  } // end namespace Impl
374 
377  template <template <class,class> class NodeData, class RowTree, class ColTree = RowTree, bool leafOnly = false>
378  using TreeMatrix
380 
381 } //namespace AMDiS
Definition: AdaptiveGrid.hpp:373
Definition: FieldMatVec.hpp:12
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6
TreeContainer< Impl::RowNodeData< NodeData, ColTree, leafOnly >::template type, RowTree, leafOnly > TreeMatrix
Definition: TreeContainer.hpp:379
TreeContainerStorage()
Default-construct the tree-container.
Definition: TreeContainer.hpp:54
Container & data()
Obtain the container (mutable)
Definition: TreeContainer.hpp:88
TreeContainerStorage(Container &&container)
Construct the tree-container from a given container storage.
Definition: TreeContainer.hpp:63
auto makeTreeContainer(Tree const &tree, NodeToValue &&nodeToValue)
Create container having the same structure as the given tree.
Definition: TreeContainer.hpp:303
UniformTreeContainer< UniformTreeContainer< Value, ColTree, leafOnly >, RowTree, leafOnly > UniformTreeMatrix
Definition: TreeContainer.hpp:348
Vector data-structure with tree-path index access and hierarchic structure given by the Container tem...
Definition: TreeContainer.hpp:33
bool operator==(TreeContainerStorage const &other) const
Compare two containers for equality.
Definition: TreeContainer.hpp:94
bool operator!=(TreeContainerStorage const &other) const
Compare two containers for inequality.
Definition: TreeContainer.hpp:100
TYPEOF(makeTreeContainer< Value, leafOnly >(std::declval< const Tree & >())) UniformTreeContainer
Definition: TreeContainer.hpp:342
Container const & data() const
Obtain the container (const)
Definition: TreeContainer.hpp:82
TYPEOF(makeTreeContainer< NodeData, leafOnly >(std::declval< const Tree & >())) TreeContainer
Definition: TreeContainer.hpp:354
decltype(auto) operator[](Dune::TypeTree::HybridTreePath< T... > const &path) const
Access a (const) element of the container by treepath.
Definition: TreeContainer.hpp:69