DUNE PDELab (unstable)

containerdescriptors.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH
8#define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH
9
10#include <array>
11#include <cassert>
12#include <functional>
13#include <type_traits>
14#include <vector>
15
19#include <dune/common/hybridutilities.hh>
21
22#include <dune/functions/common/type_traits.hh>
23#include <dune/functions/functionspacebases/basistags.hh>
24
48namespace Dune::Functions {
49namespace ContainerDescriptors {
50
52struct Unknown {};
53
54} // end namespace ContainerDescriptors
55
57template<class PreBasis>
58auto containerDescriptor(const PreBasis& preBasis)
59{
60 if constexpr (requires{ preBasis.containerDescriptor(); })
61 return preBasis.containerDescriptor();
62 else
63 return ContainerDescriptors::Unknown{};
64}
65
66
67namespace ContainerDescriptors {
68
70struct Value
71{
73 template<class Index>
74 Value operator[] (const Index&) const { return {}; }
75
77 static constexpr std::size_t size () { return 0; }
78};
79
81template<class... Children>
82using Tuple = Dune::TupleVector<Children...>;
83
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)
90{
91 using Descriptor = Tuple<Child0,Children...>;
92 return Descriptor{std::move(child0),std::move(children)...};
93}
94
95
97template<class Child, std::size_t n>
98using Array = std::array<Child, n>;
99
101template<class Child0, class... Children,
102 std::enable_if_t<(std::is_same_v<Child0, Children> &&...), int> = 0>
103auto makeDescriptor (Child0 child, Children... children)
104{
105 using Descriptor = Array<Child0,1+sizeof...(Children)>;
106 return Descriptor{std::move(child),std::move(children)...};
107}
108
109
111template<class Child>
112using Vector = std::vector<Child>;
113
115template<class Child, std::size_t n>
117{
119 template<class C = Child,
120 std::enable_if_t<std::is_default_constructible_v<C>, int> = 0>
122 : child_{}
123 {}
124
127 : child_{std::move(child)}
128 {}
129
131 template<class Index>
132 const Child& operator[] (const Index& /*i*/) const { return child_; }
133
135 static constexpr std::size_t size () { return n; }
136
137private:
138 Child child_;
139};
140
142template<std::size_t n>
143using FlatArray = UniformArray<Value,n>;
144
146template<class Child, std::size_t n>
147auto makeUniformDescriptor (std::integral_constant<std::size_t,n>, Child child)
148{
149 return UniformArray<Child,n>{std::move(child)};
150}
151
152
154template<class Child>
156{
158 template<class C = Child,
159 std::enable_if_t<std::is_default_constructible_v<C>, int> = 0>
160 explicit UniformVector (std::size_t size)
161 : size_{size}
162 , child_{}
163 {}
164
167 : size_{size}
168 , child_{std::move(child)}
169 {}
170
172 template<class Index>
173 const Child& operator[] (const Index& /*i*/) const { return child_; }
174
176 std::size_t size () const { return size_; }
177
178private:
179 std::size_t size_;
180 Child child_;
181};
182
184using FlatVector = UniformVector<Value>;
185
187template<class Child>
188auto makeUniformDescriptor (std::size_t n, Child child)
189{
190 return UniformVector<Child>{n,std::move(child)};
191}
192
193namespace Impl {
194
195template<class InnerFunc, class LeafFunc>
196struct TreeTransform
197{
198 TreeTransform (const InnerFunc& innerFunc, const LeafFunc& leafFunc)
199 : innerFunc_(innerFunc)
200 , leafFunc_(leafFunc)
201 {}
202
203 Unknown operator() (const Unknown& tree) const
204 {
205 return tree;
206 }
207
208 auto operator() (const Value& tree) const
209 {
210 return leafFunc_(tree);
211 }
212
213 template<class... V>
214 auto operator() (const Tuple<V...>& tree) const
215 {
216 return unpackIntegerSequence([&](auto... ii) {
217 return makeDescriptor(innerFunc_(tree[ii])...);
218 }, std::make_index_sequence<sizeof...(V)>());
219 }
220
221 template<class V, std::size_t n>
222 auto operator() (const Array<V,n>& tree) const
223 {
224 return unpackIntegerSequence([&](auto... ii) {
225 return makeDescriptor(innerFunc_(tree[ii])...);
226 }, std::make_index_sequence<n>());
227 }
228
229 template<class V>
230 auto operator() (const Vector<V>& tree) const
231 {
232 using W = decltype(innerFunc_(tree[0]));
233 Vector<W> result;
234 result.reserve(tree.size());
235 for (std::size_t i = 0; i < tree.size(); ++i)
236 result.emplace_back(innerFunc_(tree[i]));
237 return result;
238 }
239
240 template<class V, std::size_t n>
241 auto operator() (const UniformArray<V,n>& tree) const
242 {
243 return makeUniformDescriptor(Dune::index_constant<n>{}, innerFunc_(tree[0]));
244 }
245
246 template<class V>
247 auto operator() (const UniformVector<V>& tree) const
248 {
249 return makeUniformDescriptor(tree.size(), innerFunc_(tree[0]));
250 }
251
252private:
253 InnerFunc innerFunc_;
254 LeafFunc leafFunc_;
255};
256
257
268template<class Size, class T>
269auto appendToTree (Size s, const T& tree)
270{
271 auto transform = TreeTransform(
272 [s](auto&& node) { return appendToTree(s, node); },
273 [s](auto&& node) { return makeUniformDescriptor(s, node); });
274 return transform(tree);
275}
276
278template<class... Child>
280{
281 if constexpr ((std::is_same_v<Child, FlatVector> && ...))
282 return FlatVector((child.size() + ...));
283 else
284 return Unknown{};
285}
286
288template<class N, class Child>
289auto flatLexicographicN (N n, Child child)
290{
291 return Unknown{};
292}
293
295template<class N, class GrandChild>
296auto flatLexicographicN (N n, UniformVector<GrandChild> child)
297{
298 return UniformVector<GrandChild>{child.size()*n, child[0]};
299}
300
302template<class N, class GrandChild, std::size_t m>
303auto flatLexicographicN (N n, UniformArray<GrandChild, m> child)
304{
305 if constexpr (std::is_same_v<N, std::size_t>)
306 return UniformVector<GrandChild>{n*m, child[0]};
307 else
308 return UniformArray<GrandChild, N::value*m>{child[0]};
309}
310
312template<class N, class GrandChild>
313auto flatLexicographicN (N n, Vector<GrandChild> child)
314{
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]);
320 return result;
321}
322
324template<class N, class GrandChild, std::size_t m>
325auto flatLexicographicN (N n, Array<GrandChild, m> child)
326{
327 if constexpr (std::is_same_v<N, std::size_t>)
328 {
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]);
334 return result;
335 }
336 else
337 {
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]);
342 return result;
343 }
344}
345
347template<class N, class... GrandChild>
348auto flatLexicographicN (N n, Tuple<GrandChild...> child)
349{
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>{});
354}
355
357template<class N, class Child>
358auto flatInterleavedN (N n, Child child)
359{
360 return Unknown{};
361}
362
364template<class N, class GrandChild>
365auto flatInterleavedN (N n, UniformVector<GrandChild> child)
366{
367 return UniformVector<GrandChild>{child.size()*n, child[0]};
368}
369
371template<class N, class GrandChild, std::size_t m>
372auto flatInterleavedN (N n, UniformArray<GrandChild, m> child)
373{
374 if constexpr (std::is_integral_v<N>)
375 return UniformVector<GrandChild>{n*m, child[0]};
376 else
377 return UniformArray<GrandChild, N::value*m>{child[0]};
378}
379
381template<class N, class GrandChild>
382auto flatInterleavedN (N n, Vector<GrandChild> child)
383{
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]);
389 return result;
390}
391
393template<class N, class GrandChild, std::size_t m>
394auto flatInterleavedN (N n, Array<GrandChild, m> child)
395{
396 if constexpr (std::is_integral_v<N>)
397 {
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]);
403 return result;
404 }
405 else
406 {
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]);
411 return result;
412 }
413}
414
416template<class N, class... GrandChild>
417auto flatInterleavedN (N n, Tuple<GrandChild...> child)
418{
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>{});
423}
424
425} // end namespace Impl
426} // end namespace ContainerDescriptors
427} // end namespace Dune::Functions
428
429#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_CONTAINERDESCRIPTORS_HH
A class augmenting std::tuple by element access via operator[].
Definition: tuplevector.hh:35
Utility to generate an array with a certain value.
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:29
constexpr FlatLexicographic flatLexicographic()
Creates a lexicographic merging of direct children without blocking.
Definition: basistags.hh:192
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
free standing function for setting up a range based for loop over an integer range for (auto i: range...
Definition: rangeutilities.hh:288
typename impl::_Child< Node, indices... >::type Child
Template alias for the type of a child node given by a list of child indices.
Definition: childextraction.hh:224
ImplementationDefined child(Node &&node, Indices... indices)
Extracts the child of a node given by a sequence of compile-time and run-time indices.
Definition: childextraction.hh:127
STL namespace.
Utilities for reduction like operations on ranges.
Descriptor for arrays with all children identical and the number of children a static size.
Definition: containerdescriptors.hh:117
static constexpr std::size_t size()
The static size information, i.e., number of children.
Definition: containerdescriptors.hh:135
UniformArray()
Default constructor. Is enable if the child-type is default constructible.
Definition: containerdescriptors.hh:121
UniformArray(Child child)
Constructor that stores a single child only.
Definition: containerdescriptors.hh:126
const Child & operator[](const Index &) const
Access the i'th child that is always the same, i.e., child_.
Definition: containerdescriptors.hh:132
Uniform descriptor with dynamic size.
Definition: containerdescriptors.hh:156
UniformVector(std::size_t size, Child child)
Constructor that stores the size and a single child only.
Definition: containerdescriptors.hh:166
std::size_t size() const
The dynamic size information, i.e., number of children.
Definition: containerdescriptors.hh:176
UniformVector(std::size_t size)
Default constructor with size. Is enable if the child-type is default constructible.
Definition: containerdescriptors.hh:160
const Child & operator[](const Index &) const
Access the i'th child that is always the same, i.e., child_.
Definition: containerdescriptors.hh:173
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
Provides the TupleVector class that augments std::tuple by operator[].
Utilities for type computations, constraining overloads, ...
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Sep 30, 08:41, 2025)