File: referenceelements.hh

package info (click to toggle)
dune-geometry 2.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 2,304 kB
  • sloc: cpp: 15,221; python: 253; makefile: 3
file content (351 lines) | stat: -rw-r--r-- 10,256 bytes parent folder | download
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
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_GEOMETRY_REFERENCEELEMENTS_HH
#define DUNE_GEOMETRY_REFERENCEELEMENTS_HH

#include <cassert>

#include <algorithm>
#include <limits>
#include <tuple>
#include <utility>
#include <vector>
#include <array>

#include <dune/common/typetraits.hh>
#include <dune/common/std/type_traits.hh>
#include <dune/common/visibility.hh>

#include <dune/geometry/dimension.hh>
#include <dune/geometry/type.hh>
#include <dune/geometry/referenceelement.hh>
#include <dune/geometry/referenceelementimplementation.hh>

namespace Dune
{

  namespace Geo
  {

#ifndef DOXYGEN


    namespace Impl
    {

      // ReferenceElementContainer
      // -------------------------

      template< class ctype, int dim >
      class ReferenceElementContainer
      {
        static const unsigned int numTopologies = dim >= 0 ? (1u << dim) : 0;

        using Implementation   = ReferenceElementImplementation< ctype, dim >;

      public:

        using ReferenceElement = Dune::Geo::ReferenceElement< Implementation >;
        using value_type       = ReferenceElement;
        using const_iterator   = const value_type*;

        ReferenceElementContainer ()
        {
          for( unsigned int topologyId = 0; topologyId < numTopologies; ++topologyId )
            {
              implementations_[ topologyId ].initialize( topologyId );
              reference_elements_[ topologyId ].setImplementation( implementations_[ topologyId ] );
            }
        }

        const ReferenceElement& operator() ( const GeometryType &type ) const
        {
          assert( type.dim() == dim );
          return reference_elements_[ type.id() ];
        }

        const ReferenceElement& simplex () const
        {
          return reference_elements_[ Dune::GeometryTypes::simplex(dim).id() ];
        }

        const ReferenceElement& cube () const
        {
          return reference_elements_[ Dune::GeometryTypes::cube(dim).id() ];
        }

        const ReferenceElement& pyramid () const
        {
          return reference_elements_[ Dune::GeometryTypes::pyramid.id() ];
        }

        const ReferenceElement& prism () const
        {
          return reference_elements_[ Dune::GeometryTypes::prism.id() ];
        }

        const_iterator begin () const
        {
          return reference_elements_.data();
        }

        const_iterator end () const
        {
          return reference_elements_.data() + numTopologies;
        }

      private:

        std::array<Implementation,numTopologies> implementations_;
        std::array<ReferenceElement,numTopologies> reference_elements_;

      };


    } // namespace Impl


#endif // DOXYGEN


    // ReferenceElements
    // ------------------------

    /** \brief Class providing access to the singletons of the
     *  reference elements
     *
     *  Special methods are available for
     *  simplex and cube elements of any dimension.
     *  The method general can be used to obtain the reference element
     *  for a given geometry type.
     *
     *  \ingroup GeometryReferenceElements
     */
    template< class ctype_, int dim >
    struct ReferenceElements
    {

      //! The coordinate field type of the contained reference elements.
      using ctype = ctype_;

      //! The coordinate field type of the contained reference elements.
      using CoordinateField = ctype;

      //! The dimension of the contained reference elements.
      static constexpr int dimension = dim;

    private:

      using Container = Impl::ReferenceElementContainer< ctype, dim >;

    public:

      //! The reference element type.
      using ReferenceElement = typename Container::ReferenceElement;

      //! Iterator over available reference elements.
      using Iterator         = typename Container::const_iterator;

      //! Iterator over available reference elements.
      using iterator         = Iterator;

      //! get general reference elements
      static const ReferenceElement&
      general ( const GeometryType& type )
      {
        return container() ( type );
      }

      //! get simplex reference elements
      static const ReferenceElement& simplex ()
      {
        return container().simplex();
      }

      //! get hypercube reference elements
      static const ReferenceElement& cube ()
      {
        return container().cube();
      }

      static Iterator begin ()
      {
        return container().begin();
      }

      static Iterator end ()
      {
        return container().end();
      }

    private:

      DUNE_EXPORT static const Container& container ()
      {
        static Container container;
        return container;
      }
    };

  } // namespace Geo

  //! Make the ReferenceElements container available in the old location.
  using Geo::ReferenceElements;


#ifdef DOXYGEN

  //! Returns a reference element for the objects t....
  /**
   * \ingroup GeometryReferenceElements
   * The freestanding function referenceElement is a generic entry point
   * for getting reference elements for arbitrary objects that support the
   * operation. As it relies on argument-dependent lookup, the function should
   * be called without any qualifying namespace. Note, however, that the versions
   * of referenceElement() for a dimension and GeometryType with explicit template
   * arguments cannot be found by ADL, so you have to explicitly pull them in or
   * qualify the call using `Dune::`:
   *
     \code
     {
       // option 1: using
       using Dune::referenceElement;
       auto ref_el = referenceElement<double,dim>(geometry_type);
     }
     {
       // option 2: explicitly put in Dune::
       auto ref_el = Dune::referenceElement<double,dim>(geometry_type);
     }
     {
       // option 3: use version without explicit template arguments
       auto ref_el = referenceElement(double(),geometry_type,Dune::Dim<dim>());
     }
     \endcode
   *
   * The returned object is guaranteed to have value semantics, so you can copy it
   * around and store it by value.
   *
   * The grid geometries in dune-grid support this function, and thus most people
   * will use this function as
   *
     \code
     for (const auto& cell : elements(grid_view))
       {
         auto geo = cell.geometry();
         auto ref_el = referenceElement(geo);
         // do some work...
       }
     \endcode
   *
   * This does of course also work for entities of other codimensions.
   */
  template<typename... T>
  unspecified-value-type referenceElement(T&&... t);

#endif


  //! Returns a reference element of dimension dim for the given geometry type and coordinate field type.
  /**
   * This function allows you to obtain a reference element for a given coordinate type, dimension and
   * GeometryType:
   *
     \code
     auto gt = ...;
     using Dune::referenceElement;
     auto ref_el = referenceElement<ctype,dim>(gt);
     auto ref_el = referenceElement<ctype>(gt,Dune::Dim<dim>());
     \endcode
   *
   * \ingroup GeometryReferenceElements
   */
  template<typename T, int dim>
  auto referenceElement(const Dune::GeometryType& gt, Dune::Dim<dim> = {})
  {
    return ReferenceElements<T,dim>::general(gt);
  }


  //! Returns a reference element of dimension dim for the given geometry type and coordinate field type.
  /**
   * This function allows you to obtain a reference element for a given coordinate type, dimension and
   * GeometryType:
   *
     \code
     auto gt = ...;
     using Dune::referenceElement;
     auto ref_el = referenceElement(ctype(),gt,Dune::Dim<dim>());
     \endcode
   *
   * \ingroup GeometryReferenceElements
   */
  template<typename T, int dim, std::enable_if_t<IsNumber<std::decay_t<T>>::value, int> = 0>
  auto referenceElement(const T&, const Dune::GeometryType& gt, Dune::Dim<dim>)
  {
    return ReferenceElements<T,dim>::general(gt);
  }


#ifndef DOXYGEN

  // helpers for the ReferenceElement<> meta function
  // the complete Impl block can be removed together with deprecated Transitional::ReferenceElement

  namespace Impl {

    // Evaluates to the correct reference element iff <T...> matches the pattern <number_type,Dim<int>>
    // otherwise, it's ill-formed. Should be used with detected_or and friends.

    template<typename... T>
    struct DefaultReferenceElementExtractor;

    template<typename T, typename std::enable_if<IsNumber<T>::value,int>::type dim>
    struct DefaultReferenceElementExtractor<T,Dim<dim>>
    {
      using type = typename Dune::Geo::ReferenceElements<T,dim>::ReferenceElement;
    };

    template<typename... T>
    using DefaultReferenceElement = typename DefaultReferenceElementExtractor<T...>::type;

  }

  // looks up the type of a reference element by trying to instantiate the correct overload
  // of referenceElement() for the given arguments. This will fail if there is no valid
  // overload and should be used with detected_or or some other utility that places the
  // instantiation in SFINAE context.
  //
  // this is placed directly in namespace Dune to avoid any weird surprises

  template<typename... T>
  using LookupReferenceElement = decltype(referenceElement(std::declval<T>()...));

#endif // DOXYGEN

  namespace [[deprecated]] Transitional {

    // this abomination checks whether the template signature matches the special case
    // ReferenceElement<number_type,Dune::Dim<int>> and otherwise defers the type lookup
    // to a decltype on a call to referenceElement(std::declval<T>())

    /**
     * \deprecated Transitional::ReferenceElement is deprecated and will be removed after Dune 2.10.
     *             Use Dune::Geo::ReferenceElement directly.
     */
    template<typename... T>
    using ReferenceElement = detected_or_fallback_t<
      Impl::DefaultReferenceElement,
      LookupReferenceElement,
      T...
      >;

  }

  template<typename... T>
  using ReferenceElement = decltype(referenceElement(std::declval<T>()...));

} // namespace Dune

#endif // #ifndef DUNE_GEOMETRY_REFERENCEELEMENTS_HH