AMDiS 2.10
The Adaptive Multi-Dimensional Simulation Toolbox
NodeCache.hpp
1#pragma once
2
3#include <memory>
4#include <tuple>
5#include <vector>
6
7#include <dune/common/ftraits.hh>
8#include <dune/common/hash.hh>
9#include <dune/common/indices.hh>
10
11#include <dune/geometry/type.hh>
12
13#include <dune/typetree/leafnode.hh>
14#include <dune/typetree/powernode.hh>
15#include <dune/typetree/compositenode.hh>
16
17#include <amdis/common/ConcurrentCache.hpp>
18
19namespace AMDiS
20{
21 namespace Impl
22 {
23 template <class Node, class NodeTag = typename Node::NodeTag>
24 struct NodeCacheFactory;
25
26 } // end namespace Impl
27
28
30 template <class Node>
31 using NodeCache_t = typename Impl::NodeCacheFactory<Node>::type;
32
34 template <class Node>
35 auto makeNodeCache (Node const& node)
36 {
37 return NodeCache_t<Node>::create(node);
38 }
39
40
43 template <class NodeType>
45 {
46 public:
47 using Node = NodeType;
48 using Element = typename Node::Element;
49
50 public:
52 NodeWrapper (Node const& node)
53 : node_(&node)
54 {}
55
57 Node const& node () const
58 {
59 assert(node_ != nullptr);
60 return *node_;
61 }
62
64 Element const& element () const
65 {
66 return node_->element();
67 }
68
70 auto localIndex (std::size_t i) const
71 {
72 return node_->localIndex(i);
73 }
74
76 auto size () const
77 {
78 return node_->size();
79 }
80
82 auto treeIndex () const
83 {
84 return node_->treeIndex();
85 }
86
87 protected:
88 Node const* node_ = nullptr;
89 };
90
91
93
101 template <class Node>
103 : public Dune::TypeTree::LeafNode
104 , public NodeWrapper<Node>
105 {
106 public:
107 using BasisNode = Node;
108
109 using FiniteElement = typename Node::FiniteElement;
110 using LocalBasis = typename FiniteElement::Traits::LocalBasisType;
111
112 using ShapeValues = std::vector<typename LocalBasis::Traits::RangeType>;
113 using ShapeGradients = std::vector<typename LocalBasis::Traits::JacobianType>;
114
115 private:
116 using DomainType = typename LocalBasis::Traits::DomainType;
117
118 // Pair of GeometryType and local coordinates
119 struct CoordKey
120 {
121 unsigned int id; // topologyId
122 DomainType local; // local coordinate
123
124 struct hasher
125 {
126 std::size_t operator()(CoordKey const& t) const
127 {
128 std::size_t seed = 0;
129 Dune::hash_combine(seed, t.id);
130 Dune::hash_range(seed, t.local.begin(), t.local.end());
131 return seed;
132 }
133 };
134
135 friend bool operator==(CoordKey const& lhs, CoordKey const& rhs)
136 {
137 return std::tie(lhs.id,lhs.local) == std::tie(rhs.id,rhs.local);
138 }
139 };
140
141 private:
142 // Constructor storing a reference to the passed basis-node
143 LeafNodeCache (Node const& basisNode)
144 : NodeWrapper<Node>(basisNode)
145 {}
146
147 public:
149 static LeafNodeCache create (Node const& basisNode)
150 {
151 return {basisNode};
152 }
153
155 FiniteElement const& finiteElement () const
156 {
157 return this->node_->finiteElement();
158 }
159
161 ShapeValues const& localBasisValuesAt (DomainType const& local) const
162 {
163 CoordKey key{this->element().type().id(), local};
164 return shapeValues_.get(key, [&](CoordKey const&)
165 {
166 ShapeValues data;
167 this->localBasis().evaluateFunction(local, data);
168 return data;
169 });
170 }
171
173 ShapeGradients const& localBasisJacobiansAt (DomainType const& local) const
174 {
175 CoordKey key{this->element().type().id(), local};
176 return shapeGradients_.get(key, [&](CoordKey const&)
177 {
178 ShapeGradients data;
179 this->localBasis().evaluateJacobian(local, data);
180 return data;
181 });
182 }
183
184 private:
186 LocalBasis const& localBasis () const
187 {
188 return this->node_->finiteElement().localBasis();
189 }
190
191 private:
192 template <class Value>
193 using CoordCache = ConcurrentCache<CoordKey, Value, ConsecutivePolicy,
194 std::unordered_map<CoordKey, Value, typename CoordKey::hasher>>;
195
196 CoordCache<ShapeValues> shapeValues_;
197 CoordCache<ShapeGradients> shapeGradients_;
198 };
199
200
201 template <class Node>
203 : public Impl::NodeCacheFactory<Node>::Base
204 , public NodeWrapper<Node>
205 {
206 using Self = PowerNodeCache;
207 using Super = typename Impl::NodeCacheFactory<Node>::Base;
208
209 private:
210 PowerNodeCache (Node const& basisNode)
211 : NodeWrapper<Node>(basisNode)
212 {}
213
214 public:
216 static auto create (Node const& basisNode)
217 {
218 Self cache{basisNode};
219 for (std::size_t i = 0; i < std::size_t(basisNode.degree()); ++i)
220 cache.setChild(i, Super::ChildType::create(basisNode.child(i)));
221 return cache;
222 }
223 };
224
225
226 template <class Node>
228 : public Impl::NodeCacheFactory<Node>::Base
229 , public NodeWrapper<Node>
230 {
231 using Self = CompositeNodeCache;
232 using Super = typename Impl::NodeCacheFactory<Node>::Base;
233
234 private:
235 CompositeNodeCache (Node const& basisNode)
236 : NodeWrapper<Node>(basisNode)
237 {}
238
239 public:
241 static auto create (Node const& basisNode)
242 {
243 using TT = typename Super::ChildTypes;
244 Self cache{basisNode};
245 Dune::Hybrid::forEach(std::make_index_sequence<std::size_t(Node::degree())>{}, [&](auto ii) {
246 cache.setChild(std::tuple_element_t<ii,TT>::create(basisNode.child(ii)), ii);
247 });
248 return cache;
249 }
250 };
251
252 namespace Impl
253 {
254 template <class Node>
255 struct NodeCacheFactory<Node, Dune::TypeTree::LeafNodeTag>
256 {
257 using Base = Dune::TypeTree::LeafNode;
258 using type = LeafNodeCache<Node>;
259 };
260
261 template <class Node>
262 struct NodeCacheFactory<Node, Dune::TypeTree::PowerNodeTag>
263 {
264 using Child = typename NodeCacheFactory<typename Node::ChildType>::type;
265 using Base = Dune::TypeTree::PowerNode<Child, std::size_t(Node::degree())>;
266 using type = PowerNodeCache<Node>;
267 };
268
269 template <class Node>
270 struct NodeCacheFactory<Node, Dune::TypeTree::CompositeNodeTag>
271 {
272 template <class Indices> struct Childs;
273 template <std::size_t... i>
274 struct Childs<std::index_sequence<i...>> {
275 using type = Dune::TypeTree::CompositeNode<
276 typename NodeCacheFactory<typename Node::template Child<i>::type>::type...
277 >;
278 };
279
280 using Base = typename Childs<std::make_index_sequence<std::size_t(Node::degree())>>::type;
281 using type = CompositeNodeCache<Node>;
282 };
283
284 } // end namespace Impl
285
286} // end namespace AMDiS
Definition: NodeCache.hpp:230
static auto create(Node const &basisNode)
Construct a new composite node by setting each child individually.
Definition: NodeCache.hpp:241
Cache of LocalBasis evaluations and jacobians at local points.
Definition: NodeCache.hpp:105
static LeafNodeCache create(Node const &basisNode)
Construct a new local-basis cache.
Definition: NodeCache.hpp:149
FiniteElement const & finiteElement() const
Return the local finite-element of the stored basis-node.
Definition: NodeCache.hpp:155
ShapeValues const & localBasisValuesAt(DomainType const &local) const
Evaluate local basis functions at local coordinates.
Definition: NodeCache.hpp:161
ShapeGradients const & localBasisJacobiansAt(DomainType const &local) const
Evaluate local basis jacobians at local coordinates.
Definition: NodeCache.hpp:173
Wrapper around a basis-node storing just a pointer and providing some essential functionality like si...
Definition: NodeCache.hpp:45
NodeWrapper(Node const &node)
Store a reference to the node.
Definition: NodeCache.hpp:52
auto size() const
Return the size of the index-set of the node.
Definition: NodeCache.hpp:76
Node const & node() const
Return the stored basis-node.
Definition: NodeCache.hpp:57
Element const & element() const
Return the bound grid element.
Definition: NodeCache.hpp:64
auto localIndex(std::size_t i) const
Return the index of the i-th local basis function in the index-set of the whole tree.
Definition: NodeCache.hpp:70
auto treeIndex() const
Return a unique index within the tree.
Definition: NodeCache.hpp:82
Definition: NodeCache.hpp:205
static auto create(Node const &basisNode)
Construct a new power node by setting each child individually.
Definition: NodeCache.hpp:216
Definition: NodeCache.hpp:125