Dune-Fufem 2.11
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
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>
108
109
110
111 template<class Node, class CT>
112 requires Dune::Fufem::Impl::Concept::LeafTreeNode<Node>
113 class ShapeFunctionCache<Node, CT>
114 {
115 using GeometryJacobianInverse = typename Node::Element::Geometry::JacobianInverse;
116 public:
117
119
120 using FEValue = typename Node::FiniteElement::Traits::LocalBasisType::Traits::RangeType;
121 using FEJacobian = typename Node::FiniteElement::Traits::LocalBasisType::Traits::JacobianType;
122 using FEGlobalJacobian = typename Impl::GlobalJacobianTraits<FEJacobian, GeometryJacobianInverse>::type;
123
127
128 ShapeFunctionCache(const QuadratureRule& rule, const Node& node)
129 {
130 setRule(rule);
131 setTree(node);
132 }
133
135 node_(nullptr)
136 {
137 setRule(rule);
138 }
139
140 ShapeFunctionCache(const Node& node) :
141 rule_(nullptr)
142 {
143 setTree(node);
144 }
145
146 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
147
149
150 void setRule(const QuadratureRule& rule)
151 {
152 rule_ = &rule;
153 valueCache_.resize(rule_->size());
154 jacobianCache_.resize(rule_->size());
155 globalJacobianCache_.resize(rule_->size());
156 valueCache_[0].clear();
157 jacobianCache_[0].clear();
158 globalJacobianCache_[0].clear();
159 }
160
161 void setTree(const Node& node)
162 {
163 node_ = &node;
164 }
165
167 {
168 isNonAffine_ = true;
169 }
170
171 const QuadratureRule& rule() const
172 {
173 return *rule_;
174 }
175
177 {
178 // We use the size at the first quadrature point to indicate
179 // an invalidated cache. To this end we set it's size to zero.
180 if (isNonAffine_)
181 {
182 valueCache_[0].clear();
183 jacobianCache_[0].clear();
184 }
185 globalJacobianCache_[0].clear();
186 }
187
188 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<>& treePath) const
189 {
190 return *this;
191 }
192
193 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<>& treePath)
194 {
195 return *this;
196 }
197
198 const auto& getValues()
199 {
200 if (valueCache_[0].empty())
201 {
202 if (node_->size() == 0)
203 return valueCache_;
204 const auto& localBasis = node_->finiteElement().localBasis();
205 for(std::size_t k=0; k<rule_->size(); ++k)
206 localBasis.evaluateFunction((*rule_)[k].position(), valueCache_[k]);
207 }
208 return valueCache_;
209 }
210
211 const auto& getJacobians()
212 {
213 if (jacobianCache_[0].empty())
214 {
215 if (node_->size() == 0)
216 return jacobianCache_;
217 const auto& localBasis = node_->finiteElement().localBasis();
218 for(std::size_t k=0; k<rule_->size(); ++k)
219 localBasis.evaluateJacobian((*rule_)[k].position(), jacobianCache_[k]);
220 }
221 return jacobianCache_;
222 }
223
224 const auto& getGlobalJacobians()
225 {
226 if (globalJacobianCache_[0].empty())
227 {
228 if (node_->size() == 0)
229 return globalJacobianCache_;
230 const auto& geometry = node_->element().geometry();
231 const auto& jacobians = getJacobians();
232 for(std::size_t k=0; k<rule_->size(); ++k)
233 {
234 globalJacobianCache_[k].resize(jacobians[k].size());
235 const auto& jacobianInverse = geometry.jacobianInverse((*rule_)[k].position());
236 for(std::size_t i=0; i<jacobians[k].size(); ++i)
237 globalJacobianCache_[k][i] = jacobians[k][i] * jacobianInverse;
238 }
239 }
240 return globalJacobianCache_;
241 }
242
243 private:
244 const QuadratureRule* rule_ = nullptr;
245 const Node* node_ = nullptr;
246 ValueCache valueCache_;
247 JacobianCache jacobianCache_;
248 GlobalJacobianCache globalJacobianCache_;
249 bool isNonAffine_ = false;
250 };
251
252
253
254 template<class Node, class CT>
255 requires Dune::Fufem::Impl::Concept::UniformInnerTreeNode<Node>
256 class ShapeFunctionCache<Node, CT>
257 {
258 using ChildNode = Dune::TypeTree::Child<Node,0>;
259 using ChildCache = ShapeFunctionCache<ChildNode, CT>;
260 public:
261
263
264 ShapeFunctionCache(const QuadratureRule& rule, const Node& node) :
265 childCache_(rule, node.child(0))
266 {}
267
269 childCache_(rule)
270 {}
271
272 ShapeFunctionCache(const Node& node) :
273 childCache_(node.child(0))
274 {}
275
276 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
277
279
280 void setRule(const QuadratureRule& rule)
281 {
282 childCache_.setRule(rule);
283 }
284
285 void setTree(const Node& node)
286 {
287 childCache_.setTree(node.child(0));
288 }
289
291 {
292 childCache_.setNonAffine();
293 }
294
295 const QuadratureRule& rule() const
296 {
297 return childCache_.rule();
298 }
299
301 {
302 childCache_.invalidate();
303 }
304
306 {
307 assert(i<Node::degree());
308 return childCache_;
309 }
310
312 {
313 assert(i<Node::degree());
314 return childCache_;
315 }
316
317 template<class... T>
318 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath) const
319 {
320 return Impl::accessByTreePath(*this, treePath);
321 }
322
323 template<class... T>
324 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath)
325 {
326 return Impl::accessByTreePath(*this, treePath);
327 }
328
329 constexpr std::size_t size() const noexcept
330 {
331 return Node::degree();
332 }
333
334 private:
335 ChildCache childCache_;
336 };
337
338
339
340 namespace Impl {
341
342 template<class Node, class CT, class Indices>
343 struct TupleVectorOfChildShapeFunctionCaches
344 {};
345
346 template<class Node, class CT, std::size_t... indices>
347 struct TupleVectorOfChildShapeFunctionCaches<Node, CT, std::index_sequence<indices...>>
348 {
350 };
351
352 template<class Node>
353 using ChildIndices = std::make_index_sequence<decltype(Node::degree())::value>;
354
355 template<class Node, class CT>
356 using TupleVectorOfChildShapeFunctionCaches_t = typename TupleVectorOfChildShapeFunctionCaches<Node, CT, ChildIndices<Node>>::type;
357
358 } // end namespace Imp
359
360
361
362 template<class Node, class CT>
363 requires (Dune::Fufem::Impl::Concept::StaticDegreeInnerTreeNode<Node>
364 and not Dune::Fufem::Impl::Concept::UniformInnerTreeNode<Node>)
365 class ShapeFunctionCache<Node, CT>
366 : public Impl::TupleVectorOfChildShapeFunctionCaches_t<Node, CT>
367 {
368 using Base = Impl::TupleVectorOfChildShapeFunctionCaches_t<Node, CT>;
369 public:
370
372
373 ShapeFunctionCache(const QuadratureRule& rule, const Node& node)
374 {
375 setRule(rule);
376 setTree(node);
377 }
378
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
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
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()
constexpr index_constant< 0 > _0
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
typename Impl::ChildTraits< Node, indices... >::type Child
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
constexpr auto front() const
decltype(std::declval< T1 >()+std::declval< T2 >()) PromotedType
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 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
const auto & getValues()
Definition shapefunctioncache.hh:198
ShapeFunctionCache(const QuadratureRule &rule, const Node &node)
Definition shapefunctioncache.hh:128
const auto & getJacobians()
Definition shapefunctioncache.hh:211
ShapeFunctionCache(const Node &node)
Definition shapefunctioncache.hh:140
ChildCache & operator[](std::size_t i)
Definition shapefunctioncache.hh:311
const auto & getGlobalJacobians()
Definition shapefunctioncache.hh:224
typename std::vector< std::vector< FEValue > > ValueCache
Definition shapefunctioncache.hh:124
typename Node::FiniteElement::Traits::LocalBasisType::Traits::JacobianType FEJacobian
Definition shapefunctioncache.hh:121
typename Node::FiniteElement::Traits::LocalBasisType::Traits::RangeType FEValue
Definition shapefunctioncache.hh:120
ShapeFunctionCache(const QuadratureRule &rule)
Definition shapefunctioncache.hh:134
ShapeFunctionCache(const ShapeFunctionCache &other)=default
typename std::vector< std::vector< FEJacobian > > JacobianCache
Definition shapefunctioncache.hh:125
void setNonAffine()
Definition shapefunctioncache.hh:166
void setTree(const Node &node)
Definition shapefunctioncache.hh:161
void invalidate()
Definition shapefunctioncache.hh:176
constexpr std::size_t size() const noexcept
Definition shapefunctioncache.hh:329
typename std::vector< std::vector< FEGlobalJacobian > > GlobalJacobianCache
Definition shapefunctioncache.hh:126
const ChildCache & operator[](std::size_t i) const
Definition shapefunctioncache.hh:305
const QuadratureRule & rule() const
Definition shapefunctioncache.hh:171
void setRule(const QuadratureRule &rule)
Definition shapefunctioncache.hh:150
typename Impl::GlobalJacobianTraits< FEJacobian, GeometryJacobianInverse >::type FEGlobalJacobian
Definition shapefunctioncache.hh:122
A hierarchic cache for storing shape function evaluations for a tree.
Definition shapefunctioncache.hh:107
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
Objects of this class are used to uniquely identifies a cache.
Definition shapefunctioncache.hh:569
UniqueCacheId(const T &t)
Definition shapefunctioncache.hh:574
Quadrature rule for a subentity of some given geometry type.
Definition subentityquadraturerule.hh:31
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
A token that specifies a quadrature rule.
Definition quadraturerulecache.hh:39
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)
Definition baseclass.hh:22
STL namespace.
T push_back(T... args)
T size(T... args)
This header provides fallback implementations for dune-typetree<2.11.