3#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
4#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
9#include <dune/common/std/utility.hh>
10#include <dune/common/std/apply.hh>
11#include <dune/common/hybridutilities.hh>
12#include <dune/common/reservedvector.hh>
13#include <dune/common/typeutilities.hh>
14#include <dune/common/hybridutilities.hh>
15#include <dune/common/tupleutility.hh>
16#include <dune/common/tuplevector.hh>
18#include <dune/typetree/compositenode.hh>
19#include <dune/typetree/utility.hh>
21#include <dune/functions/common/staticforloop.hh>
22#include <dune/functions/common/type_traits.hh>
23#include <dune/functions/common/utility.hh>
24#include <dune/functions/functionspacebases/basistags.hh>
25#include <dune/functions/functionspacebases/nodes.hh>
26#include <dune/functions/functionspacebases/concepts.hh>
44template<
class PB,
class IMS>
45class CompositeNodeIndexSet;
59template<
class MI,
class IMS,
class... SPB>
68 template<std::
size_t i>
72 using GridView =
typename std::tuple_element_t<0, SubPreBases>::GridView;
81 static const std::size_t children =
sizeof...(SPB);
83 template<
class,
class>
84 friend class CompositeNodeIndexSet;
86 using ChildIndices = std::make_index_sequence<children>;
88 template<
class Indices>
91 template<std::size_t... indices>
92 struct Types<
Dune::Std::index_sequence<indices...>>
94 template<std::
size_t i>
95 using SubNode =
typename std::tuple_element_t<i, SubPreBases>::Node;
97 template<std::
size_t i>
98 using SubIndexSet =
typename std::tuple_element_t<i, SubPreBases>::IndexSet;
100 using SubIndexSets = std::tuple<SubIndexSet<indices>...>;
102 using Node = CompositeBasisNode<SubNode<indices>...>;
105 using SubIndexSets =
typename Types<ChildIndices>::SubIndexSets;
110 using Node =
typename Types<ChildIndices>::Node;
113 using IndexSet = CompositeNodeIndexSet<CompositePreBasis, IMS>;
126 template<
class... SFArgs,
130 subPreBases_(std::forward<SFArgs>(sfArgs)...)
132 Hybrid::forEach(subPreBases_, [&](
const auto&
subPreBasis){
133 static_assert(models<Concept::PreBasis<GridView>, std::decay_t<
decltype(
subPreBasis)>>(),
"Subprebases passed to CompositePreBasis does not model the PreBasis concept.");
140 Hybrid::forEach(ChildIndices(), [&](
auto i) {
148 return std::get<0>(subPreBases_).gridView();
154 Hybrid::forEach(ChildIndices(), [&](
auto i) {
165 Hybrid::forEach(ChildIndices(), [&](
auto i) {
180 unpackIntegerSequence([&](
auto... i) {
201 if (prefix.size() == 0)
204 return Hybrid::switchCases(ChildIndices(), prefix[0], [&] (
auto i) {
205 typename SubPreBasis<i>::SizePrefix subPrefix;
206 for(std::size_t i=1; i<prefix.size(); ++i)
207 subPrefix.push_back(prefix[i]);
208 return this->subPreBasis(i).size(subPrefix);
217 if (prefix.size() == 0)
218 Hybrid::forEach(ChildIndices(), [&](
auto i) {
223 staticFindInRange<0, children>([&](
auto i) {
225 if (shiftedFirstDigit < firstDigitSize)
227 typename SubPreBasis<i>::SizePrefix subPrefix;
228 subPrefix.push_back(shiftedFirstDigit);
229 for(std::size_t i=1; i<prefix.size(); ++i)
230 subPrefix.push_back(prefix[i]);
234 shiftedFirstDigit -= firstDigitSize;
248 Hybrid::forEach(ChildIndices(), [&](
auto i) {
259 Hybrid::forEach(ChildIndices(), [&](
auto i) {
266 template<std::
size_t i>
269 return std::get<i>(subPreBases_);
273 template<std::
size_t i>
276 return std::get<i>(subPreBases_);
280 std::tuple<SPB...> subPreBases_;
285template<
class PB,
class IMS>
286class CompositeNodeIndexSet
290 using size_type = std::size_t;
292 using MultiIndex =
typename PreBasis::MultiIndex;
293 using Node =
typename PreBasis::Node;
297 using IndexMergingStrategy = IMS;
298 using SubIndexSets =
typename PreBasis::SubIndexSets;
299 using ChildIndices =
typename PreBasis::ChildIndices;
303 CompositeNodeIndexSet(
const PreBasis & preBasis, SubIndexSets&& subNodeIndexSets) :
304 preBasis_(&preBasis),
305 subNodeIndexSetTuple_(std::move(subNodeIndexSets)),
309 void bind(
const Node& node)
312 Hybrid::forEach(ChildIndices(), [&](
auto i) {
313 Hybrid::elementAt(subNodeIndexSetTuple_, i).bind(node.child(i));
320 Hybrid::forEach(ChildIndices(), [&](
auto i) {
321 Hybrid::elementAt(subNodeIndexSetTuple_, i).unbind();
325 size_type size()
const
327 return node_->size();
331 template<
typename It>
332 It indices(It it)
const
334 return indices(it, IndexMergingStrategy{});
337 template<
typename It>
338 It indices(It multiIndices, BasisFactory::FlatLexicographic)
const
340 size_type firstComponentOffset = 0;
342 Hybrid::forEach(ChildIndices(), [&](
auto child){
343 const auto& subNodeIndexSet = Hybrid::elementAt(subNodeIndexSetTuple_, child);
344 const auto& subPreBasis = preBasis_->subPreBasis(child);
345 size_type subTreeSize = subNodeIndexSet.size();
349 subNodeIndexSet.indices(multiIndices);
350 for (std::size_t i = 0; i<subTreeSize; ++i)
351 multiIndices[i][0] += firstComponentOffset;
353 firstComponentOffset += subPreBasis.size({});
355 multiIndices += subTreeSize;
360 static void multiIndexPushFront(MultiIndex& M, size_type M0)
362 M.resize(M.size()+1);
363 for(std::size_t i=M.size()-1; i>0; --i)
368 template<
typename It>
369 It indices(It multiIndices, BasisFactory::BlockedLexicographic)
const
372 Hybrid::forEach(ChildIndices(), [&](
auto child){
373 const auto& subNodeIndexSet = Hybrid::elementAt(subNodeIndexSetTuple_, child);
374 size_type subTreeSize = subNodeIndexSet.size();
376 subNodeIndexSet.indices(multiIndices);
378 for (std::size_t i = 0; i<subTreeSize; ++i)
379 this->multiIndexPushFront(multiIndices[i], child);
381 multiIndices += subTreeSize;
387 const PreBasis* preBasis_;
388 SubIndexSets subNodeIndexSetTuple_;
394namespace BasisFactory {
399constexpr std::size_t maxHelper(ST0&& i0)
404template<
class ST0,
class... ST>
405constexpr std::size_t maxHelper(ST0&& i0, ST&&... i)
407 return (i0 > maxHelper(i...)) ? i0 : maxHelper(i...);
410template<
class IndexMergingStrategy,
class... ChildPreBasisFactory>
411class CompositePreBasisFactory
413 static const bool isBlocked = std::is_same<IndexMergingStrategy,BlockedLexicographic>::value or std::is_same<IndexMergingStrategy,BlockedInterleaved>::value;
415 static const std::size_t maxChildIndexSize = maxHelper(ChildPreBasisFactory::requiredMultiIndexSize...);
417 template<
class MultiIndex,
class GridView,
class... ChildPreBasis>
418 auto makePreBasisFromChildPreBases(
const GridView&, ChildPreBasis&&... childPreBasis)
const
420 return CompositePreBasis<MultiIndex, IndexMergingStrategy, std::decay_t<ChildPreBasis>...>(std::forward<ChildPreBasis>(childPreBasis)...);
425 static const std::size_t requiredMultiIndexSize = isBlocked ? (maxChildIndexSize+1) : maxChildIndexSize;
427 CompositePreBasisFactory(
const ChildPreBasisFactory&... childPreBasisFactory) :
428 childPreBasisFactories_(childPreBasisFactory...)
431 CompositePreBasisFactory(ChildPreBasisFactory&&... childPreBasisFactory) :
432 childPreBasisFactories_(std::move(childPreBasisFactory)...)
435 template<
class MultiIndex,
class Gr
idView>
436 auto makePreBasis(
const GridView& gridView)
const
439 return Std::apply([&](
const auto&... childPreBasisFactory) {
440 return this->makePreBasisFromChildPreBases<MultiIndex>(gridView, childPreBasisFactory.template makePreBasis<MultiIndex>(gridView)...);
441 }, childPreBasisFactories_);
445 std::tuple<ChildPreBasisFactory...> childPreBasisFactories_;
464 std::enable_if_t<Concept::isIndexMergingStrategy<
typename LastType<Args...>::type>(),
int> = 0>
470 using ArgTuple = std::tuple<std::decay_t<Args>...>;
473 constexpr std::size_t children = Dune::SizeOf<Args...>::value-1;
479 auto childIndices = std::make_index_sequence<children>{};
482 return applyPartial([](
auto&&... childPreBasisFactory){
483 return Imp::CompositePreBasisFactory<
IndexMergingStrategy, std::decay_t<
decltype(childPreBasisFactory)>...>(std::forward<
decltype(childPreBasisFactory)>(childPreBasisFactory)...);
485 std::forward_as_tuple(std::forward<Args>(args)...),
502 std::enable_if_t<not Concept::isIndexMergingStrategy<
typename LastType<Args...>::type>(),
int> = 0>
505 return Imp::CompositePreBasisFactory<BasisFactory::BlockedLexicographic, std::decay_t<Args>...>(std::forward<Args>(args)...);
511namespace BasisBuilder {
513 using namespace BasisFactory;
A pre-basis for composite bases.
Definition: compositebasis.hh:61
typename std::tuple_element_t< 0, SubPreBases >::GridView GridView
The grid view that the FE basis is defined on.
Definition: compositebasis.hh:72
Node makeNode() const
Create tree node.
Definition: compositebasis.hh:162
size_type size() const
Same as size(prefix) with empty prefix.
Definition: compositebasis.hh:186
typename Types< ChildIndices >::Node Node
Template mapping root tree path to type of created tree node.
Definition: compositebasis.hh:110
Dune::ReservedVector< size_type, MultiIndex::max_size()> SizePrefix
Type used for prefixes handed to the size() method.
Definition: compositebasis.hh:119
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: compositebasis.hh:244
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:267
std::size_t size_type
Type used for indices and size information.
Definition: compositebasis.hh:75
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: compositebasis.hh:192
IndexSet makeIndexSet() const
Create tree node index set.
Definition: compositebasis.hh:177
CompositeNodeIndexSet< CompositePreBasis, IMS > IndexSet
Template mapping root tree path to type of created tree node index set.
Definition: compositebasis.hh:113
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: compositebasis.hh:152
CompositePreBasis(SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: compositebasis.hh:129
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child pre-bases.
Definition: compositebasis.hh:78
std::tuple_element_t< i, SubPreBases > SubPreBasis
Export individual child pre-bases by index.
Definition: compositebasis.hh:69
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: compositebasis.hh:116
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: compositebasis.hh:255
SubPreBasis< i > & subPreBasis(Dune::index_constant< i >={})
Mutable access to the stored prebasis of the factor in the power space.
Definition: compositebasis.hh:274
std::tuple< SPB... > SubPreBases
Tuple of child pre-bases.
Definition: compositebasis.hh:65
void initializeIndices()
Initialize the global indices.
Definition: compositebasis.hh:138
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: compositebasis.hh:146
auto composite(Args &&... args)
Create a factory builder that can build a CompositePreBasis.
Definition: compositebasis.hh:465
typename std::enable_if< std::is_constructible< T, Args... >::value, int >::type enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:26
Definition: polynomial.hh:10
Lexicographic merging of direct children with blocking (i.e. creating one block per direct child).
Definition: basistags.hh:148
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:44
Get last entry of type list.
Definition: utility.hh:222