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 {
58template<
class PreBasis>
59auto containerDescriptorImpl(
const PreBasis& preBasis, Dune::PriorityTag<1>)
60 ->
decltype(preBasis.containerDescriptor())
62 return preBasis.containerDescriptor();
65template<
class PreBasis>
66auto containerDescriptorImpl(
const PreBasis& preBasis, Dune::PriorityTag<0>)
68 return ContainerDescriptors::Unknown{};
74template<
class PreBasis>
75auto containerDescriptor(
const PreBasis& preBasis)
77 return Impl::containerDescriptorImpl(preBasis, Dune::PriorityTag<2>{});
81namespace ContainerDescriptors {
91 static constexpr std::size_t
size () {
return 0; }
95template<
class... Children>
96using Tuple = Dune::TupleVector<Children...>;
100template<
class Child0,
class... Children,
101 std::enable_if_t<(
sizeof...(Children) > 0),
int> = 0,
102 std::enable_if_t<(...|| (not std::is_same_v<Child0, Children>)),
int> = 0>
103auto makeDescriptor (Child0 child0, Children... children)
105 using Descriptor = Tuple<Child0,Children...>;
106 return Descriptor{std::move(child0),std::move(children)...};
111template<
class Child, std::
size_t n>
112using Array = std::array<Child, n>;
115template<
class Child0,
class... Children,
116 std::enable_if_t<(std::is_same_v<Child0, Children> &&...),
int> = 0>
117auto makeDescriptor (Child0 child, Children... children)
119 using Descriptor = Array<Child0,1+
sizeof...(Children)>;
120 return Descriptor{std::move(child),std::move(children)...};
126using Vector = std::vector<Child>;
129template<
class Child, std::
size_t n>
133 template<
class C = Child,
134 std::enable_if_t<std::is_default_constructible_v<C>,
int> = 0>
141 : child_{std::move(child)}
145 template<
class Index>
146 const Child&
operator[] (
const Index& )
const {
return child_; }
149 static constexpr std::size_t
size () {
return n; }
156template<std::
size_t n>
157using FlatArray = UniformArray<Value,n>;
160template<
class Child, std::
size_t n>
161auto makeUniformDescriptor (std::integral_constant<std::size_t,n>, Child child)
163 return UniformArray<Child,n>{std::move(child)};
172 template<
class C = Child,
173 std::enable_if_t<std::is_default_constructible_v<C>,
int> = 0>
182 , child_{std::move(child)}
186 template<
class Index>
187 const Child&
operator[] (
const Index& )
const {
return child_; }
190 std::size_t
size ()
const {
return size_; }
198using FlatVector = UniformVector<Value>;
202auto makeUniformDescriptor (std::size_t n, Child child)
204 return UniformVector<Child>{n,std::move(child)};
209template<
class InnerFunc,
class LeafFunc>
212 TreeTransform (
const InnerFunc& innerFunc,
const LeafFunc& leafFunc)
213 : innerFunc_(innerFunc)
214 , leafFunc_(leafFunc)
217 Unknown operator() (
const Unknown& tree)
const
222 auto operator() (
const Value& tree)
const
224 return leafFunc_(tree);
228 auto operator() (
const Tuple<V...>& tree)
const
230 return unpackIntegerSequence([&](
auto... ii) {
231 return makeDescriptor(innerFunc_(tree[ii])...);
232 }, std::make_index_sequence<
sizeof...(V)>());
235 template<
class V, std::
size_t n>
236 auto operator() (
const Array<V,n>& tree)
const
238 return unpackIntegerSequence([&](
auto... ii) {
239 return makeDescriptor(innerFunc_(tree[ii])...);
240 }, std::make_index_sequence<n>());
244 auto operator() (
const Vector<V>& tree)
const
246 using W =
decltype(innerFunc_(tree[0]));
248 result.reserve(tree.size());
249 for (std::size_t i = 0; i < tree.size(); ++i)
250 result.emplace_back(innerFunc_(tree[i]));
254 template<
class V, std::
size_t n>
255 auto operator() (
const UniformArray<V,n>& tree)
const
257 return makeUniformDescriptor(Dune::index_constant<n>{}, innerFunc_(tree[0]));
261 auto operator() (
const UniformVector<V>& tree)
const
263 return makeUniformDescriptor(tree.size(), innerFunc_(tree[0]));
267 InnerFunc innerFunc_;
282template<
class Size,
class T>
283auto appendToTree (Size s,
const T& tree)
285 auto transform = TreeTransform(
286 [s](
auto&& node) {
return appendToTree(s, node); },
287 [s](
auto&& node) {
return makeUniformDescriptor(s, node); });
288 return transform(tree);
292template<
class... Child>
295 if constexpr ((std::is_same_v<Child, FlatVector> && ...))
296 return FlatVector((child.size() + ...));
302template<
class N,
class Child>
303auto flatLexicographicN (N n, Child child)
309template<
class N,
class GrandChild>
310auto flatLexicographicN (N n, UniformVector<GrandChild> child)
312 return UniformVector<GrandChild>{child.size()*n, child[0]};
316template<
class N,
class GrandChild, std::
size_t m>
317auto flatLexicographicN (N n, UniformArray<GrandChild, m> child)
319 if constexpr (std::is_same_v<N, std::size_t>)
320 return UniformVector<GrandChild>{n*m, child[0]};
322 return UniformArray<GrandChild, N::value*m>{child[0]};
326template<
class N,
class GrandChild>
327auto flatLexicographicN (N n, Vector<GrandChild> child)
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]);
338template<
class N,
class GrandChild, std::
size_t m>
339auto flatLexicographicN (N n, Array<GrandChild, m> child)
341 if constexpr (std::is_same_v<N, std::size_t>)
343 auto result = Vector<GrandChild>{};
344 result.reserve(child.size()*n);
345 for (
auto j : Dune::range(n))
346 for (
auto i : Dune::range(child.size()))
347 result.emplace_back(child[i]);
352 auto result = Array<GrandChild, N::value*m>{};
353 for (
auto j : Dune::range(n))
354 for (
auto i : Dune::range(child.size()))
355 result.emplace_back(child[i]);
361template<
class N,
class... GrandChild>
362auto flatLexicographicN (N n, Tuple<GrandChild...> child)
364 constexpr std::size_t m =
sizeof...(GrandChild);
365 return Dune::unpackIntegerSequence([&](
auto... i) {
366 return makeDescriptor(std::get<i%m>(child)...);
367 }, std::make_index_sequence<n*m>{});
371template<
class N,
class Child>
372auto flatInterleavedN (N n, Child child)
378template<
class N,
class GrandChild>
379auto flatInterleavedN (N n, UniformVector<GrandChild> child)
381 return UniformVector<GrandChild>{child.size()*n, child[0]};
385template<
class N,
class GrandChild, std::
size_t m>
386auto flatInterleavedN (N n, UniformArray<GrandChild, m> child)
388 if constexpr (std::is_integral_v<N>)
389 return UniformVector<GrandChild>{n*m, child[0]};
391 return UniformArray<GrandChild, N::value*m>{child[0]};
395template<
class N,
class GrandChild>
396auto flatInterleavedN (N n, Vector<GrandChild> child)
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]);
407template<
class N,
class GrandChild, std::
size_t m>
408auto flatInterleavedN (N n, Array<GrandChild, m> child)
410 if constexpr (std::is_integral_v<N>)
412 auto result = Vector<GrandChild>{};
413 result.reserve(child.size()*n);
414 for (
auto i : Dune::range(child.size()))
415 for (
auto j : Dune::range(n))
416 result.emplace_back(child[i]);
421 auto result = Array<GrandChild, N::value*m>{};
422 for (
auto i : Dune::range(child.size()))
423 for (
auto j : Dune::range(n))
424 result.emplace_back(child[i]);
430template<
class N,
class... GrandChild>
431auto flatInterleavedN (N n, Tuple<GrandChild...> child)
433 constexpr std::size_t m =
sizeof...(GrandChild);
434 return Dune::unpackIntegerSequence([&](
auto... i) {
435 return makeDescriptor(std::get<i/n>(child)...);
436 }, 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:85
static constexpr std::size_t size()
A value placeholder does not have any sub-descriptors, thus its size is zero.
Definition: containerdescriptors.hh:91
Value operator[](const Index &) const
The child access method is only available for the interface, but should not be called.
Definition: containerdescriptors.hh:88