7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
10#include <dune/common/reservedvector.hh>
11#include <dune/common/typeutilities.hh>
12#include <dune/common/indices.hh>
14#include <dune/functions/common/utility.hh>
15#include <dune/functions/common/type_traits.hh>
16#include <dune/functions/functionspacebases/basistags.hh>
17#include <dune/functions/functionspacebases/containerdescriptors.hh>
18#include <dune/functions/functionspacebases/nodes.hh>
19#include <dune/functions/functionspacebases/concepts.hh>
46template<
class IMS,
class SPB>
49 static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
66 using Node = DynamicPowerBasisNode<typename SubPreBasis::Node>;
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;
77 template<
class... SFArgs,
82 subPreBasis_(std::forward<SFArgs>(sfArgs)...)
84 static_assert(models<Concept::PreBasis<GridView>,
SubPreBasis>(),
"Subprebasis passed to DynamicPowerPreBasis does not model the PreBasis concept.");
90 subPreBasis_.initializeIndices();
96 return subPreBasis_.gridView();
102 subPreBasis_.update(gv);
110 auto node =
Node{children_};
111 for (std::size_t i=0; i<children_; ++i)
112 node.setChild(i, subPreBasis_.makeNode());
116 std::size_t children()
const
124 return size(Dune::ReservedVector<size_type, multiIndexBufferSize>{});
128 template<
class SizePrefix>
136 template<
class SizePrefix,
class Children>
142 if (prefix.size() == 0)
143 return children*subPreBasis_.size();
148 prefix[0] = prefix[0] / children;
149 return subPreBasis_.size(prefix);
152 template<
class SizePrefix,
class Children>
153 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatLexicographic)
const
158 if (prefix.size() == 0)
159 return children*subPreBasis_.size();
170 prefix[0] = prefix[0] % subPreBasis_.size();
171 return subPreBasis_.size(prefix);
174 template<
class MultiIndex>
175 static void multiIndexPopFront(MultiIndex& M)
177 for(std::size_t i=0; i<M.size()-1; ++i)
179 M.resize(M.size()-1);
182 template<
class SizePrefix,
class Children>
183 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedLexicographic)
const
185 if (prefix.size() == 0)
187 multiIndexPopFront(prefix);
188 return subPreBasis_.size(prefix);
191 template<
class SizePrefix,
class Children>
192 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedInterleaved)
const
194 if (prefix.size() == 0)
195 return subPreBasis_.size();
202 auto tail = prefix.back();
204 if (subPreBasis_.size(prefix) == 0)
206 prefix.push_back(tail);
213 auto subSize = subPreBasis_.size(prefix);
224 return subPreBasis_.dimension() * children_;
230 return subPreBasis_.maxNodeSize() * children_;
246 template<
class NodeType,
typename It,
247 std::enable_if_t<NodeType::isPower, int> = 0>
256 return containerDescriptorImpl(children_);
261 template<
class NodeType,
typename It,
class Children>
264 using namespace Dune::Indices;
265 size_type subTreeSize = node.child(_0).size();
267 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
270 for (std::size_t i = 0; i<subTreeSize; ++i)
271 multiIndices[i][0] *= children;
272 for (std::size_t child = 1; child<children; ++child)
274 for (std::size_t i = 0; i<subTreeSize; ++i)
280 (*next) = multiIndices[i];
281 (*next)[0] = multiIndices[i][0]+child;
288 template<
class NodeType,
typename It,
class Children>
289 It indicesImpl(
const NodeType& node, It multiIndices, Children children, BasisFactory::FlatLexicographic)
const
291 using namespace Dune::Indices;
292 size_type subTreeSize = node.child(_0).size();
295 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
296 for (std::size_t child = 1; child<children_; ++child)
298 for (std::size_t i = 0; i<subTreeSize; ++i)
304 (*next) = multiIndices[i];
305 (*next)[0] += child*firstIndexEntrySize;
312 template<
class MultiIndex>
313 static void multiIndexPushFront(MultiIndex& M,
size_type M0)
315 M.resize(M.size()+1);
316 for(std::size_t i=M.size()-1; i>0; --i)
321 template<
class NodeType,
typename It,
class Children>
322 It indicesImpl(
const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedLexicographic)
const
324 using namespace Dune::Indices;
325 size_type subTreeSize = node.child(_0).size();
327 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
329 for (std::size_t i = 0; i<subTreeSize; ++i)
330 multiIndexPushFront(multiIndices[i], 0);
331 for (std::size_t child = 1; child<children_; ++child)
333 for (std::size_t i = 0; i<subTreeSize; ++i)
339 (*next) = multiIndices[i];
347 template<
class NodeType,
typename It,
class Children>
348 It indicesImpl(
const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedInterleaved)
const
350 using namespace Dune::Indices;
351 size_type subTreeSize = node.child(_0).size();
353 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
355 for (std::size_t i = 0; i<subTreeSize; ++i)
356 multiIndices[i].push_back(0);
357 for (std::size_t child = 1; child<children_; ++child)
359 for (std::size_t i = 0; i<subTreeSize; ++i)
363 (*next) = multiIndices[i];
364 (*next).back() = child;
371 template<
class Children>
372 auto containerDescriptorImpl(Children children)
const
374 auto subTree = Dune::Functions::containerDescriptor(subPreBasis_);
375 if constexpr(std::is_same_v<IMS, BasisFactory::FlatInterleaved>)
376 return ContainerDescriptors::Impl::flatInterleavedN(children,std::move(subTree));
377 else if constexpr(std::is_same_v<IMS, BasisFactory::FlatLexicographic>)
378 return ContainerDescriptors::Impl::flatLexicographicN(children,std::move(subTree));
379 else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedLexicographic>)
380 return ContainerDescriptors::makeUniformDescriptor(children,std::move(subTree));
381 else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedInterleaved>)
382 return ContainerDescriptors::Impl::appendToTree(children,std::move(subTree));
384 return ContainerDescriptors::Unknown{};
388 std::size_t children_;
394namespace BasisFactory {
408template<
class ChildPreBasisFactory,
class IndexMergingStrategy>
411 return [childPreBasisFactory,k](
const auto& gridView) {
412 auto childPreBasis = childPreBasisFactory(gridView);
427template<
class ChildPreBasisFactory>
428auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k)
430 return [childPreBasisFactory,k](
const auto& gridView) {
431 auto childPreBasis = childPreBasisFactory(gridView);
A pre-basis for dynamic power bases.
Definition: dynamicpowerbasis.hh:48
std::size_t size_type
Type used for indices and size information.
Definition: dynamicpowerbasis.hh:60
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: dynamicpowerbasis.hh:63
DynamicPowerPreBasis(std::size_t c, SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: dynamicpowerbasis.hh:80
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: dynamicpowerbasis.hh:222
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:248
void initializeIndices()
Initialize the global indices.
Definition: dynamicpowerbasis.hh:88
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: dynamicpowerbasis.hh:100
auto containerDescriptor() const
Return the associated container descriptor.
Definition: dynamicpowerbasis.hh:254
size_type size() const
Same as size(prefix) with empty prefix.
Definition: dynamicpowerbasis.hh:122
SubPreBasis & subPreBasis()
Mutable access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:240
SPB SubPreBasis
The child pre-basis.
Definition: dynamicpowerbasis.hh:54
Node makeNode() const
Create tree node.
Definition: dynamicpowerbasis.hh:108
const SubPreBasis & subPreBasis() const
Const access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:234
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: dynamicpowerbasis.hh:228
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: dynamicpowerbasis.hh:129
DynamicPowerBasisNode< typename SubPreBasis::Node > Node
Template mapping root tree path to type of created tree node.
Definition: dynamicpowerbasis.hh:66
typename SPB::GridView GridView
The grid view that the FE basis is defined on.
Definition: dynamicpowerbasis.hh:57
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: dynamicpowerbasis.hh:94
auto power(ChildPreBasisFactory &&childPreBasisFactory, std::size_t k)
Create a factory builder that can build a PowerPreBasis.
Definition: dynamicpowerbasis.hh:428
std::enable_if_t< std::is_constructible_v< T, Args... >, int > enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:31
Definition: monomialset.hh:19
Interleaved merging of direct children without blocking.
Definition: basistags.hh:118
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:48