Loading...
Searching...
No Matches
containerdescriptors.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH
#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH
#include <array>
#include <cassert>
#include <functional>
#include <type_traits>
#include <vector>
#include <dune/common/filledarray.hh>
#include <dune/common/tuplevector.hh>
#include <dune/common/typeutilities.hh>
#include <dune/common/hybridutilities.hh>
#include <dune/common/rangeutilities.hh>
#include <dune/functions/common/type_traits.hh>
#include <dune/functions/functionspacebases/basistags.hh>
namespace Dune::Functions {
namespace ContainerDescriptors {
struct Unknown {};
} // end namespace ContainerDescriptors
template<class PreBasis>
auto containerDescriptor(const PreBasis& preBasis)
{
if constexpr (requires{ preBasis.containerDescriptor(); })
return preBasis.containerDescriptor();
else
return ContainerDescriptors::Unknown{};
}
namespace ContainerDescriptors {
struct Value
{
template<class Index>
Value operator[] (const Index&) const { return {}; }
static constexpr std::size_t size () { return 0; }
};
template<class... Children>
using Tuple = Dune::TupleVector<Children...>;
template<class Child0, class... Children,
std::enable_if_t<(sizeof...(Children) > 0), int> = 0,
std::enable_if_t<(...|| (not std::is_same_v<Child0, Children>)), int> = 0>
auto makeDescriptor (Child0 child0, Children... children)
{
using Descriptor = Tuple<Child0,Children...>;
return Descriptor{std::move(child0),std::move(children)...};
}
template<class Child, std::size_t n>
using Array = std::array<Child, n>;
template<class Child0, class... Children,
std::enable_if_t<(std::is_same_v<Child0, Children> &&...), int> = 0>
auto makeDescriptor (Child0 child, Children... children)
{
using Descriptor = Array<Child0,1+sizeof...(Children)>;
return Descriptor{std::move(child),std::move(children)...};
}
template<class Child>
using Vector = std::vector<Child>;
template<class Child, std::size_t n>
struct UniformArray
{
template<class C = Child,
std::enable_if_t<std::is_default_constructible_v<C>, int> = 0>
UniformArray ()
: child_{}
{}
explicit UniformArray (Child child)
: child_{std::move(child)}
{}
template<class Index>
const Child& operator[] (const Index& /*i*/) const { return child_; }
static constexpr std::size_t size () { return n; }
private:
Child child_;
};
template<std::size_t n>
using FlatArray = UniformArray<Value,n>;
template<class Child, std::size_t n>
auto makeUniformDescriptor (std::integral_constant<std::size_t,n>, Child child)
{
return UniformArray<Child,n>{std::move(child)};
}
template<class Child>
struct UniformVector
{
template<class C = Child,
std::enable_if_t<std::is_default_constructible_v<C>, int> = 0>
explicit UniformVector (std::size_t size)
: size_{size}
, child_{}
{}
UniformVector (std::size_t size, Child child)
: size_{size}
, child_{std::move(child)}
{}
template<class Index>
const Child& operator[] (const Index& /*i*/) const { return child_; }
std::size_t size () const { return size_; }
private:
std::size_t size_;
Child child_;
};
using FlatVector = UniformVector<Value>;
template<class Child>
auto makeUniformDescriptor (std::size_t n, Child child)
{
return UniformVector<Child>{n,std::move(child)};
}
namespace Impl {
template<class InnerFunc, class LeafFunc>
struct TreeTransform
{
TreeTransform (const InnerFunc& innerFunc, const LeafFunc& leafFunc)
: innerFunc_(innerFunc)
, leafFunc_(leafFunc)
{}
Unknown operator() (const Unknown& tree) const
{
return tree;
}
auto operator() (const Value& tree) const
{
return leafFunc_(tree);
}
template<class... V>
auto operator() (const Tuple<V...>& tree) const
{
return unpackIntegerSequence([&](auto... ii) {
return makeDescriptor(innerFunc_(tree[ii])...);
}, std::make_index_sequence<sizeof...(V)>());
}
template<class V, std::size_t n>
auto operator() (const Array<V,n>& tree) const
{
return unpackIntegerSequence([&](auto... ii) {
return makeDescriptor(innerFunc_(tree[ii])...);
}, std::make_index_sequence<n>());
}
template<class V>
auto operator() (const Vector<V>& tree) const
{
using W = decltype(innerFunc_(tree[0]));
Vector<W> result;
result.reserve(tree.size());
for (std::size_t i = 0; i < tree.size(); ++i)
result.emplace_back(innerFunc_(tree[i]));
return result;
}
template<class V, std::size_t n>
auto operator() (const UniformArray<V,n>& tree) const
{
return makeUniformDescriptor(Dune::index_constant<n>{}, innerFunc_(tree[0]));
}
template<class V>
auto operator() (const UniformVector<V>& tree) const
{
return makeUniformDescriptor(tree.size(), innerFunc_(tree[0]));
}
private:
InnerFunc innerFunc_;
LeafFunc leafFunc_;
};
template<class Size, class T>
auto appendToTree (Size s, const T& tree)
{
auto transform = TreeTransform(
[s](auto&& node) { return appendToTree(s, node); },
[s](auto&& node) { return makeUniformDescriptor(s, node); });
return transform(tree);
}
template<class... Child>
auto flatLexicographic (Child... child)
{
if constexpr ((std::is_same_v<Child, FlatVector> && ...))
return FlatVector((child.size() + ...));
else
return Unknown{};
}
template<class N, class Child>
auto flatLexicographicN (N n, Child child)
{
return Unknown{};
}
template<class N, class GrandChild>
auto flatLexicographicN (N n, UniformVector<GrandChild> child)
{
return UniformVector<GrandChild>{child.size()*n, child[0]};
}
template<class N, class GrandChild, std::size_t m>
auto flatLexicographicN (N n, UniformArray<GrandChild, m> child)
{
if constexpr (std::is_same_v<N, std::size_t>)
return UniformVector<GrandChild>{n*m, child[0]};
else
return UniformArray<GrandChild, N::value*m>{child[0]};
}
template<class N, class GrandChild>
auto flatLexicographicN (N n, Vector<GrandChild> child)
{
auto result = Vector<GrandChild>{};
result.reserve(child.size()*n);
for (auto j : Dune::range(n))
for (auto i : Dune::range(child.size()))
result.emplace_back(child[i]);
return result;
}
template<class N, class GrandChild, std::size_t m>
auto flatLexicographicN (N n, Array<GrandChild, m> child)
{
if constexpr (std::is_same_v<N, std::size_t>)
{
auto result = Vector<GrandChild>{};
result.reserve(child.size()*n);
for (auto j : Dune::range(n))
for (auto i : Dune::range(child.size()))
result.emplace_back(child[i]);
return result;
}
else
{
auto result = Array<GrandChild, N::value*m>{};
for (auto j : Dune::range(n))
for (auto i : Dune::range(child.size()))
result.emplace_back(child[i]);
return result;
}
}
template<class N, class... GrandChild>
auto flatLexicographicN (N n, Tuple<GrandChild...> child)
{
constexpr std::size_t m = sizeof...(GrandChild);
return Dune::unpackIntegerSequence([&](auto... i) {
return makeDescriptor(std::get<i%m>(child)...);
}, std::make_index_sequence<n*m>{});
}
template<class N, class Child>
auto flatInterleavedN (N n, Child child)
{
return Unknown{};
}
template<class N, class GrandChild>
auto flatInterleavedN (N n, UniformVector<GrandChild> child)
{
return UniformVector<GrandChild>{child.size()*n, child[0]};
}
template<class N, class GrandChild, std::size_t m>
auto flatInterleavedN (N n, UniformArray<GrandChild, m> child)
{
if constexpr (std::is_integral_v<N>)
return UniformVector<GrandChild>{n*m, child[0]};
else
return UniformArray<GrandChild, N::value*m>{child[0]};
}
template<class N, class GrandChild>
auto flatInterleavedN (N n, Vector<GrandChild> child)
{
auto result = Vector<GrandChild>{};
result.reserve(child.size()*n);
for (auto i : Dune::range(child.size()))
for (auto j : Dune::range(n))
result.emplace_back(child[i]);
return result;
}
template<class N, class GrandChild, std::size_t m>
auto flatInterleavedN (N n, Array<GrandChild, m> child)
{
if constexpr (std::is_integral_v<N>)
{
auto result = Vector<GrandChild>{};
result.reserve(child.size()*n);
for (auto i : Dune::range(child.size()))
for (auto j : Dune::range(n))
result.emplace_back(child[i]);
return result;
}
else
{
auto result = Array<GrandChild, N::value*m>{};
for (auto i : Dune::range(child.size()))
for (auto j : Dune::range(n))
result.emplace_back(child[i]);
return result;
}
}
template<class N, class... GrandChild>
auto flatInterleavedN (N n, Tuple<GrandChild...> child)
{
constexpr std::size_t m = sizeof...(GrandChild);
return Dune::unpackIntegerSequence([&](auto... i) {
return makeDescriptor(std::get<i/n>(child)...);
}, std::make_index_sequence<n*m>{});
}
} // end namespace Impl
} // end namespace ContainerDescriptors
} // end namespace Dune::Functions
#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH
basistags.hh
type_traits.hh
Dune::Functions
Definition monomialset.hh:19
Dune::Functions::containerDescriptor
auto containerDescriptor(const PreBasis &preBasis)
Return the container descriptor of the pre-basis, if defined, otherwise ContainerDescriptor::Unknown.
Definition containerdescriptors.hh:58
Dune::Functions::ContainerDescriptors
Definition containerfactory.hh:20
Dune::Functions::ContainerDescriptors::FlatArray
UniformArray< Value, n > FlatArray
Alias for a uniform array storing value placeholders.
Definition containerdescriptors.hh:143
Dune::Functions::ContainerDescriptors::makeUniformDescriptor
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::Functions::ContainerDescriptors::FlatVector
UniformVector< Value > FlatVector
Alias for a uniform vector storing value placeholders.
Definition containerdescriptors.hh:184
Dune::Functions::ContainerDescriptors::Tuple
Dune::TupleVector< Children... > Tuple
Descriptor with all children of possibly different type.
Definition containerdescriptors.hh:82
Dune::Functions::ContainerDescriptors::Vector
std::vector< Child > Vector
Descriptor for vectors with all children of the same type and dynamic size.
Definition containerdescriptors.hh:112
Dune::Functions::ContainerDescriptors::Array
std::array< Child, n > Array
Descriptor for arrays with all children of the same type and static size.
Definition containerdescriptors.hh:98
Dune::Functions::ContainerDescriptors::makeDescriptor
auto makeDescriptor(Child0 child, Children... children)
Generate a descriptor in case the children are all of the same type.
Definition containerdescriptors.hh:103
Dune::Functions::ContainerDescriptors::Unknown
Fallback container descriptor if nothing else fits.
Definition containerdescriptors.hh:52
Dune::Functions::ContainerDescriptors::Value
The node in the descriptor tree representing a value placeholder.
Definition containerdescriptors.hh:71
Dune::Functions::ContainerDescriptors::Value::size
static constexpr std::size_t size()
A value placeholder does not have any sub-descriptors, thus its size is zero.
Definition containerdescriptors.hh:77
Dune::Functions::ContainerDescriptors::Value::operator[]
Value operator[](const Index &) const
The child access method is only available for the interface, but should not be called.
Definition containerdescriptors.hh:74
Dune::Functions::ContainerDescriptors::UniformArray
Descriptor for arrays with all children identical and the number of children a static size.
Definition containerdescriptors.hh:117
Dune::Functions::ContainerDescriptors::UniformArray::size
static constexpr std::size_t size()
The static size information, i.e., number of children.
Definition containerdescriptors.hh:135
Dune::Functions::ContainerDescriptors::UniformArray::UniformArray
UniformArray()
Default constructor. Is enable if the child-type is default constructible.
Definition containerdescriptors.hh:121
Dune::Functions::ContainerDescriptors::UniformArray::UniformArray
UniformArray(Child child)
Constructor that stores a single child only.
Definition containerdescriptors.hh:126
Dune::Functions::ContainerDescriptors::UniformArray::operator[]
const Child & operator[](const Index &) const
Access the i'th child that is always the same, i.e., child_.
Definition containerdescriptors.hh:132
Dune::Functions::ContainerDescriptors::UniformVector
Uniform descriptor with dynamic size.
Definition containerdescriptors.hh:156
Dune::Functions::ContainerDescriptors::UniformVector::UniformVector
UniformVector(std::size_t size, Child child)
Constructor that stores the size and a single child only.
Definition containerdescriptors.hh:166
Dune::Functions::ContainerDescriptors::UniformVector< Value >::size
std::size_t size() const
Definition containerdescriptors.hh:176
Dune::Functions::ContainerDescriptors::UniformVector::UniformVector
UniformVector(std::size_t size)
Default constructor with size. Is enable if the child-type is default constructible.
Definition containerdescriptors.hh:160
Dune::Functions::ContainerDescriptors::UniformVector::operator[]
const Child & operator[](const Index &) const
Access the i'th child that is always the same, i.e., child_.
Definition containerdescriptors.hh:173