dune-functions 2.9.0
periodicbasis.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#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_PERIODICBASIS_HH
4#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_PERIODICBASIS_HH
5
6#include <utility>
7#include <type_traits>
8#include <limits>
9#include <set>
10#include <vector>
11
14
15
16namespace Dune::Functions {
17
18namespace BasisFactory {
19
20// The PeriodicBasis class is in the Experimental namespace because we are
21// not completely sure yet whether we like it. We reserve the right to
22// modify it without advance warning. Use at your own risk!
23
24namespace Experimental {
25
26
36{
37 using IndexPairSet = std::set<std::pair<std::size_t,std::size_t>>;
38public:
39
47 void unifyIndexPair(std::size_t a, std::size_t b)
48 {
49 if (a>b)
50 std::swap(a,b);
51 if (a==b)
52 return;
53 indexPairSet_.insert(std::make_pair(a,b));
54 }
55
56 const auto& indexPairSet() const
57 {
58 return indexPairSet_;
59 }
60
61private:
62 IndexPairSet indexPairSet_;
63};
64
65
66
67namespace Impl {
68
69// An index transformation for a TransformedIndexPreBasis
70// implementing periodic functions by merging indices.
71// Currently only flat indices are supported.
72class PeriodicIndexingTransformation
73{
74public:
75
76 static constexpr std::size_t minIndexSize = 1;
77 static constexpr std::size_t maxIndexSize = 1;
78
79 template<class RawPreBasis, class IndexPairSet>
80 PeriodicIndexingTransformation(const RawPreBasis& rawPreBasis, const IndexPairSet& indexPairSet)
81 {
82 static_assert(RawPreBasis::maxMultiIndexSize==1, "PeriodicIndexingTransformation is only implemented for flat multi-indices");
83 std::size_t invalid = {std::numeric_limits<std::size_t>::max()};
84 mappedIdx_.resize(rawPreBasis.size(), invalid);
85 numIndices_ = 0;
86 std::size_t i = 0;
87 for(const auto& [a, b] : indexPairSet)
88 {
89 for(; i<=a; ++i)
90 if (mappedIdx_[i] == invalid)
91 mappedIdx_[i] = numIndices_++;
92 mappedIdx_[b] = mappedIdx_[a];
93 }
94 for(; i<rawPreBasis.size(); ++i)
95 if (mappedIdx_[i] == invalid)
96 mappedIdx_[i] = numIndices_++;
97 }
98
99 template<class MultiIndex, class PreBasis>
100 void transformIndex(MultiIndex& multiIndex, const PreBasis& preBasis) const
101 {
102 multiIndex = {{ mappedIdx_[multiIndex[0]] }};
103 }
104
105 template<class Prefix, class PreBasis>
106 std::size_t size(const Prefix& prefix, const PreBasis& preBasis) const
107 {
108 if (prefix.size() == 1)
109 return 0;
110 return numIndices_;
111 }
112
113 template<class PreBasis>
114 auto dimension(const PreBasis& preBasis) const
115 {
116 return numIndices_;
117 }
118
119private:
120 std::vector<std::size_t> mappedIdx_;
121 std::size_t numIndices_;
122};
123
124
125
126template<class RawPreBasisIndicator>
127class PeriodicPreBasisFactory
128{
129public:
130 PeriodicPreBasisFactory()
131 {}
132
133 template<class RPBI, class PIS>
134 PeriodicPreBasisFactory(RPBI&& rawPreBasisIndicator, PIS&& periodicIndexSet) :
135 rawPreBasisIndicator_(std::forward<RPBI>(rawPreBasisIndicator)),
136 periodicIndexSet_(std::forward<PIS>(periodicIndexSet))
137 {}
138
139 template<class GridView,
140 std::enable_if_t<models<Concept::GlobalBasis<GridView>,RawPreBasisIndicator>(), int> = 0>
141 auto operator()(const GridView& gridView) const
142 {
143 const auto& rawPreBasis = rawPreBasisIndicator_.preBasis();
144 auto transformation = PeriodicIndexingTransformation(rawPreBasis, periodicIndexSet_.indexPairSet());
145 return Dune::Functions::Experimental::TransformedIndexPreBasis(std::move(rawPreBasis), std::move(transformation));
146 }
147
148 template<class GridView,
149 std::enable_if_t<models<Concept::PreBasis<GridView>,RawPreBasisIndicator>(), int> = 0>
150 auto operator()(const GridView& gridView) const
151 {
152 const auto& rawPreBasis = rawPreBasisIndicator_;
153 auto transformation = PeriodicIndexingTransformation(rawPreBasis, periodicIndexSet_.indexPairSet());
154 return Dune::Functions::Experimental::TransformedIndexPreBasis(std::move(rawPreBasis), std::move(transformation));
155 }
156
157 template<class GridView,
158 std::enable_if_t<not models<Concept::GlobalBasis<GridView>,RawPreBasisIndicator>(), int> = 0,
159 std::enable_if_t<not models<Concept::PreBasis<GridView>,RawPreBasisIndicator>(), int> = 0>
160 auto operator()(const GridView& gridView) const
161 {
162 auto rawPreBasis = rawPreBasisIndicator_(gridView);
163 rawPreBasis.initializeIndices();
164 auto transformation = PeriodicIndexingTransformation(rawPreBasis, periodicIndexSet_.indexPairSet());
165 return Dune::Functions::Experimental::TransformedIndexPreBasis(std::move(rawPreBasis), std::move(transformation));
166 }
167
168private:
169 RawPreBasisIndicator rawPreBasisIndicator_;
170 PeriodicIndexSet periodicIndexSet_;
171};
172
173} // end namespace BasisFactory::Impl
174
175
176
190template<class RawPreBasisIndicator, class PIS>
192 RawPreBasisIndicator&& rawPreBasisIndicator,
193 PIS&& periodicIndexSet
194 )
195{
196 return Impl::PeriodicPreBasisFactory<std::decay_t<RawPreBasisIndicator>>(
197 std::forward<RawPreBasisIndicator>(rawPreBasisIndicator),
198 std::forward<PIS>(periodicIndexSet));
199}
200
201} // end namespace Experimental
202
203} // end namespace BasisFactory
204
205} // end namespace Dune::Functions
206
207#endif // DUNE_FUFEM_PERIODICBASIS_HH
auto periodic(RawPreBasisIndicator &&rawPreBasisIndicator, PIS &&periodicIndexSet)
Create a pre-basis factory that can create a periodic pre-basis.
Definition: periodicbasis.hh:191
Definition: polynomial.hh:11
TransformedIndexPreBasis(RPB &&, T &&) -> TransformedIndexPreBasis< std::decay_t< RPB >, std::decay_t< T > >
Container storing identified indices for a periodic basis.
Definition: periodicbasis.hh:36
void unifyIndexPair(std::size_t a, std::size_t b)
Insert a pair of indices.
Definition: periodicbasis.hh:47
const auto & indexPairSet() const
Definition: periodicbasis.hh:56