QuadratureFactory.hpp 6.03 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma once

#include <dune/common/hybridutilities.hh>
#include <dune/common/std/type_traits.hh>
#include <dune/geometry/quadraturerules.hh>
#include <dune/geometry/type.hh>

#include <amdis/GridFunctions.hpp>

namespace AMDiS
{
  /// Base class for quadrature factories for localFunctions
  template <class ctype, int dimension, class LocalFunction>
  class QuadratureFactory
  {
  protected:
    using QuadratureRule = Dune::QuadratureRule<ctype, dimension>;

  public:
20
    virtual ~QuadratureFactory() = default;
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

    /// Bind the rule to a localFunction
    virtual void bind(LocalFunction const& localFct)
    {}

    /// Return the quadrature order of the coefficient relates to the localFunction
    virtual int order() const
    {
      return 0;
    }

    /// Construct a quadrature rule, based on the local geometry-type and the
    /// polynomial degree of the integrand function.
    virtual QuadratureRule const& rule(Dune::GeometryType const& type, int degree) const
    {
      using QuadratureRules = Dune::QuadratureRules<ctype, dimension>;
      return QuadratureRules::rule(type, degree);
    }
  };


  template <class LF>
  using HasLocalFunctionOrder = decltype( order(std::declval<LF>()) );


  /// \brief Factory for quadrature rule, that calculates the coefficient order from
  /// a localFunction passed to the bind method.
  template <class ctype, int dimension, class LocalFunction>
  class QuadFactoryFromLocalFunction
      : public QuadratureFactory<ctype, dimension, LocalFunction>
  {
    using Concept = Dune::Std::is_detected<HasLocalFunctionOrder, LocalFunction>;
    static_assert(Concept::value,
      "Polynomial order of GridFunction can not be extracted. Provide an explicit order parameter instead.");

  public:
    virtual void bind(LocalFunction const& localFct) final
    {
      order_ = Dune::Hybrid::ifElse(Concept{},
        [&](auto id) { return AMDiS::order(id(localFct)); },
        [] (auto)    { return -1; });
    }

    virtual int order() const final { return order_; }

  private:
    int order_ = -1;
  };

  struct PreQuadFactoryFromLocalFunction {};

Praetorius, Simon's avatar
Praetorius, Simon committed
72
  inline auto makePreQuadratureFactory()
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  {
    return PreQuadFactoryFromLocalFunction{};
  }

  /// Generator for \ref QuadFactoryFromLocalFunction. \relates QuadFactoryFromLocalFunction
  template <class ctype, int dimension, class LocalFunction>
  auto makeQuadratureFactory(PreQuadFactoryFromLocalFunction const& /*pre*/)
  {
    return QuadFactoryFromLocalFunction<ctype, dimension, LocalFunction>{};
  }

  template <class ctype, int dimension, class LocalFunction>
  auto makeQuadratureFactoryPtr(PreQuadFactoryFromLocalFunction const& /*pre*/)
  {
    using Factory = QuadFactoryFromLocalFunction<ctype, dimension, LocalFunction>;
88
    return std::make_unique<Factory>();
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  }



  /// \brief Factory for quadrature rule, that takes to order of the localFunction
  /// and a quadrature-type
  template <class ctype, int dimension, class LocalFunction>
  class QuadFactoryFromOrder
      : public QuadratureFactory<ctype, dimension, LocalFunction>
  {
    using Super = QuadratureFactory<ctype, dimension, LocalFunction>;
    using QuadratureRule = typename Super::QuadratureRule;

  public:
    /// Constructor. Takes the order of the localCoefficient and a quadrature-type
    QuadFactoryFromOrder(int order, Dune::QuadratureType::Enum qt)
      : order_(order)
      , qt_(qt)
    {}

    virtual int order() const final { return order_; }

    virtual QuadratureRule const& rule(Dune::GeometryType const& type, int degree) const final
    {
      using QuadratureRules = Dune::QuadratureRules<ctype, dimension>;
      return QuadratureRules::rule(type, degree, qt_);
    }

  private:
    int order_;
    Dune::QuadratureType::Enum qt_;
  };

  struct PreQuadFactoryFromOrder
  {
    int order;
    Dune::QuadratureType::Enum qt;
  };

Praetorius, Simon's avatar
Praetorius, Simon committed
128
  inline auto makePreQuadratureFactory(int order, Dune::QuadratureType::Enum qt = Dune::QuadratureType::GaussLegendre)
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  {
    return PreQuadFactoryFromOrder{order, qt};
  }

  /// Generator for \ref QuadFactoryFromOrder. \relates QuadFactoryFromOrder
  template <class ctype, int dimension, class LocalFunction>
  auto makeQuadratureFactory(PreQuadFactoryFromOrder const& pre)
  {
    return QuadFactoryFromOrder<ctype, dimension, LocalFunction>{pre.order, pre.qt};
  }

  template <class ctype, int dimension, class LocalFunction>
  auto makeQuadratureFactoryPtr(PreQuadFactoryFromOrder const& pre)
  {
    using Factory = QuadFactoryFromOrder<ctype, dimension, LocalFunction>;
144
    return std::make_unique<Factory>(pre.order, pre.qt);
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  }



  /// \brief Factory for quadrature rule, that is based on an existing rule
  template <class ctype, int dimension, class LocalFunction>
  class QuadFactoryFromRule
      : public QuadratureFactory<ctype, dimension, LocalFunction>
  {
    using Super = QuadratureFactory<ctype, dimension, LocalFunction>;
    using QuadratureRule = typename Super::QuadratureRule;

  public:
    QuadFactoryFromRule(QuadratureRule const& rule)
      : rule_(rule)
    {}

    virtual QuadratureRule const& rule(Dune::GeometryType const& /*type*/, int /*degree*/) const final
    {
      return rule_;
    }

  private:
    QuadratureRule const& rule_;
  };

  template <class QuadRule>
  struct PreQuadFactoryFromRule
  {
    QuadRule const& rule;
  };

  template <class ctype, int dimension>
  auto makePreQuadratureFactory(Dune::QuadratureRule<ctype, dimension> const& rule)
  {
    return PreQuadFactoryFromRule<Dune::QuadratureRule<ctype, dimension>>{rule};
  }

  /// Generator for \ref QuadFactoryFromRule. \relates QuadFactoryFromRule
  template <class ctype, int dimension, class LocalFunction, class QuadRule>
  auto makeQuadratureFactory(PreQuadFactoryFromRule<QuadRule> const& pre)
  {
    return QuadFactoryFromRule<ctype, dimension, LocalFunction>{pre.rule};
  }

  template <class ctype, int dimension, class LocalFunction, class QuadRule>
  auto makeQuadratureFactoryPtr(PreQuadFactoryFromRule<QuadRule> const& pre)
  {
    using Factory = QuadFactoryFromRule<ctype, dimension, LocalFunction>;
194
    return std::make_unique<Factory>(pre.rule);
195
196
197
  }

} // end namespace AMDiS