Loading...
Searching...
No Matches
dynamicpowerbasis.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
#include <dune/common/reservedvector.hh>
#include <dune/common/typeutilities.hh>
#include <dune/common/indices.hh>
#include <dune/common/typetree/nodeconcepts.hh>
#include <dune/functions/common/utility.hh>
#include <dune/functions/common/type_traits.hh>
#include <dune/functions/functionspacebases/basistags.hh>
#include <dune/functions/functionspacebases/containerdescriptors.hh>
#include <dune/functions/functionspacebases/nodes.hh>
#include <dune/functions/functionspacebases/concepts.hh>
namespace Dune {
namespace Functions {
// *****************************************************************************
// This is the reusable part of the dynamic power bases. It contains
//
// DynamicPowerPreBasis
//
// The pre-basis allows to create the others and is the owner of possible shared
// state. These components do _not_ depend on the global basis and local view
// and can be used without a global basis.
// *****************************************************************************
template<class IMS, class SPB>
class DynamicPowerPreBasis
{
static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
public:
using SubPreBasis = SPB;
using GridView = typename SPB::GridView;
using size_type = std::size_t;
using IndexMergingStrategy = IMS;
using Node = DynamicPowerBasisNode<typename SubPreBasis::Node>;
static constexpr size_type maxMultiIndexSize = SubPreBasis::maxMultiIndexSize + isBlocked;
static constexpr size_type minMultiIndexSize = SubPreBasis::minMultiIndexSize + isBlocked;
static constexpr size_type multiIndexBufferSize = SubPreBasis::multiIndexBufferSize + isBlocked;
template<class... SFArgs,
disableCopyMove<DynamicPowerPreBasis, SFArgs...> = 0,
enableIfConstructible<SubPreBasis, SFArgs...> = 0>
explicit DynamicPowerPreBasis(std::size_t c, SFArgs&&... sfArgs) :
children_(c),
subPreBasis_(std::forward<SFArgs>(sfArgs)...)
{
static_assert(models<Concept::PreBasis<GridView>, SubPreBasis>(), "Subprebasis passed to DynamicPowerPreBasis does not model the PreBasis concept.");
}
void initializeIndices()
{
subPreBasis_.initializeIndices();
}
const GridView& gridView() const
{
return subPreBasis_.gridView();
}
void update(const GridView& gv)
{
subPreBasis_.update(gv);
}
Node makeNode() const
{
auto node = Node{children_};
for (std::size_t i=0; i<children_; ++i)
node.setChild(i, subPreBasis_.makeNode());
return node;
}
std::size_t children() const
{
return children_;
}
size_type size() const
{
return size(Dune::ReservedVector<size_type, multiIndexBufferSize>{});
}
template<class SizePrefix>
size_type size(const SizePrefix& prefix) const
{
return sizeImpl(prefix, children_, IndexMergingStrategy{});
}
protected:
template<class SizePrefix, class Children>
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatInterleaved) const
{
// The root index size is the root index size of a single subnode
// multiplied by the number of subnodes, because we enumerate all
// child indices in a row.
if (prefix.size() == 0)
return children*subPreBasis_.size();
// The FlatInterleaved index merging strategy only changes the first
// index digit. Hence, we have to reconstruct the corresponding digit
// for the subtree and can then return the corresponding size of the subtree.
prefix[0] = prefix[0] / children;
return subPreBasis_.size(prefix);
}
template<class SizePrefix, class Children>
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatLexicographic) const
{
// The size at the index tree root is the size of at the index tree
// root of a single subnode multiplied by the number of subnodes,
// because we enumerate all child indices in a row.
if (prefix.size() == 0)
return children*subPreBasis_.size();
// The first prefix entry refers to one of the (root index size)
// subindex trees. Hence, we have to first compute the corresponding
// prefix entry for a single subnode subnode. Then we can append
// the other prefix entries unmodified, because the index tree
// looks the same after the first level.
// The FlatLexicographic index merging strategy only changes the first
// index digit. Hence, we have to reconstruct the corresponding digit
// for the subtree and can then return the corresponding size of the subtree.
prefix[0] = prefix[0] % subPreBasis_.size();
return subPreBasis_.size(prefix);
}
template<class MultiIndex>
static void multiIndexPopFront(MultiIndex& M)
{
for(std::size_t i=0; i<M.size()-1; ++i)
M[i] = M[i+1];
M.resize(M.size()-1);
}
template<class SizePrefix, class Children>
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedLexicographic) const
{
if (prefix.size() == 0)
return children;
multiIndexPopFront(prefix);
return subPreBasis_.size(prefix);
}
template<class SizePrefix, class Children>
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedInterleaved) const
{
if (prefix.size() == 0)
return subPreBasis_.size();
// Remember last index, remove it and check if the remaining
// prefix refers to a leaf in the subPreBasis index tree.
// If yes, then the full prefix must also refer to a
// leaf in the merged index tree. If not, then restore the full
// prefix and proceed.
auto tail = prefix.back();
prefix.pop_back();
if (subPreBasis_.size(prefix) == 0)
return 0;
prefix.push_back(tail);
// Now check if the full prefix refers to a leaf in the subPreBasis
// index tree.
// If yes, then it has exactly 'children' appended children in the subtree.
// If not, then the index tree looks the same in the merged subtree and we
// can forward the result.
auto subSize = subPreBasis_.size(prefix);
if (subSize == 0)
return children;
return subSize;
}
public:
size_type dimension() const
{
return subPreBasis_.dimension() * children_;
}
size_type maxNodeSize() const
{
return subPreBasis_.maxNodeSize() * children_;
}
const SubPreBasis& subPreBasis() const
{
return subPreBasis_;
}
SubPreBasis& subPreBasis()
{
return subPreBasis_;
}
template<class NodeType, typename It>
requires Dune::TypeTree::Concept::UniformInnerTreeNode<NodeType>
It indices(const NodeType& node, It it) const
{
return indicesImpl(node, it, children_, IndexMergingStrategy{});
}
auto containerDescriptor() const
{
return containerDescriptorImpl(children_);
}
protected:
template<class NodeType, typename It, class Children>
It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::FlatInterleaved) const
{
using namespace Dune::Indices;
size_type subTreeSize = node.child(_0).size();
// Fill indices for first child at the beginning.
auto next = subPreBasis().indices(node.child(_0), multiIndices);
// Multiply first component of all indices for first child by
// number of children to stretch the index range for interleaving.
for (std::size_t i = 0; i<subTreeSize; ++i)
multiIndices[i][0] *= children;
for (std::size_t child = 1; child<children; ++child)
{
for (std::size_t i = 0; i<subTreeSize; ++i)
{
// Copy indices from first child for all other children
// and shift them by child index to interleave indices.
// multiIndices[child*subTreeSize+i] = multiIndices[i];
// multiIndices[child*subTreeSize+i][0] = multiIndices[i][0]+child;
(*next) = multiIndices[i];
(*next)[0] = multiIndices[i][0]+child;
++next;
}
}
return next;
}
template<class NodeType, typename It, class Children>
It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::FlatLexicographic) const
{
using namespace Dune::Indices;
size_type subTreeSize = node.child(_0).size();
size_type firstIndexEntrySize = subPreBasis().size();
// Fill indices for first child at the beginning.
auto next = subPreBasis().indices(node.child(_0), multiIndices);
for (std::size_t child = 1; child<children_; ++child)
{
for (std::size_t i = 0; i<subTreeSize; ++i)
{
// Copy indices from first child for all other children
// and shift them by suitable offset to get lexicographic indices.
// multiIndices[child*subTreeSize+i] = multiIndices[i];
// multiIndices[child*subTreeSize+i][0] += child*firstIndexEntrySize;
(*next) = multiIndices[i];
(*next)[0] += child*firstIndexEntrySize;
++next;
}
}
return next;
}
template<class MultiIndex>
static void multiIndexPushFront(MultiIndex& M, size_type M0)
{
M.resize(M.size()+1);
for(std::size_t i=M.size()-1; i>0; --i)
M[i] = M[i-1];
M[0] = M0;
}
template<class NodeType, typename It, class Children>
It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedLexicographic) const
{
using namespace Dune::Indices;
size_type subTreeSize = node.child(_0).size();
// Fill indices for first child at the beginning.
auto next = subPreBasis().indices(node.child(_0), multiIndices);
// Insert 0 before first component of all indices for first child.
for (std::size_t i = 0; i<subTreeSize; ++i)
multiIndexPushFront(multiIndices[i], 0);
for (std::size_t child = 1; child<children_; ++child)
{
for (std::size_t i = 0; i<subTreeSize; ++i)
{
// Copy indices from first child for all other children and overwrite
// zero in first component as inserted above by child index.
// multiIndices[child*subTreeSize+i] = multiIndices[i];
// multiIndices[child*subTreeSize+i][0] = child;
(*next) = multiIndices[i];
(*next)[0] = child;
++next;
}
}
return next;
}
template<class NodeType, typename It, class Children>
It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedInterleaved) const
{
using namespace Dune::Indices;
size_type subTreeSize = node.child(_0).size();
// Fill indices for first child at the beginning.
auto next = subPreBasis().indices(node.child(_0), multiIndices);
// Append 0 after last component of all indices for first child.
for (std::size_t i = 0; i<subTreeSize; ++i)
multiIndices[i].push_back(0);
for (std::size_t child = 1; child<children_; ++child)
{
for (std::size_t i = 0; i<subTreeSize; ++i)
{
// Copy indices from first child for all other children and overwrite
// zero in last component as appended above by child index.
(*next) = multiIndices[i];
(*next).back() = child;
++next;
}
}
return next;
}
template<class Children>
auto containerDescriptorImpl(Children children) const
{
auto subTree = Dune::Functions::containerDescriptor(subPreBasis_);
if constexpr(std::is_same_v<IMS, BasisFactory::FlatInterleaved>)
return ContainerDescriptors::Impl::flatInterleavedN(children,std::move(subTree));
else if constexpr(std::is_same_v<IMS, BasisFactory::FlatLexicographic>)
return ContainerDescriptors::Impl::flatLexicographicN(children,std::move(subTree));
else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedLexicographic>)
return ContainerDescriptors::makeUniformDescriptor(children,std::move(subTree));
else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedInterleaved>)
return ContainerDescriptors::Impl::appendToTree(children,std::move(subTree));
else
return ContainerDescriptors::Unknown{};
}
protected:
std::size_t children_;
SubPreBasis subPreBasis_;
};
namespace BasisFactory {
template<class ChildPreBasisFactory, class IndexMergingStrategy>
auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k, const IndexMergingStrategy&)
{
return [childPreBasisFactory,k](const auto& gridView) {
auto childPreBasis = childPreBasisFactory(gridView);
return DynamicPowerPreBasis<IndexMergingStrategy, decltype(childPreBasis)>(k,std::move(childPreBasis));
};
}
template<class ChildPreBasisFactory>
[[deprecated("Using the method `power` without an explicit index merging strategy"
" will change its meaning after the release of dune-functions 2.11."
" Previously, the default merging strategy was `BlockedInterleaved`,"
" but this will change to `FlatInterleaved`."
" Change the call to `power(..., blockedInterleaved())` to retain the old behavior.")]]
auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k)
{
return [childPreBasisFactory,k](const auto& gridView) {
auto childPreBasis = childPreBasisFactory(gridView);
return DynamicPowerPreBasis<BlockedInterleaved, decltype(childPreBasis)>(k,std::move(childPreBasis));
};
}
} // end namespace BasisFactory
} // end namespace Functions
} // end namespace Dune
#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
nodes.hh
containerdescriptors.hh
Lightweight representation of (hierarchical) size and block structure extracted from a basis to descr...
basistags.hh
type_traits.hh
utility.hh
Dune::Functions::BasisFactory::power
auto power(ChildPreBasisFactory &&childPreBasisFactory, std::size_t k, const IndexMergingStrategy &)
Create a pre-basis factory that can build a PowerPreBasis.
Definition dynamicpowerbasis.hh:410
Dune::Functions::enableIfConstructible
std::enable_if_t< std::is_constructible_v< T, Args... >, int > enableIfConstructible
Helper to constrain forwarding constructors.
Definition type_traits.hh:30
Dune
Definition monomialset.hh:19
Dune::Functions
Definition monomialset.hh:19
Dune::Functions::containerDescriptor
auto containerDescriptor(const PreBasis &preBasis)
Return the container descriptor of the pre-basis, if defined, otherwise ContainerDescriptor::Unknown.
Definition containerdescriptors.hh:58
Dune::Functions::ContainerDescriptors::makeUniformDescriptor
auto makeUniformDescriptor(std::integral_constant< std::size_t, n >, Child child)
Generate a uniform descriptor in case the size is a static constant.
Definition containerdescriptors.hh:147
Dune::Functions::BasisFactory
Definition argyrisbasis.hh:926
Dune::Functions::BasisFactory::IndexMergingStrategy
Base class for index merging strategies to simplify detection.
Definition basistags.hh:48
Dune::Functions::BasisFactory::FlatLexicographic
Lexicographic merging of direct children without blocking.
Definition basistags.hh:84
Dune::Functions::BasisFactory::FlatInterleaved
Interleaved merging of direct children without blocking.
Definition basistags.hh:118
Dune::Functions::BasisFactory::BlockedLexicographic
Lexicographic merging of direct children with blocking (i.e. creating one block per direct child).
Definition basistags.hh:152
Dune::Functions::BasisFactory::BlockedInterleaved
Interleaved merging of direct children with blocking (i.e. creating blocks at the leaves containing o...
Definition basistags.hh:184
Dune::Functions::ContainerDescriptors::Unknown
Fallback container descriptor if nothing else fits.
Definition containerdescriptors.hh:52
Dune::Functions::DynamicPowerPreBasis
A pre-basis for dynamic power bases.
Definition dynamicpowerbasis.hh:50
Dune::Functions::DynamicPowerPreBasis::size_type
std::size_t size_type
Type used for indices and size information.
Definition dynamicpowerbasis.hh:62
Dune::Functions::DynamicPowerPreBasis::IndexMergingStrategy
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition dynamicpowerbasis.hh:65
Dune::Functions::DynamicPowerPreBasis::DynamicPowerPreBasis
DynamicPowerPreBasis(std::size_t c, SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition dynamicpowerbasis.hh:82
Dune::Functions::DynamicPowerPreBasis::multiIndexPopFront
static void multiIndexPopFront(MultiIndex &M)
Definition dynamicpowerbasis.hh:177
Dune::Functions::DynamicPowerPreBasis::dimension
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition dynamicpowerbasis.hh:224
Dune::Functions::DynamicPowerPreBasis::containerDescriptorImpl
auto containerDescriptorImpl(Children children) const
Definition dynamicpowerbasis.hh:374
Dune::Functions::DynamicPowerPreBasis::initializeIndices
void initializeIndices()
Initialize the global indices.
Definition dynamicpowerbasis.hh:90
Dune::Functions::DynamicPowerPreBasis::sizeImpl
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatInterleaved) const
Definition dynamicpowerbasis.hh:139
Dune::Functions::DynamicPowerPreBasis::maxMultiIndexSize
static constexpr size_type maxMultiIndexSize
Definition dynamicpowerbasis.hh:70
Dune::Functions::DynamicPowerPreBasis::update
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition dynamicpowerbasis.hh:102
Dune::Functions::DynamicPowerPreBasis::containerDescriptor
auto containerDescriptor() const
Return the associated container descriptor.
Definition dynamicpowerbasis.hh:256
Dune::Functions::DynamicPowerPreBasis::size
size_type size() const
Same as size(prefix) with empty prefix.
Definition dynamicpowerbasis.hh:124
Dune::Functions::DynamicPowerPreBasis::indicesImpl
It indicesImpl(const NodeType &node, It multiIndices, Children children, BasisFactory::BlockedInterleaved) const
Definition dynamicpowerbasis.hh:350
Dune::Functions::DynamicPowerPreBasis::subPreBasis
SubPreBasis & subPreBasis()
Mutable access to the stored prebasis of the factor in the power space.
Definition dynamicpowerbasis.hh:242
Dune::Functions::DynamicPowerPreBasis::sizeImpl
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatLexicographic) const
Definition dynamicpowerbasis.hh:155
Dune::Functions::DynamicPowerPreBasis::multiIndexPushFront
static void multiIndexPushFront(MultiIndex &M, size_type M0)
Definition dynamicpowerbasis.hh:315
Dune::Functions::DynamicPowerPreBasis::subPreBasis_
SubPreBasis subPreBasis_
Definition dynamicpowerbasis.hh:391
Dune::Functions::DynamicPowerPreBasis::indices
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
Dune::Functions::DynamicPowerPreBasis::sizeImpl
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedLexicographic) const
Definition dynamicpowerbasis.hh:185
Dune::Functions::DynamicPowerPreBasis::sizeImpl
size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedInterleaved) const
Definition dynamicpowerbasis.hh:194
Dune::Functions::DynamicPowerPreBasis::indicesImpl
It indicesImpl(const NodeType &node, It multiIndices, Children children, BasisFactory::BlockedLexicographic) const
Definition dynamicpowerbasis.hh:324
Dune::Functions::DynamicPowerPreBasis::multiIndexBufferSize
static constexpr size_type multiIndexBufferSize
Definition dynamicpowerbasis.hh:72
Dune::Functions::DynamicPowerPreBasis::SubPreBasis
SPB SubPreBasis
The child pre-basis.
Definition dynamicpowerbasis.hh:56
Dune::Functions::DynamicPowerPreBasis::makeNode
Node makeNode() const
Create tree node.
Definition dynamicpowerbasis.hh:110
Dune::Functions::DynamicPowerPreBasis::subPreBasis
const SubPreBasis & subPreBasis() const
Const access to the stored prebasis of the factor in the power space.
Definition dynamicpowerbasis.hh:236
Dune::Functions::DynamicPowerPreBasis::indicesImpl
It indicesImpl(const NodeType &node, It multiIndices, Children children, BasisFactory::FlatInterleaved) const
Definition dynamicpowerbasis.hh:264
Dune::Functions::DynamicPowerPreBasis::children
std::size_t children() const
Definition dynamicpowerbasis.hh:118
Dune::Functions::DynamicPowerPreBasis::maxNodeSize
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition dynamicpowerbasis.hh:230
Dune::Functions::DynamicPowerPreBasis::indicesImpl
It indicesImpl(const NodeType &node, It multiIndices, Children children, BasisFactory::FlatLexicographic) const
Definition dynamicpowerbasis.hh:291
Dune::Functions::DynamicPowerPreBasis::size
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition dynamicpowerbasis.hh:131
Dune::Functions::DynamicPowerPreBasis::Node
DynamicPowerBasisNode< typename SubPreBasis::Node > Node
Template mapping root tree path to type of created tree node.
Definition dynamicpowerbasis.hh:68
Dune::Functions::DynamicPowerPreBasis::GridView
typename SPB::GridView GridView
The grid view that the FE basis is defined on.
Definition dynamicpowerbasis.hh:59
Dune::Functions::DynamicPowerPreBasis::children_
std::size_t children_
Definition dynamicpowerbasis.hh:390
Dune::Functions::DynamicPowerPreBasis::gridView
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition dynamicpowerbasis.hh:96
Dune::Functions::DynamicPowerPreBasis::minMultiIndexSize
static constexpr size_type minMultiIndexSize
Definition dynamicpowerbasis.hh:71
Dune::Functions::DynamicPowerBasisNode
Definition nodes.hh:332
concepts.hh