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>
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 List, class CT>
343 struct TupleVectorOfShapeFunctionCaches
344 {};
345
346 template<class CT, template<class...> class ListType, class... Args>
347 struct TupleVectorOfShapeFunctionCaches<ListType<Args...>, CT>
348 {
350 };
351
352 template<class List, class CT>
353 using TupleVectorOfShapeFunctionCaches_t = typename TupleVectorOfShapeFunctionCaches<List, CT>::type;
354
355 } // end namespace Imp
356
357
358
359 template<class Node, class CT>
360 requires (Dune::Fufem::Impl::Concept::StaticDegreeInnerTreeNode<Node>
361 and not Dune::Fufem::Impl::Concept::UniformInnerTreeNode<Node>)
362 class ShapeFunctionCache<Node, CT>
363 : public Impl::TupleVectorOfShapeFunctionCaches_t<Dune::Fufem::Impl::Children<Node>, CT>
364 {
365 using Base = Impl::TupleVectorOfShapeFunctionCaches_t<Dune::Fufem::Impl::Children<Node>, CT>;
366 public:
367
369
370 ShapeFunctionCache(const QuadratureRule& rule, const Node& node)
371 {
372 setRule(rule);
373 setTree(node);
374 }
375
377 {
378 setRule(rule);
379 }
380
381 ShapeFunctionCache(const Node& node)
382 {
383 setTree(node);
384 }
385
386
387 ShapeFunctionCache(const ShapeFunctionCache& other) = default;
388
390
391 void setRule(const QuadratureRule& rule)
392 {
393 Hybrid::forEach(*this, [&](auto& childCache) {
394 childCache.setRule(rule);
395 });
396 }
397
398 void setTree(const Node& node)
399 {
400 Hybrid::forEach(Dune::range(Node::degree()), [&](const auto& i){
401 (*this)[i].setTree(node.child(i));
402 });
403 }
404
406 {
407 Hybrid::forEach(Dune::range(Node::degree()), [&](const auto& i){
408 (*this)[i].setNonAffine();
409 });
410 }
411
412 const QuadratureRule& rule() const
413 {
414 return (*this)[Dune::Indices::_0].rule();
415 }
416
417 using Base::operator[];
418
419 template<class... T>
420 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath) const
421 {
422 return Impl::accessByTreePath(*this, treePath);
423 }
424
425 template<class... T>
426 decltype(auto) operator[](const Dune::Fufem::Impl::TreePath<T...>& treePath)
427 {
428 return Impl::accessByTreePath(*this, treePath);
429 }
430
431 void invalidate() {
432 Hybrid::forEach(*this, [&](auto& childCache) {
433 childCache.invalidate();
434 });
435 }
436
437 };
438
439
440
462 template<class C>
464 {
465 using Cache = C;
466 using CT = typename Cache::QuadratureRule::CoordType;
467 constexpr static int dimension = Cache::QuadratureRule::d;
468
471
472 public:
473
476
477 private:
478
479 template<class Key>
480 const QuadratureRule& getRule(const Key& key)
481 {
484 else
485 {
486 auto facet = key.second;
487 auto&& type = key.first.geometryType();
488 auto facetGeometryType = Dune::referenceElement<CT,dimension>(type).type(facet, 1);
489 auto facetQuadratureRuleKey = key.first;
490 facetQuadratureRuleKey.setGeometryType(facetGeometryType);
491 const auto& rule = QuadratureRuleCache<CT, dimension-1>::rule(facetQuadratureRuleKey);
492 // We need to store the face quadrature rule.
493 // By using an std::list, we can store pointers
494 // to the stored rules, because they never get invalidated.
495 facetQuadratureRules_.push_back(FacetQuadratureRule(type, facet, rule));
496 return facetQuadratureRules_.back();
497 }
498 }
499
500 template<class Key>
501 Cache makeCache(const Key& key)
502 {
503 auto cache = Cache(prototype_);
504 cache.setRule(getRule(key));
505 return cache;
506 }
507
508 public:
509
510 Cache& operator[](const QuadratureRuleKey& key) {
511 auto it = elementCacheMap_.find(key);
512 if (it == elementCacheMap_.end())
513 return (elementCacheMap_.insert(std::make_pair(key, makeCache(key)))).first->second;
514 else
515 return it->second;
516 }
517
518 Cache& operator[](const FacetKey& facetKey) {
519 auto it = facetCacheMap_.find(facetKey);
520 if (it == facetCacheMap_.end())
521 return (facetCacheMap_.insert(std::make_pair(facetKey, makeCache(facetKey)))).first->second;
522 else
523 return it->second;
524 }
525
526 Cache& prototype()
527 {
528 return prototype_;
529 }
530
531 void clear()
532 {
533 prototype_.clear();
534 elementCacheMap_.clear();
535 facetCacheMap_.clear();
536 facetQuadratureRules_.clear();
537 }
538
539 private:
540 std::map<ElementKey, Cache> elementCacheMap_;
541 std::map<FacetKey, Cache> facetCacheMap_;
542 Cache prototype_;
543 std::list<FacetQuadratureRule> facetQuadratureRules_;
544 };
545
546
547
565 class UniqueCacheId : public std::pair<const void*, std::type_index>
566 {
568 public:
569
570 template<class T>
571 UniqueCacheId(const T& t) :
572 Base(&t, std::type_index(typeid(T)))
573 {}
574 };
575
610 template<class CT, int dimension>
612 {
613 public:
616
617 private:
618
619 // Simple type erasure for stored caches.
620 class TypeErasedCache
621 {
622 struct {
623 std::any impl_;
624 void*(*toRawPtr_)(std::any&);
625 void(*invalidate_)(void*);
626 void(*setRule_)(void*, const QuadratureRule&);
627 } members_;
628 void* rawPtr_;
629
630 void* toRawPtr()
631 {
632 return members_.toRawPtr_(members_.impl_);
633 }
634
635 public:
636
637 template<class Impl>
638 TypeErasedCache(Impl&& impl)
639 : members_{
640 std::move(impl),
641 [](std::any& impl) -> void* { return &std::any_cast<Impl&>(impl); },
642 [](void* impl) { static_cast<Impl*>(impl)->invalidate(); },
643 [](void* impl, const QuadratureRule& rule) { static_cast<Impl*>(impl)->setRule(rule); },
644 }
645 , rawPtr_(toRawPtr())
646 {}
647
648 TypeErasedCache(TypeErasedCache&& other)
649 : members_(std::move(other.members_))
650 , rawPtr_(toRawPtr())
651 {}
652
653 TypeErasedCache(const TypeErasedCache& other)
654 : members_(other.members_)
655 , rawPtr_(toRawPtr())
656 {}
657
658 TypeErasedCache(TypeErasedCache& other)
659 : members_(other.members_)
660 , rawPtr_(toRawPtr())
661 {}
662
663 void invalidate()
664 {
665 members_.invalidate_(rawPtr_);
666 }
667
668 void setRule(const QuadratureRule& rule)
669 {
670 members_.setRule_(rawPtr_, rule);
671 }
672
673 template<class Impl>
674 Impl& get()
675 {
676 return *static_cast<Impl*>(rawPtr_);
677 }
678 };
679
680 const QuadratureRule* rule_ = nullptr;
683
684 public:
685
686 CacheManager() = default;
687 CacheManager(CacheManager&& other) = default;
688 CacheManager(const CacheManager& other) = default;
689
692
696 void clear()
697 {
698 rule_ = nullptr;
699 cacheIndex_.clear();
700 caches_.clear();
701 }
702
706 const QuadratureRule& rule() const
707 {
708 return *rule_;
709 }
710
715 {
716 rule_ = &rule;
717 for(auto index : Dune::range(caches_.size()))
718 caches_[index].setRule(rule);
719 }
720
725 {
726 for(auto index : Dune::range(caches_.size()))
727 caches_[index].invalidate();
728 }
729
730 // For diagnostics: Print number of stored caches
731 void report() const
732 {
733 std::cout << "Number of managed caches " << caches_.size() << std::endl;
734 }
735
749 template<class Cache>
750 size_type registerCache(UniqueCacheId uniqueCacheId, Cache&& cache)
751 {
752 auto it = cacheIndex_.find(uniqueCacheId);
753 if (it == cacheIndex_.end())
754 {
755 caches_.push_back(std::forward<Cache>(cache));
756 cacheIndex_[uniqueCacheId] = caches_.size()-1;
757 return caches_.size()-1;
758 }
759 else
760 return it->second;
761 }
762
773 template<class Cache>
775 {
776 return caches_[index].template get<Cache>();
777 }
778
779 };
780
781
782
788 template<class CT, int dimension>
790
791
792
803 template<class CT, int dimension, class V>
805 {
806 public:
807
809
810 using Value = V;
812
813 SimpleCache(bool isNonAffine) :
814 isNonAffine_(isNonAffine)
815 {}
816
817 SimpleCache(const SimpleCache& other) = default;
818
820 {
821 rule_ = &rule;
822 valueCache_.resize(rule_->size());
823 isEmpty_ = true;
824 }
825
826 const QuadratureRule& rule() const
827 {
828 return *rule_;
829 }
830
832 {
833 isNonAffine_ = true;
834 }
835
837 {
838 if (isNonAffine_)
839 isEmpty_ = true;
840 }
841
842 bool isEmpty()
843 {
844 return isEmpty_;
845 }
846
847 void setEmpty(bool isEmpty)
848 {
849 isEmpty_ = isEmpty;
850 }
851
852 auto& getValues()
853 {
854 return valueCache_;
855 }
856
857 const auto& getValues() const
858 {
859 return valueCache_;
860 }
861
862 private:
863 const QuadratureRule* rule_ = nullptr;
864 ValueCache valueCache_;
865 bool isEmpty_ = true;
866 bool isNonAffine_ = false;
867 };
868
869
870
871} // namespace Dune::Fufem::Forms
872
873
874#endif // DUNE_FUFEM_FORMS_SHAPEFUNCTIONCACHE_HH
875
void invalidate()
This header provides fallback implementations for dune-typetree<2.11.
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
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
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 cache providing multiple versions for different quadrature rules.
Definition shapefunctioncache.hh:464
Cache & operator[](const QuadratureRuleKey &key)
Definition shapefunctioncache.hh:510
Cache & operator[](const FacetKey &facetKey)
Definition shapefunctioncache.hh:518
void clear()
Definition shapefunctioncache.hh:531
Cache & prototype()
Definition shapefunctioncache.hh:526
Objects of this class are used to uniquely identifies a cache.
Definition shapefunctioncache.hh:566
UniqueCacheId(const T &t)
Definition shapefunctioncache.hh:571
A class for managing caches of different types.
Definition shapefunctioncache.hh:612
auto & getCache(size_type index)
Obtain a registered cache.
Definition shapefunctioncache.hh:774
CacheManager(const CacheManager &other)=default
void invalidate()
Invalidate all stores caches.
Definition shapefunctioncache.hh:724
CacheManager & operator=(const CacheManager &)=delete
size_type registerCache(UniqueCacheId uniqueCacheId, Cache &&cache)
Register a new cache.
Definition shapefunctioncache.hh:750
void report() const
Definition shapefunctioncache.hh:731
void setRule(const QuadratureRule &rule)
Set the associated quadrature rule for all stored caches.
Definition shapefunctioncache.hh:714
CacheManager(CacheManager &&other)=default
const QuadratureRule & rule() const
Obtain the associated quadrature rule.
Definition shapefunctioncache.hh:706
void clear()
Clear all stored data.
Definition shapefunctioncache.hh:696
A simple cache implementation storing values.
Definition shapefunctioncache.hh:805
auto & getValues()
Definition shapefunctioncache.hh:852
SimpleCache(bool isNonAffine)
Definition shapefunctioncache.hh:813
bool isEmpty()
Definition shapefunctioncache.hh:842
void setEmpty(bool isEmpty)
Definition shapefunctioncache.hh:847
V Value
Definition shapefunctioncache.hh:810
void invalidate()
Definition shapefunctioncache.hh:836
void setNonAffine()
Definition shapefunctioncache.hh:831
const QuadratureRule & rule() const
Definition shapefunctioncache.hh:826
void setRule(const QuadratureRule &rule)
Definition shapefunctioncache.hh:819
SimpleCache(const SimpleCache &other)=default
const auto & getValues() const
Definition shapefunctioncache.hh:857
typename std::vector< Value > ValueCache
Definition shapefunctioncache.hh:811
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)