7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
13#include <dune/common/hybridutilities.hh>
14#include <dune/common/reservedvector.hh>
15#include <dune/common/typeutilities.hh>
16#include <dune/common/hybridutilities.hh>
17#include <dune/common/tupleutility.hh>
18#include <dune/common/tuplevector.hh>
20#include <dune/functions/common/staticforloop.hh>
21#include <dune/functions/common/type_traits.hh>
22#include <dune/functions/common/utility.hh>
23#include <dune/functions/functionspacebases/basistags.hh>
24#include <dune/functions/functionspacebases/nodes.hh>
25#include <dune/functions/functionspacebases/concepts.hh>
26#include <dune/functions/functionspacebases/containerdescriptors.hh>
27#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
55template<
class IMS,
class... SPB>
58 static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
65 template<std::
size_t i>
69 using GridView =
typename std::tuple_element_t<0, SubPreBases>::GridView;
78 static const std::size_t children =
sizeof...(SPB);
80 using ChildIndices = std::make_index_sequence<children>;
85 using Node = CompositeBasisNode<
typename SPB::Node...>;
87 static constexpr size_type maxMultiIndexSize = std::max({SPB::maxMultiIndexSize...}) + isBlocked;
88 static constexpr size_type minMultiIndexSize = std::min({SPB::minMultiIndexSize...}) + isBlocked;
89 static constexpr size_type multiIndexBufferSize = std::max({SPB::multiIndexBufferSize...}) + isBlocked;
96 template<
class... SFArgs,
100 subPreBases_(std::forward<SFArgs>(sfArgs)...)
102 Hybrid::forEach(subPreBases_, [&](
const auto&
subPreBasis){
103 static_assert(models<Concept::PreBasis<GridView>, std::decay_t<
decltype(
subPreBasis)>>(),
"Subprebases passed to CompositePreBasis does not model the PreBasis concept.");
114 std::enable_if_t<std::conjunction_v<
115 std::bool_constant<(children > 1)>,
116 std::is_same<GV, GridView>,
117 std::is_constructible<SPB, GridView>...
120 subPreBases_(SPB(gv)...)
122 Hybrid::forEach(subPreBases_, [&](
const auto&
subPreBasis){
123 static_assert(models<Concept::PreBasis<GridView>, std::decay_t<
decltype(
subPreBasis)>>(),
"Subprebases passed to CompositePreBasis does not model the PreBasis concept.");
130 Hybrid::forEach(ChildIndices(), [&](
auto i) {
138 return std::get<0>(subPreBases_).gridView();
144 Hybrid::forEach(ChildIndices(), [&](
auto i) {
155 Hybrid::forEach(ChildIndices(), [&](
auto i) {
164 return size(Dune::ReservedVector<size_type, multiIndexBufferSize>{});
168 template<
class SizePrefix>
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>
185 size_type size(SizePrefix prefix, BasisFactory::BlockedLexicographic)
const
187 if (prefix.size() == 0)
190 auto front = prefix.front();
191 multiIndexPopFront(prefix);
192 return Hybrid::switchCases(ChildIndices(), front, [&] (
auto i) {
199 template<
class SizePrefix>
200 size_type size(SizePrefix prefix, BasisFactory::FlatLexicographic)
const
203 if (prefix.size() == 0)
204 Hybrid::forEach(ChildIndices(), [&](
auto i) {
208 staticFindInRange<0, children>([&](
auto i) {
210 if (prefix[0] < firstDigitSize)
215 prefix[0] -= firstDigitSize;
229 Hybrid::forEach(ChildIndices(), [&](
auto i) {
240 Hybrid::forEach(ChildIndices(), [&](
auto i) {
247 template<std::
size_t i>
250 return std::get<i>(subPreBases_);
254 template<std::
size_t i>
257 return std::get<i>(subPreBases_);
267 template<
typename It>
276 namespace CD = Dune::Functions::ContainerDescriptors;
277 if constexpr(std::is_same_v<IMS, BasisFactory::BlockedLexicographic>) {
278 return std::apply([&](
auto const&... spb) {
279 return CD::makeDescriptor(Dune::Functions::containerDescriptor(spb)...);
282 else if constexpr(std::is_same_v<IMS, BasisFactory::FlatLexicographic>) {
291 template<
typename It>
296 Hybrid::forEach(ChildIndices(), [&](
auto child){
301 subPreBasis(child).indices(node.child(child), multiIndices);
302 for (std::size_t i = 0; i<subTreeSize; ++i)
303 multiIndices[i][0] += firstComponentOffset;
307 multiIndices += subTreeSize;
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<
typename It>
322 It
indices(
const Node& node, It multiIndices, BasisFactory::BlockedLexicographic)
const
325 Hybrid::forEach(ChildIndices(), [&](
auto child){
328 subPreBasis(child).indices(node.child(child), multiIndices);
330 for (std::size_t i = 0; i<subTreeSize; ++i)
331 this->multiIndexPushFront(multiIndices[i], child);
333 multiIndices += subTreeSize;
338 std::tuple<SPB...> subPreBases_;
343namespace BasisFactory {
347template<
class IndexMergingStrategy,
class... ChildPreBasisFactory>
348class CompositePreBasisFactory
351 template<
class GridView,
class... ChildPreBasis>
352 auto makePreBasisFromChildPreBases(
const GridView&, ChildPreBasis&&... childPreBasis)
const
354 return CompositePreBasis<IndexMergingStrategy, std::decay_t<ChildPreBasis>...>(std::forward<ChildPreBasis>(childPreBasis)...);
359 CompositePreBasisFactory(
const ChildPreBasisFactory&... childPreBasisFactory) :
360 childPreBasisFactories_(childPreBasisFactory...)
363 CompositePreBasisFactory(ChildPreBasisFactory&&... childPreBasisFactory) :
364 childPreBasisFactories_(std::move(childPreBasisFactory)...)
367 template<
class Gr
idView>
368 auto operator()(
const GridView& gridView)
const
371 return std::apply([&](
const auto&... childPreBasisFactory) {
372 return this->makePreBasisFromChildPreBases(gridView, childPreBasisFactory(gridView)...);
373 }, childPreBasisFactories_);
377 std::tuple<ChildPreBasisFactory...> childPreBasisFactories_;
396 std::enable_if_t<Concept::isIndexMergingStrategy<
typename LastType<Args...>::type>(),
int> = 0>
402 using ArgTuple = std::tuple<std::decay_t<Args>...>;
405 constexpr std::size_t children =
sizeof...(Args) - 1;
411 auto childIndices = std::make_index_sequence<children>{};
414 return applyPartial([](
auto&&... childPreBasisFactory){
415 return Imp::CompositePreBasisFactory<
IndexMergingStrategy, std::decay_t<
decltype(childPreBasisFactory)>...>(std::forward<
decltype(childPreBasisFactory)>(childPreBasisFactory)...);
417 std::forward_as_tuple(std::forward<Args>(args)...),
434 std::enable_if_t<not Concept::isIndexMergingStrategy<
typename LastType<Args...>::type>(),
int> = 0>
437 return Imp::CompositePreBasisFactory<BasisFactory::BlockedLexicographic, std::decay_t<Args>...>(std::forward<Args>(args)...);
443namespace [[deprecated(
"Will be removed after Dune 2.10")]] BasisBuilder {
445 using namespace BasisFactory;
A pre-basis for composite bases.
Definition: compositebasis.hh:57
SubPreBasis< i > & subPreBasis(Dune::index_constant< i >={})
Mutable access to the stored prebasis of the factor in the power space.
Definition: compositebasis.hh:255
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child pre-bases.
Definition: compositebasis.hh:75
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: compositebasis.hh:236
const SubPreBasis< i > & subPreBasis(Dune::index_constant< i >={}) const
Const access to the stored prebasis of the factor in the power space.
Definition: compositebasis.hh:248
std::size_t size_type
Type used for indices and size information.
Definition: compositebasis.hh:72
CompositeBasisNode< typename SPB::Node... > Node
Template mapping root tree path to type of created tree node.
Definition: compositebasis.hh:85
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: compositebasis.hh:169
CompositePreBasis(SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: compositebasis.hh:99
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: compositebasis.hh:225
CompositePreBasis(const GV &gv)
Constructor for given GridView.
Definition: compositebasis.hh:119
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: compositebasis.hh:268
size_type size() const
Same as size(prefix) with empty prefix.
Definition: compositebasis.hh:162
typename std::tuple_element_t< 0, SubPreBases >::GridView GridView
The grid view that the FE basis is defined on.
Definition: compositebasis.hh:69
std::tuple< SPB... > SubPreBases
Tuple of child pre-bases.
Definition: compositebasis.hh:62
Node makeNode() const
Create tree node.
Definition: compositebasis.hh:152
void initializeIndices()
Initialize the global indices.
Definition: compositebasis.hh:128
std::tuple_element_t< i, SubPreBases > SubPreBasis
Export individual child pre-bases by index.
Definition: compositebasis.hh:66
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: compositebasis.hh:142
const auto & subPreBases() const
Const access to the stored prebases tuple.
Definition: compositebasis.hh:261
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: compositebasis.hh:136
auto containerDescriptor() const
Return the associated container descriptor.
Definition: compositebasis.hh:274
auto composite(Args &&... args)
Create a factory builder that can build a CompositePreBasis.
Definition: compositebasis.hh:397
std::enable_if_t< std::is_constructible_v< T, Args... >, int > enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:31
Definition: polynomial.hh:17
Lexicographic merging of direct children without blocking.
Definition: basistags.hh:84
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:48
Fallback container descriptor if nothing else fits.
Definition: containerdescriptors.hh:50
Get last entry of type list.
Definition: utility.hh:226