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