DUNE-FUNCTIONS (unstable)

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