FlatPreBasis.hpp 6.17 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
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
#pragma once

#include <dune/common/version.hh>
#include <dune/functions/functionspacebases/basistags.hh>
#include <dune/functions/functionspacebases/compositebasis.hh>
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/functions/functionspacebases/powerbasis.hh>
#include <dune/functions/functionspacebases/flatmultiindex.hh>

#include <amdis/Output.hpp>
#include <amdis/common/TypeTraits.hpp>
#include <amdis/typetree/FiniteElementType.hpp>

namespace AMDiS
{
  // Convert the index-merging strategy to FlatLexicographic or FlatInterleaved for
  // composite or power bases, respectively.
  template <class PreBasis,
            class MultiIndex = Dune::Functions::FlatMultiIndex<std::size_t>>
  struct FlatPreBasis
  {
    using type = PreBasis;

    template <class PB>
    static type create(PB const& preBasis)
    {
      return {preBasis.gridView()};
    }

    static PreBasis const& create(PreBasis const& preBasis)
    {
      return preBasis;
    }
  };

  template <class PreBasis,
            class MultiIndex = Dune::Functions::FlatMultiIndex<std::size_t>>
  using FlatPreBasis_t = typename FlatPreBasis<PreBasis, MultiIndex>::type;

  template <class PreBasis>
  auto flatPreBasis(PreBasis const& preBasis)
  {
    return FlatPreBasis<PreBasis>::create(preBasis);
  }

  // specialization for Lagrange basis that needs an additional `order` parameter.
#if DUNE_VERSION_LT(DUNE_FUNCTIONS,2,7)
  template <class GV, class MI, class MultiIndex>
  struct FlatPreBasis<Dune::Functions::LagrangePreBasis<GV,-1,MI>, MultiIndex>
  {
    using type = Dune::Functions::LagrangePreBasis<GV,-1,MultiIndex>;
#else
  template <class GV, class MI, class R, class MultiIndex>
  struct FlatPreBasis<Dune::Functions::LagrangePreBasis<GV,-1,MI,R>, MultiIndex>
  {
    using type = Dune::Functions::LagrangePreBasis<GV,-1,MultiIndex,R>;
#endif

    template <class PB>
    static type create(PB const& preBasis)
    {
      auto node = preBasis.makeNode();
      node.bind(*preBasis.gridView().template begin<0>());
      return {preBasis.gridView(), (unsigned int)(polynomialDegree(node))};
    }

    static type const& create(type const& preBasis)
    {
      return preBasis;
    }
  };

  namespace Impl
  {
#if DUNE_VERSION_LT(DUNE_FUNCTIONS,2,7)
    // NOTE: dirty hack to get access to protected member variable, due to missing
    // function in dune-functions-2.6
    template <class PreBasis>
    class DerivedPreBasis {
    public:
      // specialization for PowerPreBasis
      template <class PB, class SPB = typename PB::SubPreBasis>
      static SPB const& subPreBasis(PB const& pb)
      {
        return access(pb).subPreBasis_;
      }

      // specialization for CompositePreBasis
      template <std::size_t I, class PB, class SPB = typename PB::template SubPreBasis<I>>
      static SPB const& subPreBasis(PB const& pb, Dune::index_constant<I>)
      {
        return std::get<I>(access(pb).subPreBases_);
      }

      template <class T>
      class Accessor : public T { friend class DerivedPreBasis<PreBasis>; };

      template <class T>
      static Accessor<T> const& access(T const& obj) { return static_cast<Accessor<T> const&>(obj); }
    };

    template <class PreBasis, class... Index>
    static auto const& subPreBasis(PreBasis const& preBasis, Index... ii)
    {
      return DerivedPreBasis<PreBasis>::subPreBasis(preBasis,ii...);
    }
#else
    template <class PreBasis, class... Index>
    static auto const& subPreBasis(PreBasis const& preBasis, Index... ii)
    {
      return preBasis.subPreBasis(ii...);
    }
#endif
  } // end namespace Impl


  // specialization for composite bases
  template <class MI, class IMS, class... SPB, class MultiIndex>
  struct FlatPreBasis<Dune::Functions::CompositePreBasis<MI, IMS, SPB...>, MultiIndex>
  {
    using FIMS = Dune::Functions::BasisFactory::FlatLexicographic;
    using type = Dune::Functions::CompositePreBasis<MultiIndex, FIMS, FlatPreBasis_t<SPB, MultiIndex>...>;

    template <class PreBasis>
    static type create(PreBasis const& preBasis)
    {
      return create(preBasis, std::index_sequence_for<SPB...>{});
    }

    template <class PreBasis, std::size_t... I>
    static type create(PreBasis const& preBasis, std::index_sequence<I...>)
    {
      test_warning(std::is_same_v<IMS,FIMS>, "Basis converted into flat index-merging strategy.");
      return {FlatPreBasis<SPB, MultiIndex>::create(Impl::subPreBasis(preBasis,Dune::index_constant<I>{}))...};
    }
  };

  // specialization for flat power bases
  template <class MI, class IMS, class SPB, std::size_t C, class MultiIndex>
  struct FlatPreBasis<Dune::Functions::PowerPreBasis<MI, IMS, SPB, C>, MultiIndex>
  {
    using type = Dune::Functions::PowerPreBasis<MultiIndex, IMS, SPB, C>;

    template <class PreBasis>
    static type create(PreBasis const& preBasis)
    {
      return {FlatPreBasis<SPB, MultiIndex>::create(Impl::subPreBasis(preBasis))};
    }
  };

  // specialization for blocked power bases
  template <class MI, class SPB, std::size_t C, class MultiIndex>
  struct FlatPreBasis<Dune::Functions::PowerPreBasis
    <MI, Dune::Functions::BasisFactory::BlockedInterleaved, SPB, C>, MultiIndex>
  {
    using FIMS = Dune::Functions::BasisFactory::FlatInterleaved;
    using type = Dune::Functions::PowerPreBasis<MultiIndex, FIMS, FlatPreBasis_t<SPB, MultiIndex>, C>;

    template <class PreBasis>
    static type create(PreBasis const& preBasis)
    {
      warning("Basis converted into flat index-merging strategy.");
      return {FlatPreBasis<SPB, MultiIndex>::create(Impl::subPreBasis(preBasis))};
    }
  };

  // specialization for blocked power bases
  template <class MI, class SPB, std::size_t C, class MultiIndex>
  struct FlatPreBasis<Dune::Functions::PowerPreBasis
    <MI, Dune::Functions::BasisFactory::BlockedLexicographic, SPB, C>, MultiIndex>
  {
    using FIMS = Dune::Functions::BasisFactory::FlatLexicographic;
    using type = Dune::Functions::PowerPreBasis<MultiIndex, FIMS, FlatPreBasis_t<SPB, MultiIndex>, C>;

    template <class PreBasis>
    static type create(PreBasis const& preBasis)
    {
      warning("Basis converted into flat index-merging strategy.");
      return {FlatPreBasis<SPB, MultiIndex>::create(Impl::subPreBasis(preBasis))};
    }
  };

} // end namespace AMDiS