dune-functions 2.9.0
powerbasis.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_POWERBASIS_HH
4#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_POWERBASIS_HH
5
6#include <dune/common/reservedvector.hh>
7#include <dune/common/typeutilities.hh>
8#include <dune/common/indices.hh>
9
16
17
18
19namespace Dune {
20namespace Functions {
21
22
23// *****************************************************************************
24// This is the reusable part of the power bases. It contains
25//
26// PowerPreBasis
27//
28// The pre-basis allows to create the others and is the owner of possible shared
29// state. These components do _not_ depend on the global basis and local view
30// and can be used without a global basis.
31// *****************************************************************************
32
43template<class IMS, class SPB, std::size_t C>
45{
46 static const std::size_t children = C;
47 static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
48
49public:
50
52 using SubPreBasis = SPB;
53
55 using GridView = typename SPB::GridView;
56
58 using size_type = std::size_t;
59
62
63 using SubNode = typename SubPreBasis::Node;
64
67
68 static constexpr size_type maxMultiIndexSize = SubPreBasis::maxMultiIndexSize + isBlocked;
69 static constexpr size_type minMultiIndexSize = SubPreBasis::minMultiIndexSize + isBlocked;
70 static constexpr size_type multiIndexBufferSize = SubPreBasis::multiIndexBufferSize + isBlocked;
71
77 template<class... SFArgs,
78 disableCopyMove<PowerPreBasis, SFArgs...> = 0,
79 enableIfConstructible<SubPreBasis, SFArgs...> = 0>
80 PowerPreBasis(SFArgs&&... sfArgs) :
81 subPreBasis_(std::forward<SFArgs>(sfArgs)...)
82 {
83 static_assert(models<Concept::PreBasis<GridView>, SubPreBasis>(), "Subprebasis passed to PowerPreBasis does not model the PreBasis concept.");
84 }
85
88 {
89 subPreBasis_.initializeIndices();
90 }
91
93 const GridView& gridView() const
94 {
95 return subPreBasis_.gridView();
96 }
97
99 void update(const GridView& gv)
100 {
101 subPreBasis_.update(gv);
102 }
103
108 {
109 auto node = Node{};
110 for (std::size_t i=0; i<children; ++i)
111 node.setChild(i, subPreBasis_.makeNode());
112 return node;
113 }
114
117 {
118 return size(Dune::ReservedVector<size_type, multiIndexBufferSize>{});
119 }
120
122
123 template<class SizePrefix>
124 size_type size(const SizePrefix& prefix) const
125 {
126 return size(prefix, IndexMergingStrategy{});
127 }
128
129private:
130
131 template<class SizePrefix>
132 size_type size(const SizePrefix& prefix, BasisFactory::FlatInterleaved) const
133 {
134 // The root index size is the root index size of a single subnode
135 // multiplied by the number of subnodes because we enumerate all
136 // child indices in a row.
137 if (prefix.size() == 0)
138 return children*subPreBasis_.size();
139
140 // The first prefix entry refers to one of the (root index size)
141 // subindex trees. Hence we have to first compute the corresponding
142 // prefix entry for a single subnode subnode. The we can append
143 // the other prefix entries unmodified, because the index tree
144 // looks the same after the first level.
145 SizePrefix subPrefix;
146 subPrefix.push_back(prefix[0] / children);
147 for(std::size_t i=1; i<prefix.size(); ++i)
148 subPrefix.push_back(prefix[i]);
149 return subPreBasis_.size(subPrefix);
150 }
151
152 template<class SizePrefix>
153 size_type size(const SizePrefix& prefix, BasisFactory::FlatLexicographic) const
154 {
155 // The size at the index tree root is the size of at the index tree
156 // root of a single subnode multiplied by the number of subnodes
157 // because we enumerate all child indices in a row.
158 if (prefix.size() == 0)
159 return children*subPreBasis_.size();
160
161 // The first prefix entry refers to one of the (root index size)
162 // subindex trees. Hence we have to first compute the corresponding
163 // prefix entry for a single subnode subnode. The we can append
164 // the other prefix entries unmodified, because the index tree
165 // looks the same after the first level.
166 SizePrefix subPrefix;
167 subPrefix.push_back(prefix[0] % children);
168 for(std::size_t i=1; i<prefix.size(); ++i)
169 subPrefix.push_back(prefix[i]);
170 return subPreBasis_.size(subPrefix);
171 }
172
173 template<class SizePrefix>
174 size_type size(const SizePrefix& prefix, BasisFactory::BlockedLexicographic) const
175 {
176 if (prefix.size() == 0)
177 return children;
178 SizePrefix subPrefix;
179 for(std::size_t i=1; i<prefix.size(); ++i)
180 subPrefix.push_back(prefix[i]);
181 return subPreBasis_.size(subPrefix);
182 }
183
184 template<class SizePrefix>
185 size_type size(const SizePrefix& prefix, BasisFactory::BlockedInterleaved) const
186 {
187 if (prefix.size() == 0)
188 return subPreBasis_.size();
189
190 SizePrefix subPrefix;
191 for(std::size_t i=0; i<prefix.size()-1; ++i)
192 subPrefix.push_back(prefix[i]);
193
194 size_type r = subPreBasis_.size(subPrefix);
195 if (r==0)
196 return 0;
197 subPrefix.push_back(prefix.back());
198 r = subPreBasis_.size(subPrefix);
199 if (r==0)
200 return children;
201 return r;
202 }
203
204public:
205
208 {
209 return subPreBasis_.dimension() * children;
210 }
211
214 {
215 return subPreBasis_.maxNodeSize() * children;
216 }
217
220 {
221 return subPreBasis_;
222 }
223
226 {
227 return subPreBasis_;
228 }
229
231 template<typename It>
232 It indices(const Node& node, It it) const
233 {
234 return indices(node, it, IndexMergingStrategy{});
235 }
236
237private:
238
239 template<typename It>
240 It indices(const Node& node, It multiIndices, BasisFactory::FlatInterleaved) const
241 {
242 using namespace Dune::Indices;
243 size_type subTreeSize = node.child(_0).size();
244 // Fill indices for first child at the beginning.
245 auto next = subPreBasis().indices(node.child(_0), multiIndices);
246 // Multiply first component of all indices for first child by
247 // number of children to stretch the index range for interleaving.
248 for (std::size_t i = 0; i<subTreeSize; ++i)
249 multiIndices[i][0] *= children;
250 for (std::size_t child = 1; child<children; ++child)
251 {
252 for (std::size_t i = 0; i<subTreeSize; ++i)
253 {
254 // Copy indices from first child for all other children
255 // and shift them by child index to interleave indices.
256 // multiIndices[child*subTreeSize+i] = multiIndices[i];
257 // multiIndices[child*subTreeSize+i][0] = multiIndices[i][0]+child;
258 (*next) = multiIndices[i];
259 (*next)[0] = multiIndices[i][0]+child;
260 ++next;
261 }
262 }
263 return next;
264 }
265
266 template<typename It>
267 It indices(const Node& node, It multiIndices, BasisFactory::FlatLexicographic) const
268 {
269 using namespace Dune::Indices;
270 size_type subTreeSize = node.child(_0).size();
271 size_type firstIndexEntrySize = subPreBasis().size();
272 // Fill indices for first child at the beginning.
273 auto next = subPreBasis().indices(node.child(_0), multiIndices);
274 for (std::size_t child = 1; child<children; ++child)
275 {
276 for (std::size_t i = 0; i<subTreeSize; ++i)
277 {
278 // Copy indices from first child for all other children
279 // and shift them by suitable offset to get lexicographic indices.
280 // multiIndices[child*subTreeSize+i] = multiIndices[i];
281 // multiIndices[child*subTreeSize+i][0] += child*firstIndexEntrySize;
282 (*next) = multiIndices[i];
283 (*next)[0] += child*firstIndexEntrySize;
284 ++next;
285 }
286 }
287 return next;
288 }
289
290 template<class MultiIndex>
291 static void multiIndexPushFront(MultiIndex& M, size_type M0)
292 {
293 M.resize(M.size()+1);
294 for(std::size_t i=M.size()-1; i>0; --i)
295 M[i] = M[i-1];
296 M[0] = M0;
297 }
298
299 template<typename It>
300 It indices(const Node& node, It multiIndices, BasisFactory::BlockedLexicographic) const
301 {
302 using namespace Dune::Indices;
303 size_type subTreeSize = node.child(_0).size();
304 // Fill indices for first child at the beginning.
305 auto next = subPreBasis().indices(node.child(_0), multiIndices);
306 // Insert 0 before first component of all indices for first child.
307 for (std::size_t i = 0; i<subTreeSize; ++i)
308 multiIndexPushFront(multiIndices[i], 0);
309 for (std::size_t child = 1; child<children; ++child)
310 {
311 for (std::size_t i = 0; i<subTreeSize; ++i)
312 {
313 // Copy indices from first child for all other children and overwrite
314 // zero in first component as inserted above by child index.
315 // multiIndices[child*subTreeSize+i] = multiIndices[i];
316 // multiIndices[child*subTreeSize+i][0] = child;
317 (*next) = multiIndices[i];
318 (*next)[0] = child;
319 ++next;
320 }
321 }
322 return next;
323 }
324
325 template<typename It>
326 It indices(const Node& node, It multiIndices, BasisFactory::BlockedInterleaved) const
327 {
328 using namespace Dune::Indices;
329 size_type subTreeSize = node.child(_0).size();
330 // Fill indices for first child at the beginning.
331 auto next = subPreBasis().indices(node.child(_0), multiIndices);
332 // Append 0 after last component of all indices for first child.
333 for (std::size_t i = 0; i<subTreeSize; ++i)
334 multiIndices[i].push_back(0);
335 for (std::size_t child = 1; child<children; ++child)
336 {
337 for (std::size_t i = 0; i<subTreeSize; ++i)
338 {
339 // Copy indices from first child for all other children and overwrite
340 // zero in last component as appended above by child index.
341 (*next) = multiIndices[i];
342 (*next).back() = child;
343 ++next;
344 }
345 }
346 return next;
347 }
348
349 SubPreBasis subPreBasis_;
350};
351
352
353
354namespace BasisFactory {
355
368template<std::size_t k, class ChildPreBasisFactory, class IndexMergingStrategy>
369auto power(ChildPreBasisFactory&& childPreBasisFactory, const IndexMergingStrategy&)
370{
371 return [childPreBasisFactory](const auto& gridView) {
372 auto childPreBasis = childPreBasisFactory(gridView);
374 };
375}
376
387template<std::size_t k, class ChildPreBasisFactory>
388auto power(ChildPreBasisFactory&& childPreBasisFactory)
389{
390 return [childPreBasisFactory](const auto& gridView) {
391 auto childPreBasis = childPreBasisFactory(gridView);
393 };
394}
395
396} // end namespace BasisFactory
397
398// Backward compatibility
399namespace BasisBuilder {
400
401 using namespace BasisFactory;
402
403}
404
405
406} // end namespace Functions
407} // end namespace Dune
408
409
410#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_POWERBASIS_HH
auto power(ChildPreBasisFactory &&childPreBasisFactory)
Create a factory builder that can build a PowerPreBasis.
Definition: powerbasis.hh:388
typename std::enable_if< std::is_constructible< T, Args... >::value, int >::type enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:26
Definition: polynomial.hh:10
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:44
Interleaved merging of direct children without blocking.
Definition: basistags.hh:114
Definition: nodes.hh:193
A pre-basis for power bases.
Definition: powerbasis.hh:45
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: powerbasis.hh:207
std::size_t size_type
Type used for indices and size information.
Definition: powerbasis.hh:58
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: powerbasis.hh:61
PowerBasisNode< SubNode, children > Node
Template mapping root tree path to type of created tree node.
Definition: powerbasis.hh:66
typename SPB::GridView GridView
The grid view that the FE basis is defined on.
Definition: powerbasis.hh:55
static constexpr size_type multiIndexBufferSize
Definition: powerbasis.hh:70
SPB SubPreBasis
The child pre-basis.
Definition: powerbasis.hh:52
typename SubPreBasis::Node SubNode
Definition: powerbasis.hh:63
void initializeIndices()
Initialize the global indices.
Definition: powerbasis.hh:87
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: powerbasis.hh:99
It indices(const Node &node, It it) const
Maps from subtree index set [0..size-1] to a globally unique multi index in global basis.
Definition: powerbasis.hh:232
PowerPreBasis(SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: powerbasis.hh:80
size_type size() const
Same as size(prefix) with empty prefix.
Definition: powerbasis.hh:116
SubPreBasis & subPreBasis()
Mutable access to the stored prebasis of the factor in the power space.
Definition: powerbasis.hh:225
Node makeNode() const
Create tree node.
Definition: powerbasis.hh:107
static constexpr size_type maxMultiIndexSize
Definition: powerbasis.hh:68
static constexpr size_type minMultiIndexSize
Definition: powerbasis.hh:69
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: powerbasis.hh:213
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: powerbasis.hh:93
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: powerbasis.hh:124
const SubPreBasis & subPreBasis() const
Const access to the stored prebasis of the factor in the power space.
Definition: powerbasis.hh:219