dune-functions  2.8.0
hierarchicvectorwrapper.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_HIERARCHICVECTORWRAPPER_HH
4 #define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_HIERARCHICVECTORWRAPPER_HH
5 
6 #include <dune/common/concept.hh>
7 #include <dune/common/hybridutilities.hh>
8 #include <dune/common/indices.hh>
9 
14 
15 
16 namespace Dune {
17 namespace Functions {
18 
19 
20 
21 namespace Imp {
22 
23  // Construct default coefficent type from vector and multiindex type
24  // This requires that MultiIndex has a static size. Otherwise the
25  // vector type itself is returned.
26  template<class V, class MultiIndex>
27  struct CoefficientType
28  {
29  template<class E, std::size_t size>
30  struct DefaultCoefficientTypeHelper
31  {
32  using E0 = decltype(std::declval<E>()[Dune::Indices::_0]);
33  using type = typename DefaultCoefficientTypeHelper<E0, size-1>::type;
34  };
35 
36  template<class E>
37  struct DefaultCoefficientTypeHelper<E, 0>
38  {
39  using type = E;
40  };
41 
42  template<class MI,
43  typename std::enable_if<HasStaticSize<MI>::value, int>::type = 0>
44  static constexpr std::size_t getStaticSizeOrZero()
45  {
46  return StaticSize<MI>::value;
47  }
48 
49  template<class MI,
50  typename std::enable_if<not HasStaticSize<MI>::value, int>::type = 0>
51  static constexpr std::size_t getStaticSizeOrZero()
52  {
53  return 0;
54  }
55 
56  using type = typename DefaultCoefficientTypeHelper<V, getStaticSizeOrZero<MultiIndex>()>::type;
57  };
58 
59 
60 
61  // This tag class is used as Coefficient template parameter
62  // for HierarchicVectorWrapper if the coefficient type should
63  // be deduced.
64  struct DeducedCoefficientTag {};
65 
66 } // namespace Imp
67 
68 
69 
90 template<class V, class CO=Imp::DeducedCoefficientTag>
92 {
93  template<class MultiIndex>
94  using Coefficient = typename std::conditional< std::is_same<Imp::DeducedCoefficientTag,CO>::value and HasStaticSize<MultiIndex>::value,
95  typename Imp::CoefficientType<V, MultiIndex>::type,
96  CO
97  >::type;
98 
99 
100  using size_type = std::size_t;
101 
102  template<class C, class SizeProvider,
103  typename std::enable_if< not models<Concept::HasResize, C>(), int>::type = 0,
104  typename std::enable_if< not models<Concept::HasSizeMethod, C>(), int>::type = 0>
105  static void resizeHelper(C& c, const SizeProvider& sizeProvider, typename SizeProvider::SizePrefix prefix)
106  {
107  auto size = sizeProvider.size(prefix);
108  if (size != 0)
109  DUNE_THROW(RangeError, "Can't resize scalar vector entry v[" << prefix << "] to size(" << prefix << ")=" << size);
110  }
111 
112  struct StaticResizeHelper
113  {
114  template<class I, class C, class SizeProvider>
115  static void apply(I&& i, C& c, const SizeProvider& sizeProvider, typename SizeProvider::SizePrefix prefix)
116  {
117  prefix.back() = i;
118  resizeHelper(c[i], sizeProvider, prefix);
119  }
120  };
121 
122  template<class C, class SizeProvider,
123  typename std::enable_if< not models<Concept::HasResize, C>(), int>::type = 0,
124  typename std::enable_if< models<Concept::HasSizeMethod, C>(), int>::type = 0>
125  static void resizeHelper(C& c, const SizeProvider& sizeProvider, typename SizeProvider::SizePrefix prefix)
126  {
127  auto size = sizeProvider.size(prefix);
128  if (size == 0)
129  return;
130 
131  if (c.size() != size)
132  DUNE_THROW(RangeError, "Can't resize statically sized vector entry v[" << prefix << "] of size " << c.size() << " to size(" << prefix << ")=" << size);
133 
134  using namespace Dune::Hybrid;
135  prefix.push_back(0);
136  forEach(integralRange(Hybrid::size(c)), [&](auto&& i) {
137  StaticResizeHelper::apply(i, c, sizeProvider, prefix);
138  });
139  }
140 
141  template<class C, class SizeProvider,
142  typename std::enable_if< models<Concept::HasResize, C>(), int>::type = 0>
143  static void resizeHelper(C& c, const SizeProvider& sizeProvider, typename SizeProvider::SizePrefix prefix)
144  {
145  auto size = sizeProvider.size(prefix);
146  if (size==0)
147  {
148  if (c.size()==0)
149  DUNE_THROW(RangeError, "Can't resize dynamically sized vector entry v[" << prefix << "]. Its size is 0 but the target size is unknown due to size(" << prefix << ")=0.");
150  else
151  return;
152  }
153 
154  c.resize(size);
155  prefix.push_back(0);
156  for(std::size_t i=0; i<size; ++i)
157  {
158  prefix.back() = i;
159  resizeHelper(c[i], sizeProvider, prefix);
160  }
161  }
162 
163 
164 
165 public:
166 
167  using Vector = V;
168 
169  template<class MultiIndex>
170  using Entry = Coefficient<MultiIndex>;
171 
173  vector_(&vector)
174  {}
175 
176  template<class SizeProvider>
177  void resize(const SizeProvider& sizeProvider)
178  {
179  typename SizeProvider::SizePrefix prefix;
180  prefix.resize(0);
181  resizeHelper(*vector_, sizeProvider, prefix);
182  }
183 
184  template<class MultiIndex>
185  const Entry<MultiIndex>& operator[](const MultiIndex& index) const
186  {
187  static_assert(not std::is_same<Imp::DeducedCoefficientTag,Entry<MultiIndex>>::value, "Coefficient type for HierarchicVectorWrapper and given multi-index type cannot be determined automatically!");
188  return hybridMultiIndexAccess<const Entry<MultiIndex>&>(*vector_, index);
189  }
190 
191  template<class MultiIndex>
192  Entry<MultiIndex>& operator[](const MultiIndex& index)
193  {
194  static_assert(not std::is_same<Imp::DeducedCoefficientTag,Entry<MultiIndex>>::value, "Coefficient type for HierarchicVectorWrapper and given multi-index type cannot be determined automatically!");
195  return hybridMultiIndexAccess<Entry<MultiIndex>&>(*vector_, index);
196  }
197 
198  template<class MultiIndex>
199  const Entry<MultiIndex>& operator()(const MultiIndex& index) const
200  {
201  static_assert(not std::is_same<Imp::DeducedCoefficientTag,Entry<MultiIndex>>::value, "Coefficient type for HierarchicVectorWrapper and given multi-index type cannot be determined automatically!");
202  return (*this)[index];
203  }
204 
205  template<class MultiIndex>
206  Entry<MultiIndex>& operator()(const MultiIndex& index)
207  {
208  static_assert(not std::is_same<Imp::DeducedCoefficientTag,Entry<MultiIndex>>::value, "Coefficient type for HierarchicVectorWrapper and given multi-index type cannot be determined automatically!");
209  return (*this)[index];
210  }
211 
212  const Vector& vector() const
213  {
214  return *vector_;
215  }
216 
218  {
219  return *vector_;
220  }
221 
222 private:
223 
224  Vector* vector_;
225 };
226 
227 
228 
229 
230 template<class V>
232 {
233  return HierarchicVectorWrapper<V>(v);
234 }
235 
236 
237 
238 template<class MultiIndex, class V,
239  typename std::enable_if< models<Concept::HasIndexAccess, V, MultiIndex>(), int>::type = 0>
241 {
242  return v;
243 }
244 
245 
246 
247 template<class MultiIndex, class V,
248  typename std::enable_if< not models<Concept::HasIndexAccess, V, MultiIndex>(), int>::type = 0>
250 {
251  return HierarchicVectorWrapper<V>(v);
252 }
253 
254 
255 
256 } // namespace Dune::Functions
257 } // namespace Dune
258 
259 
260 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_HIERARCHICVECTORWRAPPER_HH
Definition: polynomial.hh:10
V & makeHierarchicVectorForMultiIndex(V &v)
Definition: hierarchicvectorwrapper.hh:240
HierarchicVectorWrapper< V > hierarchicVector(V &v)
Definition: hierarchicvectorwrapper.hh:231
Check if type is a statically sized container.
Definition: type_traits.hh:83
A wrapper providing multiindex access to vector entries.
Definition: hierarchicvectorwrapper.hh:92
const Entry< MultiIndex > & operator()(const MultiIndex &index) const
Definition: hierarchicvectorwrapper.hh:199
Entry< MultiIndex > & operator()(const MultiIndex &index)
Definition: hierarchicvectorwrapper.hh:206
Vector & vector()
Definition: hierarchicvectorwrapper.hh:217
V Vector
Definition: hierarchicvectorwrapper.hh:167
Coefficient< MultiIndex > Entry
Definition: hierarchicvectorwrapper.hh:170
const Vector & vector() const
Definition: hierarchicvectorwrapper.hh:212
const Entry< MultiIndex > & operator[](const MultiIndex &index) const
Definition: hierarchicvectorwrapper.hh:185
Entry< MultiIndex > & operator[](const MultiIndex &index)
Definition: hierarchicvectorwrapper.hh:192
HierarchicVectorWrapper(Vector &vector)
Definition: hierarchicvectorwrapper.hh:172
void resize(const SizeProvider &sizeProvider)
Definition: hierarchicvectorwrapper.hh:177