DUNE PDELab (git)

dynamicpowerbasis.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_DYNAMICPOWERBASIS_HH
4#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
5
8#include <dune/common/indices.hh>
9
10#include <dune/functions/common/utility.hh>
11#include <dune/functions/common/type_traits.hh>
12#include <dune/functions/functionspacebases/basistags.hh>
13#include <dune/functions/functionspacebases/containerdescriptors.hh>
14#include <dune/functions/functionspacebases/nodes.hh>
15#include <dune/functions/functionspacebases/concepts.hh>
16
17
18
19namespace Dune {
20namespace Functions {
21
22
23// *****************************************************************************
24// This is the reusable part of the dynamic power bases. It contains
25//
26// DynamicPowerPreBasis
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
42template<class IMS, class SPB>
44{
45 static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
46
47public:
48
50 using SubPreBasis = SPB;
51
53 using GridView = typename SPB::GridView;
54
56 using size_type = std::size_t;
57
60
62 using Node = DynamicPowerBasisNode<typename SubPreBasis::Node>;
63
64 static constexpr size_type maxMultiIndexSize = SubPreBasis::maxMultiIndexSize + isBlocked;
65 static constexpr size_type minMultiIndexSize = SubPreBasis::minMultiIndexSize + isBlocked;
66 static constexpr size_type multiIndexBufferSize = SubPreBasis::multiIndexBufferSize + isBlocked;
67
73 template<class... SFArgs,
75 enableIfConstructible<SubPreBasis, SFArgs...> = 0>
76 explicit DynamicPowerPreBasis(std::size_t c, SFArgs&&... sfArgs) :
77 children_(c),
78 subPreBasis_(std::forward<SFArgs>(sfArgs)...)
79 {
80 static_assert(models<Concept::PreBasis<GridView>, SubPreBasis>(), "Subprebasis passed to DynamicPowerPreBasis does not model the PreBasis concept.");
81 }
82
85 {
86 subPreBasis_.initializeIndices();
87 }
88
90 const GridView& gridView() const
91 {
92 return subPreBasis_.gridView();
93 }
94
96 void update(const GridView& gv)
97 {
98 subPreBasis_.update(gv);
99 }
100
105 {
106 auto node = Node{children_};
107 for (std::size_t i=0; i<children_; ++i)
108 node.setChild(i, subPreBasis_.makeNode());
109 return node;
110 }
111
112 std::size_t children() const
113 {
114 return children_;
115 }
116
119 {
121 }
122
124 template<class SizePrefix>
125 size_type size(const SizePrefix& prefix) const
126 {
127 return sizeImpl(prefix, children_, IndexMergingStrategy{});
128 }
129
130protected:
131
132 template<class SizePrefix, class Children>
133 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatInterleaved) const
134 {
135 // The root index size is the root index size of a single subnode
136 // multiplied by the number of subnodes, because we enumerate all
137 // child indices in a row.
138 if (prefix.size() == 0)
139 return children*subPreBasis_.size();
140
141 // The FlatInterleaved index merging strategy only changes the first
142 // index digit. Hence, we have to reconstruct the corresponding digit
143 // for the subtree and can then return the corresponding size of the subtree.
144 prefix[0] = prefix[0] / children;
145 return subPreBasis_.size(prefix);
146 }
147
148 template<class SizePrefix, class Children>
149 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatLexicographic) const
150 {
151 // The size at the index tree root is the size of at the index tree
152 // root of a single subnode multiplied by the number of subnodes,
153 // because we enumerate all child indices in a row.
154 if (prefix.size() == 0)
155 return children*subPreBasis_.size();
156
157 // The first prefix entry refers to one of the (root index size)
158 // subindex trees. Hence, we have to first compute the corresponding
159 // prefix entry for a single subnode subnode. Then we can append
160 // the other prefix entries unmodified, because the index tree
161 // looks the same after the first level.
162
163 // The FlatLexicographic index merging strategy only changes the first
164 // index digit. Hence, we have to reconstruct the corresponding digit
165 // for the subtree and can then return the corresponding size of the subtree.
166 prefix[0] = prefix[0] % subPreBasis_.size();
167 return subPreBasis_.size(prefix);
168 }
169
170 template<class MultiIndex>
171 static void multiIndexPopFront(MultiIndex& M)
172 {
173 for(std::size_t i=0; i<M.size()-1; ++i)
174 M[i] = M[i+1];
175 M.resize(M.size()-1);
176 }
177
178 template<class SizePrefix, class Children>
179 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedLexicographic) const
180 {
181 if (prefix.size() == 0)
182 return children;
183 multiIndexPopFront(prefix);
184 return subPreBasis_.size(prefix);
185 }
186
187 template<class SizePrefix, class Children>
188 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedInterleaved) const
189 {
190 if (prefix.size() == 0)
191 return subPreBasis_.size();
192
193 // Remember last index, remove it and check if the remaining
194 // prefix refers to a leaf in the subPreBasis index tree.
195 // If yes, then the full prefix must also refer to a
196 // leaf in the merged index tree. If not, then restore the full
197 // prefix and proceed.
198 auto tail = prefix.back();
199 prefix.pop_back();
200 if (subPreBasis_.size(prefix) == 0)
201 return 0;
202 prefix.push_back(tail);
203
204 // Now check if the full prefix refers to a leaf in the subPreBasis
205 // index tree.
206 // If yes, then it has exactly 'children' appended children in the subtree.
207 // If not, then the index tree looks the same in the merged subtree and we
208 // can forward the result.
209 auto subSize = subPreBasis_.size(prefix);
210 if (subSize == 0)
211 return children;
212 return subSize;
213 }
214
215public:
216
219 {
220 return subPreBasis_.dimension() * children_;
221 }
222
225 {
226 return subPreBasis_.maxNodeSize() * children_;
227 }
228
231 {
232 return subPreBasis_;
233 }
234
237 {
238 return subPreBasis_;
239 }
240
242 template<class NodeType, typename It,
243 std::enable_if_t<NodeType::isPower, int> = 0>
244 It indices(const NodeType& node, It it) const
245 {
246 return indicesImpl(node, it, children_, IndexMergingStrategy{});
247 }
248
251 {
252 return containerDescriptorImpl(children_);
253 }
254
255protected:
256
257 template<class NodeType, typename It, class Children>
258 It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::FlatInterleaved) const
259 {
260 using namespace Dune::Indices;
261 size_type subTreeSize = node.child(_0).size();
262 // Fill indices for first child at the beginning.
263 auto next = subPreBasis().indices(node.child(_0), multiIndices);
264 // Multiply first component of all indices for first child by
265 // number of children to stretch the index range for interleaving.
266 for (std::size_t i = 0; i<subTreeSize; ++i)
267 multiIndices[i][0] *= children;
268 for (std::size_t child = 1; child<children; ++child)
269 {
270 for (std::size_t i = 0; i<subTreeSize; ++i)
271 {
272 // Copy indices from first child for all other children
273 // and shift them by child index to interleave indices.
274 // multiIndices[child*subTreeSize+i] = multiIndices[i];
275 // multiIndices[child*subTreeSize+i][0] = multiIndices[i][0]+child;
276 (*next) = multiIndices[i];
277 (*next)[0] = multiIndices[i][0]+child;
278 ++next;
279 }
280 }
281 return next;
282 }
283
284 template<class NodeType, typename It, class Children>
285 It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::FlatLexicographic) const
286 {
287 using namespace Dune::Indices;
288 size_type subTreeSize = node.child(_0).size();
289 size_type firstIndexEntrySize = subPreBasis().size();
290 // Fill indices for first child at the beginning.
291 auto next = subPreBasis().indices(node.child(_0), multiIndices);
292 for (std::size_t child = 1; child<children_; ++child)
293 {
294 for (std::size_t i = 0; i<subTreeSize; ++i)
295 {
296 // Copy indices from first child for all other children
297 // and shift them by suitable offset to get lexicographic indices.
298 // multiIndices[child*subTreeSize+i] = multiIndices[i];
299 // multiIndices[child*subTreeSize+i][0] += child*firstIndexEntrySize;
300 (*next) = multiIndices[i];
301 (*next)[0] += child*firstIndexEntrySize;
302 ++next;
303 }
304 }
305 return next;
306 }
307
308 template<class MultiIndex>
309 static void multiIndexPushFront(MultiIndex& M, size_type M0)
310 {
311 M.resize(M.size()+1);
312 for(std::size_t i=M.size()-1; i>0; --i)
313 M[i] = M[i-1];
314 M[0] = M0;
315 }
316
317 template<class NodeType, typename It, class Children>
318 It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedLexicographic) const
319 {
320 using namespace Dune::Indices;
321 size_type subTreeSize = node.child(_0).size();
322 // Fill indices for first child at the beginning.
323 auto next = subPreBasis().indices(node.child(_0), multiIndices);
324 // Insert 0 before first component of all indices for first child.
325 for (std::size_t i = 0; i<subTreeSize; ++i)
326 multiIndexPushFront(multiIndices[i], 0);
327 for (std::size_t child = 1; child<children_; ++child)
328 {
329 for (std::size_t i = 0; i<subTreeSize; ++i)
330 {
331 // Copy indices from first child for all other children and overwrite
332 // zero in first component as inserted above by child index.
333 // multiIndices[child*subTreeSize+i] = multiIndices[i];
334 // multiIndices[child*subTreeSize+i][0] = child;
335 (*next) = multiIndices[i];
336 (*next)[0] = child;
337 ++next;
338 }
339 }
340 return next;
341 }
342
343 template<class NodeType, typename It, class Children>
344 It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedInterleaved) const
345 {
346 using namespace Dune::Indices;
347 size_type subTreeSize = node.child(_0).size();
348 // Fill indices for first child at the beginning.
349 auto next = subPreBasis().indices(node.child(_0), multiIndices);
350 // Append 0 after last component of all indices for first child.
351 for (std::size_t i = 0; i<subTreeSize; ++i)
352 multiIndices[i].push_back(0);
353 for (std::size_t child = 1; child<children_; ++child)
354 {
355 for (std::size_t i = 0; i<subTreeSize; ++i)
356 {
357 // Copy indices from first child for all other children and overwrite
358 // zero in last component as appended above by child index.
359 (*next) = multiIndices[i];
360 (*next).back() = child;
361 ++next;
362 }
363 }
364 return next;
365 }
366
367 template<class Children>
368 auto containerDescriptorImpl(Children children) const
369 {
370 auto subTree = Dune::Functions::containerDescriptor(subPreBasis_);
371 if constexpr(std::is_same_v<IMS, BasisFactory::FlatInterleaved>)
372 return ContainerDescriptors::Unknown{}; // Not yet implemented
373 else if constexpr(std::is_same_v<IMS, BasisFactory::FlatLexicographic>)
374 return ContainerDescriptors::Unknown{}; // Not yet implemented
375 else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedLexicographic>)
376 return ContainerDescriptors::makeUniformDescriptor(children,std::move(subTree));
377 else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedInterleaved>)
378 return ContainerDescriptors::Unknown{}; // Not yet implemented
379 else
380 return ContainerDescriptors::Unknown{};
381 }
382
383protected:
384 std::size_t children_;
385 SubPreBasis subPreBasis_;
386};
387
388
389
390namespace BasisFactory {
391
404template<class ChildPreBasisFactory, class IndexMergingStrategy>
405auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k, const IndexMergingStrategy&)
406{
407 return [childPreBasisFactory,k](const auto& gridView) {
408 auto childPreBasis = childPreBasisFactory(gridView);
410 };
411}
412
423template<class ChildPreBasisFactory>
424auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k)
425{
426 return [childPreBasisFactory,k](const auto& gridView) {
427 auto childPreBasis = childPreBasisFactory(gridView);
429 };
430}
431
432} // end namespace BasisFactory
433
434} // end namespace Functions
435} // end namespace Dune
436
437
438#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
A pre-basis for dynamic power bases.
Definition: dynamicpowerbasis.hh:44
std::size_t size_type
Type used for indices and size information.
Definition: dynamicpowerbasis.hh:56
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: dynamicpowerbasis.hh:59
DynamicPowerPreBasis(std::size_t c, SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: dynamicpowerbasis.hh:76
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: dynamicpowerbasis.hh:218
It indices(const NodeType &node, It it) const
Maps from subtree index set [0..size-1] to a globally unique multi index in global basis.
Definition: dynamicpowerbasis.hh:244
void initializeIndices()
Initialize the global indices.
Definition: dynamicpowerbasis.hh:84
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: dynamicpowerbasis.hh:96
auto containerDescriptor() const
Return the associated container descriptor.
Definition: dynamicpowerbasis.hh:250
size_type size() const
Same as size(prefix) with empty prefix.
Definition: dynamicpowerbasis.hh:118
SubPreBasis & subPreBasis()
Mutable access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:236
SPB SubPreBasis
The child pre-basis.
Definition: dynamicpowerbasis.hh:50
Node makeNode() const
Create tree node.
Definition: dynamicpowerbasis.hh:104
const SubPreBasis & subPreBasis() const
Const access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:230
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: dynamicpowerbasis.hh:224
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: dynamicpowerbasis.hh:125
DynamicPowerBasisNode< typename SubPreBasis::Node > Node
Template mapping root tree path to type of created tree node.
Definition: dynamicpowerbasis.hh:62
typename SPB::GridView GridView
The grid view that the FE basis is defined on.
Definition: dynamicpowerbasis.hh:53
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: dynamicpowerbasis.hh:90
A Vector class with statically reserved memory.
Definition: reservedvector.hh:47
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:52
ImplementationDefined child(Node &&node, Indices... indices)
Extracts the child of a node given by a sequence of compile-time and run-time indices.
Definition: childextraction.hh:128
std::enable_if_t< not Impl::disableCopyMoveHelper< This, T... >::value, int > disableCopyMove
Helper to disable constructor as copy and move constructor.
Definition: typeutilities.hh:45
std::enable_if_t< std::is_constructible_v< T, Args... >, int > enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:27
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:50
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integer_sequence< T, II..., T(IN)> push_back(std::integer_sequence< T, II... >, std::integral_constant< T, IN >={})
Append an index IN to the back of the sequence.
Definition: integersequence.hh:69
constexpr Base power(Base m, Exponent p)
Power method for integer exponents.
Definition: math.hh:75
constexpr std::integer_sequence< T, II... > tail(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the tail sequence.
Definition: integersequence.hh:58
STL namespace.
An stl-compliant random-access container which stores everything on the stack.
Interleaved merging of direct children without blocking.
Definition: basistags.hh:114
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:44
Utilities for type computations, constraining overloads, ...
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)