7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH 
    8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH 
   16#include <dune/common/filledarray.hh> 
   17#include <dune/common/tuplevector.hh> 
   18#include <dune/common/typeutilities.hh> 
   19#include <dune/common/hybridutilities.hh> 
   20#include <dune/common/rangeutilities.hh> 
   22#include <dune/functions/common/type_traits.hh> 
   23#include <dune/functions/functionspacebases/basistags.hh> 
   48namespace Dune::Functions {
 
   49namespace ContainerDescriptors {
 
   57template<
class PreBasis>
 
   60  if constexpr (
requires{ preBasis.containerDescriptor(); })
 
   61    return preBasis.containerDescriptor();
 
   67namespace ContainerDescriptors {
 
   77  static constexpr std::size_t 
size () { 
return 0; }
 
   81template<
class... Children>
 
   82using Tuple = Dune::TupleVector<Children...>;
 
   86template<
class Child0, 
class... Children,
 
   87  std::enable_if_t<(
sizeof...(Children) > 0), 
int> = 0,
 
   88  std::enable_if_t<(...|| (not std::is_same_v<Child0, Children>)), 
int> = 0>
 
   91  using Descriptor = 
Tuple<Child0,Children...>;
 
   92  return Descriptor{std::move(child0),std::move(children)...};
 
   97template<
class Child, std::
size_t n>
 
   98using Array = std::array<Child, n>;
 
  101template<
class Child0, 
class... Children,
 
  102  std::enable_if_t<(std::is_same_v<Child0, Children> &&...), 
int> = 0>
 
  105  using Descriptor = 
Array<Child0,1+
sizeof...(Children)>;
 
  106  return Descriptor{std::move(child),std::move(children)...};
 
  115template<
class Child, std::
size_t n>
 
  119  template<
class C = Child,
 
  120    std::enable_if_t<std::is_default_constructible_v<C>, 
int> = 0>
 
  127    : child_{std::move(child)}
 
  131  template<
class Index>
 
  132  const Child& 
operator[] (
const Index& )
 const { 
return child_; }
 
  135  static constexpr std::size_t 
size () { 
return n; }
 
  142template<std::
size_t n>
 
  146template<
class Child, std::
size_t n>
 
  158  template<
class C = Child,
 
  159    std::enable_if_t<std::is_default_constructible_v<C>, 
int> = 0>
 
  168    , child_{std::move(child)}
 
  172  template<
class Index>
 
  173  const Child& 
operator[] (
const Index& )
 const { 
return child_; }
 
  176  std::size_t 
size ()
 const { 
return size_; }
 
  195template<
class InnerFunc, 
class LeafFunc>
 
  198  TreeTransform (
const InnerFunc& innerFunc, 
const LeafFunc& leafFunc)
 
  199    : innerFunc_(innerFunc)
 
  200    , leafFunc_(leafFunc)
 
  203  Unknown operator() (
const Unknown& tree)
 const 
  208  auto operator() (
const Value& tree)
 const 
  210    return leafFunc_(tree);
 
  214  auto operator() (
const Tuple<V...>& tree)
 const 
  216    return unpackIntegerSequence([&](
auto... ii) {
 
  218    }, std::make_index_sequence<
sizeof...(V)>());
 
  221  template<
class V, std::
size_t n>
 
  222  auto operator() (
const Array<V,n>& tree)
 const 
  224    return unpackIntegerSequence([&](
auto... ii) {
 
  226    }, std::make_index_sequence<n>());
 
  230  auto operator() (
const Vector<V>& tree)
 const 
  232    using W = 
decltype(innerFunc_(tree[0]));
 
  234    result.reserve(tree.size());
 
  235    for (std::size_t i = 0; i < tree.size(); ++i)
 
  236      result.emplace_back(innerFunc_(tree[i]));
 
  240  template<
class V, std::
size_t n>
 
  241  auto operator() (
const UniformArray<V,n>& tree)
 const 
  247  auto operator() (
const UniformVector<V>& tree)
 const 
  253  InnerFunc innerFunc_;
 
  268template<
class Size, 
class T>
 
  269auto appendToTree (Size s, 
const T& tree)
 
  271  auto transform = TreeTransform(
 
  272    [s](
auto&& node) { 
return appendToTree(s, node); },
 
  274  return transform(tree);
 
  278template<
class... Child>
 
  281  if constexpr ((std::is_same_v<Child, FlatVector> && ...))
 
  288template<
class N, 
class Child>
 
  289auto flatLexicographicN (N n, Child child)
 
  295template<
class N, 
class GrandChild>
 
  296auto flatLexicographicN (N n, UniformVector<GrandChild> child)
 
  298  return UniformVector<GrandChild>{child.size()*n, child[0]};
 
  302template<
class N, 
class GrandChild, std::
size_t m>
 
  303auto flatLexicographicN (N n, UniformArray<GrandChild, m> child)
 
  305  if constexpr (std::is_same_v<N, std::size_t>)
 
  306    return UniformVector<GrandChild>{n*m, child[0]};
 
  308    return UniformArray<GrandChild, N::value*m>{child[0]};
 
  312template<
class N, 
class GrandChild>
 
  313auto flatLexicographicN (N n, Vector<GrandChild> child)
 
  315  auto result = Vector<GrandChild>{};
 
  316  result.reserve(child.size()*n);
 
  317  for (
auto j : Dune::range(n))
 
  318    for (
auto i : Dune::range(child.size()))
 
  319      result.emplace_back(child[i]);
 
  324template<
class N, 
class GrandChild, std::
size_t m>
 
  325auto flatLexicographicN (N n, Array<GrandChild, m> child)
 
  327  if constexpr (std::is_same_v<N, std::size_t>)
 
  329    auto result = Vector<GrandChild>{};
 
  330    result.reserve(child.size()*n);
 
  331    for (
auto j : Dune::range(n))
 
  332      for (
auto i : Dune::range(child.size()))
 
  333        result.emplace_back(child[i]);
 
  338    auto result = Array<GrandChild, N::value*m>{};
 
  339    for (
auto j : Dune::range(n))
 
  340      for (
auto i : Dune::range(child.size()))
 
  341        result.emplace_back(child[i]);
 
  347template<
class N, 
class... GrandChild>
 
  348auto flatLexicographicN (N n, Tuple<GrandChild...> child)
 
  350  constexpr std::size_t m = 
sizeof...(GrandChild);
 
  351  return Dune::unpackIntegerSequence([&](
auto... i) {
 
  353  }, std::make_index_sequence<n*m>{});
 
  357template<
class N, 
class Child>
 
  358auto flatInterleavedN (N n, Child child)
 
  364template<
class N, 
class GrandChild>
 
  365auto flatInterleavedN (N n, UniformVector<GrandChild> child)
 
  367  return UniformVector<GrandChild>{child.size()*n, child[0]};
 
  371template<
class N, 
class GrandChild, std::
size_t m>
 
  372auto flatInterleavedN (N n, UniformArray<GrandChild, m> child)
 
  374  if constexpr (std::is_integral_v<N>)
 
  375    return UniformVector<GrandChild>{n*m, child[0]};
 
  377    return UniformArray<GrandChild, N::value*m>{child[0]};
 
  381template<
class N, 
class GrandChild>
 
  382auto flatInterleavedN (N n, Vector<GrandChild> child)
 
  384  auto result = Vector<GrandChild>{};
 
  385  result.reserve(child.size()*n);
 
  386  for (
auto i : Dune::range(child.size()))
 
  387    for (
auto j : Dune::range(n))
 
  388      result.emplace_back(child[i]);
 
  393template<
class N, 
class GrandChild, std::
size_t m>
 
  394auto flatInterleavedN (N n, Array<GrandChild, m> child)
 
  396  if constexpr (std::is_integral_v<N>)
 
  398    auto result = Vector<GrandChild>{};
 
  399    result.reserve(child.size()*n);
 
  400    for (
auto i : Dune::range(child.size()))
 
  401      for (
auto j : Dune::range(n))
 
  402        result.emplace_back(child[i]);
 
  407    auto result = Array<GrandChild, N::value*m>{};
 
  408    for (
auto i : Dune::range(child.size()))
 
  409      for (
auto j : Dune::range(n))
 
  410        result.emplace_back(child[i]);
 
  416template<
class N, 
class... GrandChild>
 
  417auto flatInterleavedN (N n, Tuple<GrandChild...> child)
 
  419  constexpr std::size_t m = 
sizeof...(GrandChild);
 
  420  return Dune::unpackIntegerSequence([&](
auto... i) {
 
  422  }, std::make_index_sequence<n*m>{});
 
std::array< Child, n > Array
Descriptor for arrays with all children of the same type and static size.
Definition: containerdescriptors.hh:98
 
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::TupleVector< Children... > Tuple
Descriptor with all children of possibly different type.
Definition: containerdescriptors.hh:82
 
auto containerDescriptor(const PreBasis &preBasis)
Return the container descriptor of the pre-basis, if defined, otherwise ContainerDescriptor::Unknown.
Definition: containerdescriptors.hh:58
 
auto makeDescriptor(Child0 child, Children... children)
Generate a descriptor in case the children are all of the same type.
Definition: containerdescriptors.hh:103
 
UniformVector< Value > FlatVector
Alias for a uniform vector storing value placeholders.
Definition: containerdescriptors.hh:184
 
std::vector< Child > Vector
Descriptor for vectors with all children of the same type and dynamic size.
Definition: containerdescriptors.hh:112
 
constexpr FlatLexicographic flatLexicographic()
Creates a lexicographic merging of direct children without blocking.
Definition: basistags.hh:192
 
Fallback container descriptor if nothing else fits.
Definition: containerdescriptors.hh:52
 
The node in the descriptor tree representing a value placeholder.
Definition: containerdescriptors.hh:71
 
static constexpr std::size_t size()
A value placeholder does not have any sub-descriptors, thus its size is zero.
Definition: containerdescriptors.hh:77
 
Value operator[](const Index &) const
The child access method is only available for the interface, but should not be called.
Definition: containerdescriptors.hh:74