Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
shapefunctioncache.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE-FUFEM Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef DUNE_FUFEM_FORMS_SHAPEFUNCTIONCACHE_HH
8#define DUNE_FUFEM_FORMS_SHAPEFUNCTIONCACHE_HH
9
10#include <type_traits>
11#include <utility>
12#include <list>
13#include <any>
14#include <typeindex>
15
19
20#if DUNE_VERSION_GTE(DUNE_FUNCTIONS, 2, 11)
22#else
23#include <dune/typetree/treepath.hh>
24#endif
25
29
30
31namespace Dune::Fufem::Forms::Impl {
32
33 template<class C, class... T>
34 static constexpr decltype(auto) accessByTreePath(C&& container, const Dune::Fufem::Impl::TreePath<T...>& path)
35 {
36 if constexpr (sizeof...(T)==0)
37 return container;
38 else
39 return accessByTreePath(container[path.front()], pop_front(path));
40 }
41
42 template<class ReferenceJacobian, class GeometryJacobianInverse>
43 struct GlobalJacobianTraits
44 {
45 using GeometryField = typename GeometryJacobianInverse::field_type;
46 using ReferenceJacobianField = typename ReferenceJacobian::field_type;
48 static constexpr int dimWorld = GeometryJacobianInverse::cols;
50 };
51
52 template<class GeometryJacobianInverse, class JF, int dimRange, int dim>
53 struct GlobalJacobianTraits<Dune::FieldMatrix<JF, dimRange, dim>, GeometryJacobianInverse>
54 {
55 using GeometryField = typename GeometryJacobianInverse::field_type;
56 using ReferenceJacobianField = JF;
58 static constexpr int dimWorld = GeometryJacobianInverse::cols;
60 };
61
62
63
64} // end namespace Dune::Fufem::Forms::Impl
65
66
67
68namespace Dune::Fufem::Forms {
69
70
71
106 template<class Node, class CT=double, class Dummy=void>
108
109
110
111 template<class Node, class CT>
112 class ShapeFunctionCache<Node, CT, std::enable_if_t<
113 Dune::Fufem::Impl::Concept::LeafTreeNode<Node>
114 >>
115 {
116 using GeometryJacobianInverse = typename Node::Element::Geometry::JacobianInverse;
117 public:
118
120
121 using FEValue = typename Node::FiniteElement::Traits::LocalBasisType::Traits::RangeType;
122 using FEJacobian = typename Node::FiniteElement::Traits::LocalBasisType::Traits::JacobianType;
123 using FEGlobalJacobian = typename Impl::GlobalJacobianTraits<FEJacobian, GeometryJacobianInverse>::type;
124
125 using ValueCache = typename std::vector<std::vector<FEValue>>;
126 using JacobianCache = typename std::vector<std::vector<FEJacobian>>;
127 using GlobalJacobianCache = typename std::vector<std::vector<FEGlobalJacobian>>;
128
129 ShapeFunctionCache(const QuadratureRule& rule, const Node& node)
130 {
131 setRule(rule);
132 setTree(node);
133 }
134
136 node_(nullptr)
137 {
138 setRule(rule);
139 }
140
141 ShapeFunctionCache(const Node& node) :
142 rule_(nullptr)
143 {
144 setTree(node);
145 }
146
147 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
148
149 ShapeFunctionCache() = default;
150
151 void setRule(const QuadratureRule& rule)
152 {
153 rule_ = &rule;
154 valueCache_.resize(rule_->size());
155 jacobianCache_.resize(rule_->size());
156 globalJacobianCache_.resize(rule_->size());
157 valueCache_[0].clear();
158 jacobianCache_[0].clear();
159 globalJacobianCache_[0].clear();
160 }
161
162 void setTree(const Node& node)
163 {
164 node_ = &node;
165 }
166
167 void setNonAffine()
168 {
169 isNonAffine_ = true;
170 }
171
172 const QuadratureRule& rule() const
173 {
174 return *rule_;
175 }
176
177 void invalidate()
178 {
179 // We use the size at the first quadrature point to indicate
180 // an invalidated cache. To this end we set it's size to zero.
181 if (isNonAffine_)
182 {
183 valueCache_[0].clear();
184 jacobianCache_[0].clear();
185 }
186 globalJacobianCache_[0].clear();
187 }
188
189 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<>& treePath) const
190 {
191 return *this;
192 }
193
194 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<>& treePath)
195 {
196 return *this;
197 }
198
199 const auto& getValues()
200 {
201 if (valueCache_[0].empty())
202 {
203 if (node_->size() == 0)
204 return valueCache_;
205 const auto& localBasis = node_->finiteElement().localBasis();
206 for(std::size_t k=0; k<rule_->size(); ++k)
207 localBasis.evaluateFunction((*rule_)[k].position(), valueCache_[k]);
208 }
209 return valueCache_;
210 }
211
212 const auto& getJacobians()
213 {
214 if (jacobianCache_[0].empty())
215 {
216 if (node_->size() == 0)
217 return jacobianCache_;
218 const auto& localBasis = node_->finiteElement().localBasis();
219 for(std::size_t k=0; k<rule_->size(); ++k)
220 localBasis.evaluateJacobian((*rule_)[k].position(), jacobianCache_[k]);
221 }
222 return jacobianCache_;
223 }
224
225 const auto& getGlobalJacobians()
226 {
227 if (globalJacobianCache_[0].empty())
228 {
229 if (node_->size() == 0)
230 return globalJacobianCache_;
231 const auto& geometry = node_->element().geometry();
232 const auto& jacobians = getJacobians();
233 for(std::size_t k=0; k<rule_->size(); ++k)
234 {
235 globalJacobianCache_[k].resize(jacobians[k].size());
236 const auto& jacobianInverse = geometry.jacobianInverse((*rule_)[k].position());
237 for(std::size_t i=0; i<jacobians[k].size(); ++i)
238 globalJacobianCache_[k][i] = jacobians[k][i] * jacobianInverse;
239 }
240 }
241 return globalJacobianCache_;
242 }
243
244 private:
245 const QuadratureRule* rule_ = nullptr;
246 const Node* node_ = nullptr;
247 ValueCache valueCache_;
248 JacobianCache jacobianCache_;
249 GlobalJacobianCache globalJacobianCache_;
250 bool isNonAffine_ = false;
251 };
252
253
254
255 template<class Node, class CT>
256 class ShapeFunctionCache<Node, CT, std::enable_if_t<
257 Dune::Fufem::Impl::Concept::UniformInnerTreeNode<Node>
258 >>
259 {
260 using ChildNode = Dune::TypeTree::Child<Node,0>;
261 using ChildCache = ShapeFunctionCache<ChildNode, CT>;
262 public:
263
265
266 ShapeFunctionCache(const QuadratureRule& rule, const Node& node) :
267 childCache_(rule, node.child(0))
268 {}
269
270 ShapeFunctionCache(const QuadratureRule& rule) :
271 childCache_(rule)
272 {}
273
274 ShapeFunctionCache(const Node& node) :
275 childCache_(node.child(0))
276 {}
277
278 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
279
280 ShapeFunctionCache() = default;
281
282 void setRule(const QuadratureRule& rule)
283 {
284 childCache_.setRule(rule);
285 }
286
287 void setTree(const Node& node)
288 {
289 childCache_.setTree(node.child(0));
290 }
291
292 void setNonAffine()
293 {
294 childCache_.setNonAffine();
295 }
296
297 const QuadratureRule& rule() const
298 {
299 return childCache_.rule();
300 }
301
302 void invalidate()
303 {
304 childCache_.invalidate();
305 }
306
307 const ChildCache& operator[](std::size_t i) const
308 {
309 assert(i<Node::degree());
310 return childCache_;
311 }
312
313 ChildCache& operator[](std::size_t i)
314 {
315 assert(i<Node::degree());
316 return childCache_;
317 }
318
319 template<class... T>
320 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath) const
321 {
322 return Impl::accessByTreePath(*this, treePath);
323 }
324
325 template<class... T>
326 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath)
327 {
328 return Impl::accessByTreePath(*this, treePath);
329 }
330
331 constexpr std::size_t size() const noexcept
332 {
333 return Node::degree();
334 }
335
336 private:
337 ChildCache childCache_;
338 };
339
340
341
342 namespace Impl {
343
344 template<class List, class CT>
345 struct TupleVectorOfShapeFunctionCaches
346 {};
347
348 template<class CT, template<class...> class ListType, class... Args>
349 struct TupleVectorOfShapeFunctionCaches<ListType<Args...>, CT>
350 {
352 };
353
354 template<class List, class CT>
355 using TupleVectorOfShapeFunctionCaches_t = typename TupleVectorOfShapeFunctionCaches<List, CT>::type;
356
357 } // end namespace Imp
358
359
360
361 template<class Node, class CT>
362 class ShapeFunctionCache<Node, CT, std::enable_if_t<
363 Dune::Fufem::Impl::Concept::StaticDegreeInnerTreeNode<Node>
364 and not Dune::Fufem::Impl::Concept::UniformInnerTreeNode<Node>
365 >>
366 : public Impl::TupleVectorOfShapeFunctionCaches_t<Dune::Fufem::Impl::Children<Node>, CT>
367 {
368 using Base = Impl::TupleVectorOfShapeFunctionCaches_t<Dune::Fufem::Impl::Children<Node>, CT>;
369 public:
370
372
373 ShapeFunctionCache(const QuadratureRule& rule, const Node& node)
374 {
375 setRule(rule);
376 setTree(node);
377 }
378
379 ShapeFunctionCache(const QuadratureRule& rule)
380 {
381 setRule(rule);
382 }
383
384 ShapeFunctionCache(const Node& node)
385 {
386 setTree(node);
387 }
388
389
390 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
391
392 ShapeFunctionCache() = default;
393
394 void setRule(const QuadratureRule& rule)
395 {
396 Hybrid::forEach(*this, [&](auto& childCache) {
397 childCache.setRule(rule);
398 });
399 }
400
401 void setTree(const Node& node)
402 {
403 Hybrid::forEach(Dune::range(Node::degree()), [&](const auto& i){
404 (*this)[i].setTree(node.child(i));
405 });
406 }
407
408 void setNonAffine()
409 {
410 Hybrid::forEach(Dune::range(Node::degree()), [&](const auto& i){
411 (*this)[i].setNonAffine();
412 });
413 }
414
415 const QuadratureRule& rule() const
416 {
417 return (*this)[Dune::Indices::_0].rule();
418 }
419
420 using Base::operator[];
421
422 template<class... T>
423 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath) const
424 {
425 return Impl::accessByTreePath(*this, treePath);
426 }
427
428 template<class... T>
429 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath)
430 {
431 return Impl::accessByTreePath(*this, treePath);
432 }
433
434 void invalidate() {
435 Hybrid::forEach(*this, [&](auto& childCache) {
436 childCache.invalidate();
437 });
438 }
439
440 };
441
442
443
465 template<class C>
467 {
468 using Cache = C;
469 using CT = typename Cache::QuadratureRule::CoordType;
470 constexpr static int dimension = Cache::QuadratureRule::d;
471
474
475 public:
476
479
480 private:
481
482 template<class Key>
483 const QuadratureRule& getRule(const Key& key)
484 {
487 else
488 {
489 auto facet = key.second;
490 auto&& type = key.first.geometryType();
491 auto facetGeometryType = Dune::referenceElement<CT,dimension>(type).type(facet, 1);
492 auto facetQuadratureRuleKey = key.first;
493 facetQuadratureRuleKey.setGeometryType(facetGeometryType);
494 const auto& rule = QuadratureRuleCache<CT, dimension-1>::rule(facetQuadratureRuleKey);
495 // We need to store the face quadrature rule.
496 // By using an std::list, we can store pointers
497 // to the stored rules, because they never get invalidated.
498 facetQuadratureRules_.push_back(FacetQuadratureRule(type, facet, rule));
499 return facetQuadratureRules_.back();
500 }
501 }
502
503 template<class Key>
504 Cache makeCache(const Key& key)
505 {
506 auto cache = Cache(prototype_);
507 cache.setRule(getRule(key));
508 return cache;
509 }
510
511 public:
512
513 Cache& operator[](const QuadratureRuleKey& key) {
514 auto it = elementCacheMap_.find(key);
515 if (it == elementCacheMap_.end())
516 return (elementCacheMap_.insert(std::make_pair(key, makeCache(key)))).first->second;
517 else
518 return it->second;
519 }
520
521 Cache& operator[](const FacetKey& facetKey) {
522 auto it = facetCacheMap_.find(facetKey);
523 if (it == facetCacheMap_.end())
524 return (facetCacheMap_.insert(std::make_pair(facetKey, makeCache(facetKey)))).first->second;
525 else
526 return it->second;
527 }
528
529 Cache& prototype()
530 {
531 return prototype_;
532 }
533
534 void clear()
535 {
536 prototype_.clear();
537 elementCacheMap_.clear();
538 facetCacheMap_.clear();
539 facetQuadratureRules_.clear();
540 }
541
542 private:
543 std::map<ElementKey, Cache> elementCacheMap_;
544 std::map<FacetKey, Cache> facetCacheMap_;
545 Cache prototype_;
546 std::list<FacetQuadratureRule> facetQuadratureRules_;
547 };
548
549
550
568 class UniqueCacheId : public std::pair<const void*, std::type_index>
569 {
571 public:
572
573 template<class T>
574 UniqueCacheId(const T& t) :
575 Base(&t, std::type_index(typeid(T)))
576 {}
577 };
578
613 template<class CT, int dimension>
615 {
616 public:
619
620 private:
621
622 // Simple type erasure for stored caches.
623 class TypeErasedCache
624 {
625 struct {
626 std::any impl_;
627 void*(*toRawPtr_)(std::any&);
628 void(*invalidate_)(void*);
629 void(*setRule_)(void*, const QuadratureRule&);
630 } members_;
631 void* rawPtr_;
632
633 void* toRawPtr()
634 {
635 return members_.toRawPtr_(members_.impl_);
636 }
637
638 public:
639
640 template<class Impl>
641 TypeErasedCache(Impl&& impl)
642 : members_{
643 std::move(impl),
644 [](std::any& impl) -> void* { return &std::any_cast<Impl&>(impl); },
645 [](void* impl) { static_cast<Impl*>(impl)->invalidate(); },
646 [](void* impl, const QuadratureRule& rule) { static_cast<Impl*>(impl)->setRule(rule); },
647 }
648 , rawPtr_(toRawPtr())
649 {}
650
651 TypeErasedCache(TypeErasedCache&& other)
652 : members_(std::move(other.members_))
653 , rawPtr_(toRawPtr())
654 {}
655
656 TypeErasedCache(const TypeErasedCache& other)
657 : members_(other.members_)
658 , rawPtr_(toRawPtr())
659 {}
660
661 TypeErasedCache(TypeErasedCache& other)
662 : members_(other.members_)
663 , rawPtr_(toRawPtr())
664 {}
665
666 void invalidate()
667 {
668 members_.invalidate_(rawPtr_);
669 }
670
671 void setRule(const QuadratureRule& rule)
672 {
673 members_.setRule_(rawPtr_, rule);
674 }
675
676 template<class Impl>
677 Impl& get()
678 {
679 return *static_cast<Impl*>(rawPtr_);
680 }
681 };
682
683 const QuadratureRule* rule_ = nullptr;
686
687 public:
688
689 CacheManager() = default;
690 CacheManager(CacheManager&& other) = default;
691 CacheManager(const CacheManager& other) = default;
692
695
699 void clear()
700 {
701 rule_ = nullptr;
702 cacheIndex_.clear();
703 caches_.clear();
704 }
705
709 const QuadratureRule& rule() const
710 {
711 return *rule_;
712 }
713
718 {
719 rule_ = &rule;
720 for(auto index : Dune::range(caches_.size()))
721 caches_[index].setRule(rule);
722 }
723
728 {
729 for(auto index : Dune::range(caches_.size()))
730 caches_[index].invalidate();
731 }
732
733 // For diagnostics: Print number of stored caches
734 void report() const
735 {
736 std::cout << "Number of managed caches " << caches_.size() << std::endl;
737 }
738
752 template<class Cache>
753 size_type registerCache(UniqueCacheId uniqueCacheId, Cache&& cache)
754 {
755 auto it = cacheIndex_.find(uniqueCacheId);
756 if (it == cacheIndex_.end())
757 {
758 caches_.push_back(std::forward<Cache>(cache));
759 cacheIndex_[uniqueCacheId] = caches_.size()-1;
760 return caches_.size()-1;
761 }
762 else
763 return it->second;
764 }
765
776 template<class Cache>
778 {
779 return caches_[index].template get<Cache>();
780 }
781
782 };
783
784
785
791 template<class CT, int dimension>
793
794
795
806 template<class CT, int dimension, class V>
808 {
809 public:
810
812
813 using Value = V;
815
816 SimpleCache(bool isNonAffine) :
817 isNonAffine_(isNonAffine)
818 {}
819
820 SimpleCache(const SimpleCache& other) = default;
821
823 {
824 rule_ = &rule;
825 valueCache_.resize(rule_->size());
826 isEmpty_ = true;
827 }
828
829 const QuadratureRule& rule() const
830 {
831 return *rule_;
832 }
833
835 {
836 isNonAffine_ = true;
837 }
838
840 {
841 if (isNonAffine_)
842 isEmpty_ = true;
843 }
844
845 bool isEmpty()
846 {
847 return isEmpty_;
848 }
849
850 void setEmpty(bool isEmpty)
851 {
852 isEmpty_ = isEmpty;
853 }
854
855 auto& getValues()
856 {
857 return valueCache_;
858 }
859
860 const auto& getValues() const
861 {
862 return valueCache_;
863 }
864
865 private:
866 const QuadratureRule* rule_ = nullptr;
867 ValueCache valueCache_;
868 bool isEmpty_ = true;
869 bool isNonAffine_ = false;
870 };
871
872
873
874} // namespace Dune::Fufem::Forms
875
876
877#endif // DUNE_FUFEM_FORMS_SHAPEFUNCTIONCACHE_HH
878
void invalidate()
This header provides fallback implementations for dune-typetree<2.11.
reference operator[](size_type i)
int size() const
bool empty() const
void pop_front()
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
constexpr void forEach(Range &&range, F &&f)
std::ptrdiff_t index() const
decltype(auto) child(Node &&node, TreePath< Indices... > treePath)
typename Impl::ChildTraits< Node, indices... >::type Child
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
constexpr index_constant< 0 > _0
STL namespace.
Definition baseclass.hh:22
decltype(std::declval< T1 >()+std::declval< T2 >()) PromotedType
A hierarchic cache for storing shape function evaluations for a tree.
Definition shapefunctioncache.hh:107
A cache providing multiple versions for different quadrature rules.
Definition shapefunctioncache.hh:467
Cache & operator[](const QuadratureRuleKey &key)
Definition shapefunctioncache.hh:513
Cache & operator[](const FacetKey &facetKey)
Definition shapefunctioncache.hh:521
void clear()
Definition shapefunctioncache.hh:534
Cache & prototype()
Definition shapefunctioncache.hh:529
Objects of this class are used to uniquely identifies a cache.
Definition shapefunctioncache.hh:569
UniqueCacheId(const T &t)
Definition shapefunctioncache.hh:574
A class for managing caches of different types.
Definition shapefunctioncache.hh:615
auto & getCache(size_type index)
Obtain a registered cache.
Definition shapefunctioncache.hh:777
CacheManager(const CacheManager &other)=default
void invalidate()
Invalidate all stores caches.
Definition shapefunctioncache.hh:727
CacheManager & operator=(const CacheManager &)=delete
size_type registerCache(UniqueCacheId uniqueCacheId, Cache &&cache)
Register a new cache.
Definition shapefunctioncache.hh:753
void report() const
Definition shapefunctioncache.hh:734
void setRule(const QuadratureRule &rule)
Set the associated quadrature rule for all stored caches.
Definition shapefunctioncache.hh:717
CacheManager(CacheManager &&other)=default
const QuadratureRule & rule() const
Obtain the associated quadrature rule.
Definition shapefunctioncache.hh:709
void clear()
Clear all stored data.
Definition shapefunctioncache.hh:699
A simple cache implementation storing values.
Definition shapefunctioncache.hh:808
auto & getValues()
Definition shapefunctioncache.hh:855
SimpleCache(bool isNonAffine)
Definition shapefunctioncache.hh:816
bool isEmpty()
Definition shapefunctioncache.hh:845
void setEmpty(bool isEmpty)
Definition shapefunctioncache.hh:850
V Value
Definition shapefunctioncache.hh:813
void invalidate()
Definition shapefunctioncache.hh:839
void setNonAffine()
Definition shapefunctioncache.hh:834
const QuadratureRule & rule() const
Definition shapefunctioncache.hh:829
void setRule(const QuadratureRule &rule)
Definition shapefunctioncache.hh:822
SimpleCache(const SimpleCache &other)=default
const auto & getValues() const
Definition shapefunctioncache.hh:860
typename std::vector< Value > ValueCache
Definition shapefunctioncache.hh:814
A token that specifies a quadrature rule.
Definition quadraturerulecache.hh:39
Definition quadraturerulecache.hh:190
static const Dune::QuadratureRule< coord_type, dim > & rule(const Dune::GeometryType &gt, const int order, int refinement)
Definition quadraturerulecache.hh:196
Quadrature rule for a subentity of some given geometry type.
Definition subentityquadraturerule.hh:31
T clear(T... args)
T end(T... args)
T endl(T... args)
T find(T... args)
T forward(T... args)
T make_pair(T... args)
T push_back(T... args)
T size(T... args)