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/common/typetree/nodeconcepts.hh>
16#include <dune/functions/common/utility.hh>
17#include <dune/functions/common/type_traits.hh>
18#include <dune/functions/functionspacebases/basistags.hh>
20#include <dune/functions/functionspacebases/nodes.hh>
21#include <dune/functions/functionspacebases/concepts.hh>
48template<
class IMS,
class SPB>
51 static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
68 using Node = DynamicPowerBasisNode<typename SubPreBasis::Node>;
70 static constexpr size_type maxMultiIndexSize = SubPreBasis::maxMultiIndexSize + isBlocked;
71 static constexpr size_type minMultiIndexSize = SubPreBasis::minMultiIndexSize + isBlocked;
72 static constexpr size_type multiIndexBufferSize = SubPreBasis::multiIndexBufferSize + isBlocked;
79 template<
class... SFArgs,
84 subPreBasis_(std::forward<SFArgs>(sfArgs)...)
86 static_assert(models<Concept::PreBasis<GridView>,
SubPreBasis>(),
"Subprebasis passed to DynamicPowerPreBasis does not model the PreBasis concept.");
92 subPreBasis_.initializeIndices();
98 return subPreBasis_.gridView();
104 subPreBasis_.update(gv);
112 auto node =
Node{children_};
113 for (std::size_t i=0; i<children_; ++i)
114 node.setChild(i, subPreBasis_.makeNode());
118 std::size_t children()
const
126 return size(Dune::ReservedVector<size_type, multiIndexBufferSize>{});
130 template<
class SizePrefix>
138 template<
class SizePrefix,
class Children>
144 if (prefix.size() == 0)
145 return children*subPreBasis_.size();
150 prefix[0] = prefix[0] / children;
151 return subPreBasis_.size(prefix);
154 template<
class SizePrefix,
class Children>
155 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatLexicographic)
const
160 if (prefix.size() == 0)
161 return children*subPreBasis_.size();
172 prefix[0] = prefix[0] % subPreBasis_.size();
173 return subPreBasis_.size(prefix);
176 template<
class MultiIndex>
177 static void multiIndexPopFront(MultiIndex& M)
179 for(std::size_t i=0; i<M.size()-1; ++i)
181 M.resize(M.size()-1);
184 template<
class SizePrefix,
class Children>
185 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedLexicographic)
const
187 if (prefix.size() == 0)
189 multiIndexPopFront(prefix);
190 return subPreBasis_.size(prefix);
193 template<
class SizePrefix,
class Children>
194 size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedInterleaved)
const
196 if (prefix.size() == 0)
197 return subPreBasis_.size();
204 auto tail = prefix.back();
206 if (subPreBasis_.size(prefix) == 0)
208 prefix.push_back(tail);
215 auto subSize = subPreBasis_.size(prefix);
226 return subPreBasis_.dimension() * children_;
232 return subPreBasis_.maxNodeSize() * children_;
248 template<
class NodeType,
typename It>
249 requires Dune::TypeTree::Concept::UniformInnerTreeNode<NodeType>
258 return containerDescriptorImpl(children_);
263 template<
class NodeType,
typename It,
class Children>
266 using namespace Dune::Indices;
267 size_type subTreeSize = node.child(_0).size();
269 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
272 for (std::size_t i = 0; i<subTreeSize; ++i)
273 multiIndices[i][0] *= children;
274 for (std::size_t child = 1; child<children; ++child)
276 for (std::size_t i = 0; i<subTreeSize; ++i)
282 (*next) = multiIndices[i];
283 (*next)[0] = multiIndices[i][0]+child;
290 template<
class NodeType,
typename It,
class Children>
291 It indicesImpl(
const NodeType& node, It multiIndices, Children children, BasisFactory::FlatLexicographic)
const
293 using namespace Dune::Indices;
294 size_type subTreeSize = node.child(_0).size();
297 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
298 for (std::size_t child = 1; child<children_; ++child)
300 for (std::size_t i = 0; i<subTreeSize; ++i)
306 (*next) = multiIndices[i];
307 (*next)[0] += child*firstIndexEntrySize;
314 template<
class MultiIndex>
315 static void multiIndexPushFront(MultiIndex& M,
size_type M0)
317 M.resize(M.size()+1);
318 for(std::size_t i=M.size()-1; i>0; --i)
323 template<
class NodeType,
typename It,
class Children>
324 It indicesImpl(
const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedLexicographic)
const
326 using namespace Dune::Indices;
327 size_type subTreeSize = node.child(_0).size();
329 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
331 for (std::size_t i = 0; i<subTreeSize; ++i)
332 multiIndexPushFront(multiIndices[i], 0);
333 for (std::size_t child = 1; child<children_; ++child)
335 for (std::size_t i = 0; i<subTreeSize; ++i)
341 (*next) = multiIndices[i];
349 template<
class NodeType,
typename It,
class Children>
350 It indicesImpl(
const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedInterleaved)
const
352 using namespace Dune::Indices;
353 size_type subTreeSize = node.child(_0).size();
355 auto next =
subPreBasis().indices(node.child(_0), multiIndices);
357 for (std::size_t i = 0; i<subTreeSize; ++i)
358 multiIndices[i].push_back(0);
359 for (std::size_t child = 1; child<children_; ++child)
361 for (std::size_t i = 0; i<subTreeSize; ++i)
365 (*next) = multiIndices[i];
366 (*next).back() = child;
373 template<
class Children>
374 auto containerDescriptorImpl(Children children)
const
377 if constexpr(std::is_same_v<IMS, BasisFactory::FlatInterleaved>)
378 return ContainerDescriptors::Impl::flatInterleavedN(children,std::move(subTree));
379 else if constexpr(std::is_same_v<IMS, BasisFactory::FlatLexicographic>)
380 return ContainerDescriptors::Impl::flatLexicographicN(children,std::move(subTree));
381 else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedLexicographic>)
382 return ContainerDescriptors::makeUniformDescriptor(children,std::move(subTree));
383 else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedInterleaved>)
384 return ContainerDescriptors::Impl::appendToTree(children,std::move(subTree));
386 return ContainerDescriptors::Unknown{};
390 std::size_t children_;
396namespace BasisFactory {
409template<
class ChildPreBasisFactory,
class IndexMergingStrategy>
412 return [childPreBasisFactory,k](
const auto& gridView) {
413 auto childPreBasis = childPreBasisFactory(gridView);
428template<
class ChildPreBasisFactory>
429[[deprecated(
"Using the method `power` without an explicit index merging strategy"
430 " will change its meaning after the release of dune-functions 2.11."
431 " Previously, the default merging strategy was `BlockedInterleaved`,"
432 " but this will change to `FlatInterleaved`."
433 " Change the call to `power(..., blockedInterleaved())` to retain the old behavior.")]]
434auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k)
436 return [childPreBasisFactory,k](
const auto& gridView) {
437 auto childPreBasis = childPreBasisFactory(gridView);
A pre-basis for dynamic power bases.
Definition: dynamicpowerbasis.hh:50
std::size_t size_type
Type used for indices and size information.
Definition: dynamicpowerbasis.hh:62
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: dynamicpowerbasis.hh:65
DynamicPowerPreBasis(std::size_t c, SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: dynamicpowerbasis.hh:82
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: dynamicpowerbasis.hh:224
void initializeIndices()
Initialize the global indices.
Definition: dynamicpowerbasis.hh:90
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: dynamicpowerbasis.hh:102
auto containerDescriptor() const
Return the associated container descriptor.
Definition: dynamicpowerbasis.hh:256
size_type size() const
Same as size(prefix) with empty prefix.
Definition: dynamicpowerbasis.hh:124
SubPreBasis & subPreBasis()
Mutable access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:242
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:250
SPB SubPreBasis
The child pre-basis.
Definition: dynamicpowerbasis.hh:56
Node makeNode() const
Create tree node.
Definition: dynamicpowerbasis.hh:110
const SubPreBasis & subPreBasis() const
Const access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:236
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: dynamicpowerbasis.hh:230
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: dynamicpowerbasis.hh:131
DynamicPowerBasisNode< typename SubPreBasis::Node > Node
Template mapping root tree path to type of created tree node.
Definition: dynamicpowerbasis.hh:68
typename SPB::GridView GridView
The grid view that the FE basis is defined on.
Definition: dynamicpowerbasis.hh:59
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: dynamicpowerbasis.hh:96
Lightweight representation of (hierarchical) size and block structure extracted from a basis to descr...
auto containerDescriptor(const PreBasis &preBasis)
Return the container descriptor of the pre-basis, if defined, otherwise ContainerDescriptor::Unknown.
Definition: containerdescriptors.hh:58
auto power(ChildPreBasisFactory &&childPreBasisFactory, std::size_t k)
Create a factory builder that can build a PowerPreBasis.
Definition: dynamicpowerbasis.hh:434
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