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>
58auto containerDescriptor(
const PreBasis& preBasis)
60 if constexpr (
requires{ preBasis.containerDescriptor(); })
61 return preBasis.containerDescriptor();
63 return ContainerDescriptors::Unknown{};
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>
89auto makeDescriptor (Child0 child0, Children... children)
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>
103auto makeDescriptor (Child0 child, Children... children)
105 using Descriptor = Array<Child0,1+
sizeof...(Children)>;
106 return Descriptor{std::move(child),std::move(children)...};
112using Vector = std::vector<Child>;
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>
143using FlatArray = UniformArray<Value,n>;
146template<
class Child, std::
size_t n>
147auto makeUniformDescriptor (std::integral_constant<std::size_t,n>, Child child)
149 return UniformArray<Child,n>{std::move(child)};
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_; }
184using FlatVector = UniformVector<Value>;
188auto makeUniformDescriptor (std::size_t n, Child child)
190 return UniformVector<Child>{n,std::move(child)};
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) {
217 return makeDescriptor(innerFunc_(tree[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) {
225 return makeDescriptor(innerFunc_(tree[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
243 return makeUniformDescriptor(Dune::index_constant<n>{}, innerFunc_(tree[0]));
247 auto operator() (
const UniformVector<V>& tree)
const
249 return makeUniformDescriptor(tree.size(), innerFunc_(tree[0]));
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); },
273 [s](
auto&& node) {
return makeUniformDescriptor(s, node); });
274 return transform(tree);
278template<
class... Child>
281 if constexpr ((std::is_same_v<Child, FlatVector> && ...))
282 return FlatVector((child.size() + ...));
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) {
352 return makeDescriptor(std::get<i%m>(child)...);
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) {
421 return makeDescriptor(std::get<i/n>(child)...);
422 }, std::make_index_sequence<n*m>{});
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