LocalBasisEvaluatorCache.hpp 3.01 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#pragma once

#include <vector>

#include <dune/geometry/quadraturerules.hh>
#include <dune/geometry/type.hh>

#include <amdis/LocalBasisCache.hpp>
#include <amdis/common/TupleUtility.hpp>
#include <amdis/utility/ConcurrentCache.hpp>

namespace AMDiS
{
  namespace Impl
  {
    /// Pair of GeometryType and quadrature order and size
    template <class LocalBasisType, class Tag>
    struct EvaluatorCacheKey
    {
      using type = std::tuple<HashableGeometryType,typename LocalBasisType::Traits::DomainType>;
      type value;

      friend std::size_t hash_value(EvaluatorCacheKey const& t)
      {
        std::size_t seed = hash_value(std::get<0>(t.value));
        Dune::hash_range(seed, std::get<1>(t.value).begin(), std::get<1>(t.value).end());
        return seed;
      }

      friend bool operator==(EvaluatorCacheKey const& lhs, EvaluatorCacheKey const& rhs)
      {
        return lhs.value == rhs.value;
      }
    };
  }
} // end namespace AMDiS

DUNE_DEFINE_HASH(DUNE_HASH_TEMPLATE_ARGS(class LocalBasisType, class Tag),DUNE_HASH_TYPE(AMDiS::Impl::EvaluatorCacheKey<LocalBasisType,Tag>))

namespace AMDiS
{
  template <class LocalBasisType>
  class LocalBasisEvaluatorCache
  {
  public:
    using Traits = typename LocalBasisType::Traits;

    using DomainType = typename Traits::DomainType;
    using RangeType = typename Traits::RangeType;
    using RangeFieldType = typename Traits::RangeFieldType;
    using JacobianType = typename Traits::JacobianType;

    using QuadratureRule = Dune::QuadratureRule<RangeFieldType,Traits::dimDomain>;
    using QuadratureRules = Dune::QuadratureRules<RangeFieldType,Traits::dimDomain>;

  private:
    using ValuesKey = Impl::EvaluatorCacheKey<LocalBasisType, struct ValuesTag>;
    using GradientsKey = Impl::EvaluatorCacheKey<LocalBasisType, struct GradientsTag>;
    using Policy = tag::thread_local_policy;

  public:
    using ShapeValues = std::vector<RangeType>;
    using ShapeGradients = std::vector<JacobianType>;

    LocalBasisEvaluatorCache(LocalBasisType const& localBasis)
      : localBasis_(&localBasis)
    {}

    template <class LocalContext>
    ShapeValues const& evaluateFunction(LocalContext const& context, DomainType const& local)
    {
      ValuesKey key{typename ValuesKey::type{context.type(),local}};
      return ShapeValuesCache::get(key, [&](ShapeValues* data, ValuesKey const&)
      {
        localBasis_->evaluateFunction(local, *data);
      });
    }

    template <class LocalContext>
    ShapeGradients const& evaluateJacobian(LocalContext const& context, DomainType const& local)
    {
      GradientsKey key{typename GradientsKey::type{context.type(),local}};
      return ShapeGradientsCache::get(key, [&](ShapeGradients* data, GradientsKey const&)
      {
        localBasis_->evaluateJacobian(local, *data);
      });
    }

  private:
    using ShapeValuesCache = ConcurrentCache<ValuesKey, ShapeValues, Policy>;
    using ShapeGradientsCache = ConcurrentCache<GradientsKey, ShapeGradients, Policy>;

    LocalBasisType const* localBasis_;
  };

} // end namespace AMDiS