DUNE-FUNCTIONS (2.7)

hierarchicvectorwrapper.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_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
11#include <dune/functions/common/indexaccess.hh>
12#include <dune/functions/common/utility.hh>
13#include <dune/functions/common/type_traits.hh>
14#include <dune/functions/functionspacebases/concepts.hh>
15
16
17namespace Dune {
18namespace Functions {
19
20
21
22namespace 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
91template<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
166public:
167
168 using Vector = V;
169
170 template<class MultiIndex>
171 using Entry = Coefficient<MultiIndex>;
172
173 HierarchicVectorWrapper(Vector& vector) :
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
218 Vector& vector()
219 {
220 return *vector_;
221 }
222
223private:
224
225 Vector* vector_;
226};
227
228
229
230
231template<class V>
232HierarchicVectorWrapper< V > hierarchicVector(V& v)
233{
235}
236
237
238
239template<class MultiIndex, class V,
240 typename std::enable_if< models<Concept::HasIndexAccess, V, MultiIndex>(), int>::type = 0>
241V& makeHierarchicVectorForMultiIndex(V& v)
242{
243 return v;
244}
245
246
247
248template<class MultiIndex, class V,
249 typename std::enable_if< not models<Concept::HasIndexAccess, V, MultiIndex>(), int>::type = 0>
250HierarchicVectorWrapper< V > makeHierarchicVectorForMultiIndex(V& v)
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
A wrapper providing multiindex access to vector entries.
Definition: hierarchicvectorwrapper.hh:93
Definition: polynomial.hh:10
Check if type is a statically sized container.
Definition: type_traits.hh:83
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)