Dune-Fufem 2.12-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
20
23
24
25namespace Dune::Fufem::Forms::Impl {
26
27 template<class C, class... T>
28 static constexpr decltype(auto) accessByTreePath(C&& container, const Dune::TypeTree::TreePath<T...>& path)
29 {
30 if constexpr (sizeof...(T)==0)
31 return container;
32 else
33 return accessByTreePath(container[path.front()], pop_front(path));
34 }
35
36 template<class ReferenceJacobian, class GeometryJacobianInverse>
37 struct GlobalJacobianTraits
38 {
39 using GeometryField = typename GeometryJacobianInverse::field_type;
40 using ReferenceJacobianField = typename ReferenceJacobian::field_type;
42 static constexpr int dimWorld = GeometryJacobianInverse::cols;
44 };
45
46 template<class GeometryJacobianInverse, class JF, int dimRange, int dim>
47 struct GlobalJacobianTraits<Dune::FieldMatrix<JF, dimRange, dim>, GeometryJacobianInverse>
48 {
49 using GeometryField = typename GeometryJacobianInverse::field_type;
50 using ReferenceJacobianField = JF;
52 static constexpr int dimWorld = GeometryJacobianInverse::cols;
54 };
55
56
57
58} // end namespace Dune::Fufem::Forms::Impl
59
60
61
62namespace Dune::Fufem::Forms {
63
64
65
100 template<class Node, class CT=double>
102
103
104
105 template<class Node, class CT>
107 class ShapeFunctionCache<Node, CT>
108 {
109 using GeometryJacobianInverse = typename Node::Element::Geometry::JacobianInverse;
110 public:
111
113
114 using FEValue = typename Node::FiniteElement::Traits::LocalBasisType::Traits::RangeType;
115 using FEJacobian = typename Node::FiniteElement::Traits::LocalBasisType::Traits::JacobianType;
116 using FEGlobalJacobian = typename Impl::GlobalJacobianTraits<FEJacobian, GeometryJacobianInverse>::type;
117
121
122 ShapeFunctionCache(const QuadratureRule& rule, const Node& node)
123 {
124 setRule(rule);
125 setTree(node);
126 }
127
129 node_(nullptr)
130 {
131 setRule(rule);
132 }
133
134 ShapeFunctionCache(const Node& node) :
135 rule_(nullptr)
136 {
137 setTree(node);
138 }
139
140 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
141
143
144 void setRule(const QuadratureRule& rule)
145 {
146 rule_ = &rule;
147 valueCache_.resize(rule_->size());
148 jacobianCache_.resize(rule_->size());
149 globalJacobianCache_.resize(rule_->size());
150 valueCache_[0].clear();
151 jacobianCache_[0].clear();
152 globalJacobianCache_[0].clear();
153 }
154
155 void setTree(const Node& node)
156 {
157 node_ = &node;
158 }
159
161 {
162 isNonAffine_ = true;
163 }
164
165 const QuadratureRule& rule() const
166 {
167 return *rule_;
168 }
169
171 {
172 // We use the size at the first quadrature point to indicate
173 // an invalidated cache. To this end we set it's size to zero.
174 if (isNonAffine_)
175 {
176 valueCache_[0].clear();
177 jacobianCache_[0].clear();
178 }
179 globalJacobianCache_[0].clear();
180 }
181
182 decltype(auto) operator[](const Dune::TypeTree::TreePath<>& treePath) const
183 {
184 return *this;
185 }
186
187 decltype(auto) operator[](const Dune::TypeTree::TreePath<>& treePath)
188 {
189 return *this;
190 }
191
192 const auto& getValues()
193 {
194 if (valueCache_[0].empty())
195 {
196 if (node_->size() == 0)
197 return valueCache_;
198 const auto& localBasis = node_->finiteElement().localBasis();
199 for(std::size_t k=0; k<rule_->size(); ++k)
200 localBasis.evaluateFunction((*rule_)[k].position(), valueCache_[k]);
201 }
202 return valueCache_;
203 }
204
205 const auto& getJacobians()
206 {
207 if (jacobianCache_[0].empty())
208 {
209 if (node_->size() == 0)
210 return jacobianCache_;
211 const auto& localBasis = node_->finiteElement().localBasis();
212 for(std::size_t k=0; k<rule_->size(); ++k)
213 localBasis.evaluateJacobian((*rule_)[k].position(), jacobianCache_[k]);
214 }
215 return jacobianCache_;
216 }
217
218 const auto& getGlobalJacobians()
219 {
220 if (globalJacobianCache_[0].empty())
221 {
222 if (node_->size() == 0)
223 return globalJacobianCache_;
224 const auto& geometry = node_->element().geometry();
225 const auto& jacobians = getJacobians();
226 for(std::size_t k=0; k<rule_->size(); ++k)
227 {
228 globalJacobianCache_[k].resize(jacobians[k].size());
229 const auto& jacobianInverse = geometry.jacobianInverse((*rule_)[k].position());
230 for(std::size_t i=0; i<jacobians[k].size(); ++i)
231 globalJacobianCache_[k][i] = jacobians[k][i] * jacobianInverse;
232 }
233 }
234 return globalJacobianCache_;
235 }
236
237 private:
238 const QuadratureRule* rule_ = nullptr;
239 const Node* node_ = nullptr;
240 ValueCache valueCache_;
241 JacobianCache jacobianCache_;
242 GlobalJacobianCache globalJacobianCache_;
243 bool isNonAffine_ = false;
244 };
245
246
247
248 template<class Node, class CT>
250 class ShapeFunctionCache<Node, CT>
251 {
252 using ChildNode = Dune::TypeTree::Child<Node,0>;
253 using ChildCache = ShapeFunctionCache<ChildNode, CT>;
254 public:
255
257
258 ShapeFunctionCache(const QuadratureRule& rule, const Node& node) :
259 childCache_(rule, node.child(0))
260 {}
261
263 childCache_(rule)
264 {}
265
266 ShapeFunctionCache(const Node& node) :
267 childCache_(node.child(0))
268 {}
269
270 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
271
273
274 void setRule(const QuadratureRule& rule)
275 {
276 childCache_.setRule(rule);
277 }
278
279 void setTree(const Node& node)
280 {
281 childCache_.setTree(node.child(0));
282 }
283
285 {
286 childCache_.setNonAffine();
287 }
288
289 const QuadratureRule& rule() const
290 {
291 return childCache_.rule();
292 }
293
295 {
296 childCache_.invalidate();
297 }
298
300 {
301 assert(i<Node::degree());
302 return childCache_;
303 }
304
306 {
307 assert(i<Node::degree());
308 return childCache_;
309 }
310
311 template<class... T>
312 decltype(auto) operator[](const Dune::TypeTree::TreePath<T...>& treePath) const
313 {
314 return Impl::accessByTreePath(*this, treePath);
315 }
316
317 template<class... T>
318 decltype(auto) operator[](const Dune::TypeTree::TreePath<T...>& treePath)
319 {
320 return Impl::accessByTreePath(*this, treePath);
321 }
322
323 constexpr std::size_t size() const noexcept
324 {
325 return Node::degree();
326 }
327
328 private:
329 ChildCache childCache_;
330 };
331
332
333
334 namespace Impl {
335
336 template<class Node, class CT, class Indices>
337 struct TupleVectorOfChildShapeFunctionCaches
338 {};
339
340 template<class Node, class CT, std::size_t... indices>
341 struct TupleVectorOfChildShapeFunctionCaches<Node, CT, std::index_sequence<indices...>>
342 {
344 };
345
346 template<class Node>
347 using ChildIndices = std::make_index_sequence<decltype(Node::degree())::value>;
348
349 template<class Node, class CT>
350 using TupleVectorOfChildShapeFunctionCaches_t = typename TupleVectorOfChildShapeFunctionCaches<Node, CT, ChildIndices<Node>>::type;
351
352 } // end namespace Imp
353
354
355
356 template<class Node, class CT>
359 class ShapeFunctionCache<Node, CT>
360 : public Impl::TupleVectorOfChildShapeFunctionCaches_t<Node, CT>
361 {
362 using Base = Impl::TupleVectorOfChildShapeFunctionCaches_t<Node, CT>;
363 public:
364
366
367 ShapeFunctionCache(const QuadratureRule& rule, const Node& node)
368 {
369 setRule(rule);
370 setTree(node);
371 }
372
374 {
375 setRule(rule);
376 }
377
378 ShapeFunctionCache(const Node& node)
379 {
380 setTree(node);
381 }
382
383
384 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
385
387
388 void setRule(const QuadratureRule& rule)
389 {
390 Hybrid::forEach(*this, [&](auto& childCache) {
391 childCache.setRule(rule);
392 });
393 }
394
395 void setTree(const Node& node)
396 {
397 Hybrid::forEach(Dune::range(Node::degree()), [&](const auto& i){
398 (*this)[i].setTree(node.child(i));
399 });
400 }
401
403 {
404 Hybrid::forEach(Dune::range(Node::degree()), [&](const auto& i){
405 (*this)[i].setNonAffine();
406 });
407 }
408
409 const QuadratureRule& rule() const
410 {
411 return (*this)[Dune::Indices::_0].rule();
412 }
413
414 using Base::operator[];
415
416 template<class... T>
417 decltype(auto) operator[](const Dune::TypeTree::TreePath<T...>& treePath) const
418 {
419 return Impl::accessByTreePath(*this, treePath);
420 }
421
422 template<class... T>
423 decltype(auto) operator[](const Dune::TypeTree::TreePath<T...>& treePath)
424 {
425 return Impl::accessByTreePath(*this, treePath);
426 }
427
428 void invalidate() {
429 Hybrid::forEach(*this, [&](auto& childCache) {
430 childCache.invalidate();
431 });
432 }
433
434 };
435
436
437
459 template<class C>
461 {
462 using Cache = C;
463 using CT = typename Cache::QuadratureRule::CoordType;
464 constexpr static int dimension = Cache::QuadratureRule::d;
465
468
469 public:
470
473
474 private:
475
476 template<class Key>
477 const QuadratureRule& getRule(const Key& key)
478 {
481 else
482 {
483 auto facet = key.second;
484 auto&& type = key.first.geometryType();
485 auto facetGeometryType = Dune::referenceElement<CT,dimension>(type).type(facet, 1);
486 auto facetQuadratureRuleKey = key.first;
487 facetQuadratureRuleKey.setGeometryType(facetGeometryType);
488 const auto& rule = QuadratureRuleCache<CT, dimension-1>::rule(facetQuadratureRuleKey);
489 // We need to store the face quadrature rule.
490 // By using an std::list, we can store pointers
491 // to the stored rules, because they never get invalidated.
492 facetQuadratureRules_.push_back(FacetQuadratureRule(type, facet, rule));
493 return facetQuadratureRules_.back();
494 }
495 }
496
497 template<class Key>
498 Cache makeCache(const Key& key)
499 {
500 auto cache = Cache(prototype_);
501 cache.setRule(getRule(key));
502 return cache;
503 }
504
505 public:
506
507 Cache& operator[](const QuadratureRuleKey& key) {
508 auto it = elementCacheMap_.find(key);
509 if (it == elementCacheMap_.end())
510 return (elementCacheMap_.insert(std::make_pair(key, makeCache(key)))).first->second;
511 else
512 return it->second;
513 }
514
515 Cache& operator[](const FacetKey& facetKey) {
516 auto it = facetCacheMap_.find(facetKey);
517 if (it == facetCacheMap_.end())
518 return (facetCacheMap_.insert(std::make_pair(facetKey, makeCache(facetKey)))).first->second;
519 else
520 return it->second;
521 }
522
523 Cache& prototype()
524 {
525 return prototype_;
526 }
527
528 void clear()
529 {
530 prototype_.clear();
531 elementCacheMap_.clear();
532 facetCacheMap_.clear();
533 facetQuadratureRules_.clear();
534 }
535
536 private:
537 std::map<ElementKey, Cache> elementCacheMap_;
538 std::map<FacetKey, Cache> facetCacheMap_;
539 Cache prototype_;
540 std::list<FacetQuadratureRule> facetQuadratureRules_;
541 };
542
543
544
562 class UniqueCacheId : public std::pair<const void*, std::type_index>
563 {
565 public:
566
567 template<class T>
568 UniqueCacheId(const T& t) :
569 Base(&t, std::type_index(typeid(T)))
570 {}
571 };
572
607 template<class CT, int dimension>
609 {
610 public:
613
614 private:
615
616 // Simple type erasure for stored caches.
617 class TypeErasedCache
618 {
619 struct {
620 std::any impl_;
621 void*(*toRawPtr_)(std::any&);
622 void(*invalidate_)(void*);
623 void(*setRule_)(void*, const QuadratureRule&);
624 } members_;
625 void* rawPtr_;
626
627 void* toRawPtr()
628 {
629 return members_.toRawPtr_(members_.impl_);
630 }
631
632 public:
633
634 template<class Impl>
635 TypeErasedCache(Impl&& impl)
636 : members_{
637 std::move(impl),
638 [](std::any& impl) -> void* { return &std::any_cast<Impl&>(impl); },
639 [](void* impl) { static_cast<Impl*>(impl)->invalidate(); },
640 [](void* impl, const QuadratureRule& rule) { static_cast<Impl*>(impl)->setRule(rule); },
641 }
642 , rawPtr_(toRawPtr())
643 {}
644
645 TypeErasedCache(TypeErasedCache&& other)
646 : members_(std::move(other.members_))
647 , rawPtr_(toRawPtr())
648 {}
649
650 TypeErasedCache(const TypeErasedCache& other)
651 : members_(other.members_)
652 , rawPtr_(toRawPtr())
653 {}
654
655 TypeErasedCache(TypeErasedCache& other)
656 : members_(other.members_)
657 , rawPtr_(toRawPtr())
658 {}
659
660 void invalidate()
661 {
662 members_.invalidate_(rawPtr_);
663 }
664
665 void setRule(const QuadratureRule& rule)
666 {
667 members_.setRule_(rawPtr_, rule);
668 }
669
670 template<class Impl>
671 Impl& get()
672 {
673 return *static_cast<Impl*>(rawPtr_);
674 }
675 };
676
677 const QuadratureRule* rule_ = nullptr;
680
681 public:
682
683 CacheManager() = default;
684 CacheManager(CacheManager&& other) = default;
685 CacheManager(const CacheManager& other) = default;
686
689
693 void clear()
694 {
695 rule_ = nullptr;
696 cacheIndex_.clear();
697 caches_.clear();
698 }
699
703 const QuadratureRule& rule() const
704 {
705 return *rule_;
706 }
707
712 {
713 rule_ = &rule;
714 for(auto index : Dune::range(caches_.size()))
715 caches_[index].setRule(rule);
716 }
717
722 {
723 for(auto index : Dune::range(caches_.size()))
724 caches_[index].invalidate();
725 }
726
727 // For diagnostics: Print number of stored caches
728 void report() const
729 {
730 std::cout << "Number of managed caches " << caches_.size() << std::endl;
731 }
732
746 template<class Cache>
747 size_type registerCache(UniqueCacheId uniqueCacheId, Cache&& cache)
748 {
749 auto it = cacheIndex_.find(uniqueCacheId);
750 if (it == cacheIndex_.end())
751 {
752 caches_.push_back(std::forward<Cache>(cache));
753 cacheIndex_[uniqueCacheId] = caches_.size()-1;
754 return caches_.size()-1;
755 }
756 else
757 return it->second;
758 }
759
770 template<class Cache>
772 {
773 return caches_[index].template get<Cache>();
774 }
775
776 };
777
778
779
785 template<class CT, int dimension>
787
788
789
800 template<class CT, int dimension, class V>
802 {
803 public:
804
806
807 using Value = V;
809
810 SimpleCache(bool isNonAffine) :
811 isNonAffine_(isNonAffine)
812 {}
813
814 SimpleCache(const SimpleCache& other) = default;
815
817 {
818 rule_ = &rule;
819 valueCache_.resize(rule_->size());
820 isEmpty_ = true;
821 }
822
823 const QuadratureRule& rule() const
824 {
825 return *rule_;
826 }
827
829 {
830 isNonAffine_ = true;
831 }
832
834 {
835 if (isNonAffine_)
836 isEmpty_ = true;
837 }
838
839 bool isEmpty()
840 {
841 return isEmpty_;
842 }
843
844 void setEmpty(bool isEmpty)
845 {
846 isEmpty_ = isEmpty;
847 }
848
849 auto& getValues()
850 {
851 return valueCache_;
852 }
853
854 const auto& getValues() const
855 {
856 return valueCache_;
857 }
858
859 private:
860 const QuadratureRule* rule_ = nullptr;
861 ValueCache valueCache_;
862 bool isEmpty_ = true;
863 bool isNonAffine_ = false;
864 };
865
866
867
868} // namespace Dune::Fufem::Forms
869
870
871#endif // DUNE_FUFEM_FORMS_SHAPEFUNCTIONCACHE_HH
872
void invalidate()
int size() const
bool empty() const
void pop_front()
static constexpr IntegralRange< T > range(T from, T 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 index_constant< 0 > _0
constexpr auto front() const
decltype(std::declval< T1 >()+std::declval< T2 >()) PromotedType
A class for managing caches of different types.
Definition shapefunctioncache.hh:609
auto & getCache(size_type index)
Obtain a registered cache.
Definition shapefunctioncache.hh:771
CacheManager(const CacheManager &other)=default
void invalidate()
Invalidate all stores caches.
Definition shapefunctioncache.hh:721
CacheManager & operator=(const CacheManager &)=delete
size_type registerCache(UniqueCacheId uniqueCacheId, Cache &&cache)
Register a new cache.
Definition shapefunctioncache.hh:747
void report() const
Definition shapefunctioncache.hh:728
void setRule(const QuadratureRule &rule)
Set the associated quadrature rule for all stored caches.
Definition shapefunctioncache.hh:711
CacheManager(CacheManager &&other)=default
const QuadratureRule & rule() const
Obtain the associated quadrature rule.
Definition shapefunctioncache.hh:703
void clear()
Clear all stored data.
Definition shapefunctioncache.hh:693
A cache providing multiple versions for different quadrature rules.
Definition shapefunctioncache.hh:461
Cache & operator[](const QuadratureRuleKey &key)
Definition shapefunctioncache.hh:507
Cache & operator[](const FacetKey &facetKey)
Definition shapefunctioncache.hh:515
void clear()
Definition shapefunctioncache.hh:528
Cache & prototype()
Definition shapefunctioncache.hh:523
const auto & getValues()
Definition shapefunctioncache.hh:192
ShapeFunctionCache(const QuadratureRule &rule, const Node &node)
Definition shapefunctioncache.hh:122
const auto & getJacobians()
Definition shapefunctioncache.hh:205
ShapeFunctionCache(const Node &node)
Definition shapefunctioncache.hh:134
ChildCache & operator[](std::size_t i)
Definition shapefunctioncache.hh:305
const auto & getGlobalJacobians()
Definition shapefunctioncache.hh:218
typename std::vector< std::vector< FEValue > > ValueCache
Definition shapefunctioncache.hh:118
typename Node::FiniteElement::Traits::LocalBasisType::Traits::JacobianType FEJacobian
Definition shapefunctioncache.hh:115
typename Node::FiniteElement::Traits::LocalBasisType::Traits::RangeType FEValue
Definition shapefunctioncache.hh:114
ShapeFunctionCache(const QuadratureRule &rule)
Definition shapefunctioncache.hh:128
ShapeFunctionCache(const ShapeFunctionCache &other)=default
typename std::vector< std::vector< FEJacobian > > JacobianCache
Definition shapefunctioncache.hh:119
void setNonAffine()
Definition shapefunctioncache.hh:160
void setTree(const Node &node)
Definition shapefunctioncache.hh:155
void invalidate()
Definition shapefunctioncache.hh:170
constexpr std::size_t size() const noexcept
Definition shapefunctioncache.hh:323
typename std::vector< std::vector< FEGlobalJacobian > > GlobalJacobianCache
Definition shapefunctioncache.hh:120
const ChildCache & operator[](std::size_t i) const
Definition shapefunctioncache.hh:299
const QuadratureRule & rule() const
Definition shapefunctioncache.hh:165
void setRule(const QuadratureRule &rule)
Definition shapefunctioncache.hh:144
typename Impl::GlobalJacobianTraits< FEJacobian, GeometryJacobianInverse >::type FEGlobalJacobian
Definition shapefunctioncache.hh:116
A hierarchic cache for storing shape function evaluations for a tree.
Definition shapefunctioncache.hh:101
A simple cache implementation storing values.
Definition shapefunctioncache.hh:802
auto & getValues()
Definition shapefunctioncache.hh:849
SimpleCache(bool isNonAffine)
Definition shapefunctioncache.hh:810
bool isEmpty()
Definition shapefunctioncache.hh:839
void setEmpty(bool isEmpty)
Definition shapefunctioncache.hh:844
V Value
Definition shapefunctioncache.hh:807
void invalidate()
Definition shapefunctioncache.hh:833
void setNonAffine()
Definition shapefunctioncache.hh:828
const QuadratureRule & rule() const
Definition shapefunctioncache.hh:823
void setRule(const QuadratureRule &rule)
Definition shapefunctioncache.hh:816
SimpleCache(const SimpleCache &other)=default
const auto & getValues() const
Definition shapefunctioncache.hh:854
typename std::vector< Value > ValueCache
Definition shapefunctioncache.hh:808
Objects of this class are used to uniquely identifies a cache.
Definition shapefunctioncache.hh:563
UniqueCacheId(const T &t)
Definition shapefunctioncache.hh:568
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)