DUNE-ACFEM (unstable)

tensorbase.hh
1#ifndef __DUNE_ACFEM_TENSORS_TENSORBASE_HH__
2#define __DUNE_ACFEM_TENSORS_TENSORBASE_HH__
3
4#include <dune/common/fvector.hh>
5#include <dune/common/tupleutility.hh>
6
7#include "../common/types.hh"
8#include "../mpl/generators.hh"
9#include "../mpl/subtuple.hh"
10#include "../mpl/filter.hh"
11#include "../mpl/compare.hh"
12#include "../mpl/multiindex.hh"
13#include "../expressions/constantoperations.hh"
14#include "../expressions/interface.hh"
15
16#include "operations/restrictionoperators.hh"
17
18#define DUNE_ACFEM_TENSOR_WORKAROUND_GCC(MAJOR) DUNE_ACFEM_IS_GCC(MAJOR, MAJOR)
19
20namespace Dune
21{
22 namespace ACFem
23 {
24 namespace Tensor
25 {
26 using namespace Literals;
27 using namespace Expressions;
28
32 template<std::size_t... Ints>
33 using Seq = IndexSequence<Ints...>;
34
38 template<std::size_t... Dimensions>
39 using TensorSignature = Seq<Dimensions...>;
40
41 template<class T, class SFINAE = void>
42 struct IsTensor
43 : FalseType
44 {};
45
46 template<class T>
47 struct IsTensor<T, std::enable_if_t<!IsDecay<T>::value> >
48 : IsTensor<std::decay_t<T> >
49 {};
50
52 template<class T>
53 struct IsTensor<T, std::enable_if_t<(IsDecay<T>::value
54 && T::Signature::size() == T::rank
55 )> >
56 : TrueType
57 {};
58
62 template<class T,
63 std::enable_if_t<(IsTensor<T>::value
66 ), int> = 0>
67 decltype(auto) tensor(T&& t)
68 {
69 return std::forward<T>(t);
70 }
71
75 template<class T,
76 std::enable_if_t<(IsTensor<T>::value
79 ), int> = 0>
80 std::decay_t<T> tensor(T&& t)
81 {
82 return std::forward<T>(t);
83 }
84
90 template<
91 class T,
92 std::enable_if_t<(IsTensor<T>::value
93 && Expressions::IsClosure<std::decay_t<T> >::value
94 && !IsTypedValue<Operand<0, T> >::value
95 ), int> = 0>
96 constexpr decltype(auto) tensor(T&& t)
97 {
98 Expressions::danglingReferenceCheck<0>(std::forward<T>(t));
99 return operand<0>(std::forward<T>(t));
100 }
101
102 template<
103 class T,
104 std::enable_if_t<(IsTensor<T>::value
105 && Expressions::IsClosure<std::decay_t<T> >::value
106 && IsTypedValue<Operand<0, T> >::value
107 ), int> = 0>
108 std::decay_t<Operand<0, T> > tensor(T&& t)
109 {
110 return std::forward<T>(t).template operand<0>();
111 }
112
114 template<class T, class SFINAE = void>
116 : FalseType
117 {};
118
120 template<class T>
121 struct IsTensorOperand<T, std::enable_if_t<!IsDecay<T>::value> >
122 : IsTensorOperand<std::decay_t<T> >
123 {};
124
126 template<class T>
127 struct IsTensorOperand<T, std::enable_if_t<(IsTensor<T>::value && IsDecay<T>::value)> >
128 : TrueType
129 {};
130
131 // forward
132 template<class T, class SFINAE = void>
133 struct TensorTraits;
134
136 template<class T, std::enable_if_t<(IsTensorOperand<T>::value && !IsTensor<T>::value), int> = 0>
137 auto tensor(T&& t)
138 {
139 return TensorTraits<T>::toTensor(std::forward<T>(t));
140 }
141
143 template<class Field, class Seq, class Impl>
145
146 // Forward
147 template<class T>
148 class RestrictionOperators;
149
153 template<class Field, std::size_t... Dimensions, class Impl>
154 struct TensorBase<Field, TensorSignature<Dimensions...>, Impl>
155 : public RestrictionOperators<Impl>
156 {
157 public:
158 using TensorType = Impl;
159 using FieldType = Field;
160 using Signature = TensorSignature<Dimensions...>;
161
162 static constexpr std::size_t rank = sizeof...(Dimensions);
163
167 template<std::size_t... Ind, std::enable_if_t<(sizeof...(Ind) <= rank), int> = 0>
168 static std::size_t constexpr dim(Seq<Ind...> = Seq<Ind...>{})
169 {
170 using SubSignature = ConditionalType<sizeof...(Ind) == 0, Signature, SubSequence<Signature, Ind...> >;
171 return multiDim(SubSignature{});
172 }
173
177 template<std::size_t... Ind, std::enable_if_t<(sizeof...(Ind) > rank), int> = 0>
178 static std::size_t constexpr dim(Seq<Ind...> = Seq<Ind...>{})
179 {
180 return std::numeric_limits<std::size_t>::max();
181 }
182
184 static auto constexpr signature()
185 {
186 return Signature{};
187 }
188
189 template<std::size_t... Indices, class Pos = MakeIndexSequence<sizeof...(Indices)> >
190 static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
191 {
192 return false;
193 }
194
195 std::string name() const
196 {
197 return name(Signature{});
198 }
199
200 template<class T, std::enable_if_t<(rank == 0 && SameDecay<T, FieldType>::value), int> = 0>
201 operator T () const
202 {
203 return static_cast<const Impl&>(*this)();
204 }
205
206 protected:
207 std::string name(Seq<>) const
208 {
209 return std::to_string(static_cast<const Impl&>(*this)());
210 }
211
212 template<std::size_t D0, std::size_t... Rest>
213 std::string name(Seq<D0, Rest...> sig) const
214 {
215 return "tensor<"+toString(sig)+">";
216 }
217
218 };
219
220 template<class T, class SFINAE>
221 struct TensorTraits
222 {
223 using Signature = Seq<>;
224 static constexpr std::size_t rank = std::numeric_limits<std::size_t>::max();
225 };
226
227 template<class T>
228 constexpr inline bool HasTensorTraitsV =
229 TensorTraits<T>::Signature::size() == TensorTraits<T>::rank;
230
231 template<class T>
232 struct TensorTraitsBase
233 {
234 using TensorType = std::decay_t<T>;
235 using FieldType = typename TensorType::FieldType;
236 using Signature = typename TensorType::Signature;
237 static constexpr std::size_t rank = TensorType::rank;
238
239 template<std::size_t... Indices, class Pos = MakeIndexSequence<sizeof...(Indices)> >
240 static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
241 {
242 return TensorType::isZero(Seq<Indices...>{}, Pos{});
243 }
244
248 template<std::size_t... Ind, std::enable_if_t<(sizeof...(Ind) <= rank), int> = 0>
249 static std::size_t constexpr dim(Seq<Ind...> = Seq<Ind...>{})
250 {
251 using SubSignature = ConditionalType<sizeof...(Ind) == 0, Signature, SubSequence<Signature, Ind...> >;
252 return multiDim(SubSignature{});
253 }
254
258 template<std::size_t... Ind, std::enable_if_t<(sizeof...(Ind) > rank), int> = 0>
259 static std::size_t constexpr dim(Seq<Ind...> = Seq<Ind...>{})
260 {
261 return std::numeric_limits<std::size_t>::max();
262 }
263
267 static Signature constexpr signature()
268 {
269 return Signature{};
270 }
271
272 using ZeroIndex = MakeIndexSequence<rank, 0, 0>;
273 private:
274 static TrueType mutableArg(FieldType&);
275 static FalseType mutableArg(const FieldType&);
276 static FalseType mutableArg(FieldType&&);
277#ifndef NDEBUG
278 static_assert(ZeroIndex::size() == rank, "bug");
279#endif
280 template<class U, class SFINE = void>
281 struct ElementZeroHelper
282 {
283 using Type = decltype(std::declval<const U&>()(ZeroIndex{}));
284 static constexpr bool hasMutableCallOperator = false;
285 };
286
287 template<class U>
288 struct ElementZeroHelper<U, VoidType<decltype(std::declval<U&>()(ZeroIndex{}))> >
289 {
290 using Type = decltype(std::declval<U&>()(ZeroIndex{}));
291 static constexpr bool hasMutableCallOperator = true;
292 };
293 public:
294 using ElementZero = typename ElementZeroHelper<T>::Type;
295 static constexpr bool hasMutableComponents = decltype(mutableArg(std::declval<ElementZero>()))::value;
296 static constexpr bool hasMutableCallOperator = ElementZeroHelper<T>::hasMutableCallOperator;
297 };
298
299 template<class T>
300 struct TensorTraits<T, std::enable_if_t<!IsDecay<T>::value> >
301 : TensorTraits<std::decay_t<T> >
302 {};
303
304 template<class T>
305 struct TensorTraits<T, std::enable_if_t<IsTensor<T>::value && IsDecay<T>::value> >
306 : TensorTraitsBase<T>
307 {};
308
309 template<class T, std::enable_if_t<IsTensorOperand<T>::value, int> = 0>
310 constexpr auto rank(T&& t)
311 {
312 return TensorTraits<T>::rank;
313 }
314
315 template<class T, std::enable_if_t<IsTensorOperand<T>::value, int> = 0>
316 constexpr auto signature(T&& t)
317 {
318 return typename TensorTraits<T>::Signature{};
319 }
320
321 template<class T, class SFINAE = void>
322 struct IsTensorZero
323 : FalseType
324 {};
325
326 template<class T>
327 struct IsTensorZero<
328 T,
329 std::enable_if_t<(IsTensor<T>::value
330 && IsDecay<T>::value
331 && T::isZero()
332 )> >
333 : TrueType
334 {};
335
336 template<class T, class SFINAE = void>
337 struct IsTensorNotZero
338 : FalseType
339 {};
340
341 template<class T>
342 struct IsTensorNotZero<
343 T,
344 std::enable_if_t<(IsTensor<T>::value
345 && IsDecay<T>::value
346 && !T::isZero()
347 )> >
348 : TrueType
349 {};
350
351 namespace {
352
353 template<class Tensor, class Tuple, std::size_t... Unpack>
354 decltype(auto) tensorValueHelper(Tensor&& t,
355 Tuple&& indices,
356 IndexSequence<Unpack...>&&)
357 {
358 return std::forward<Tensor>(t)(std::get<Unpack>(indices)...);
359 }
360 }
361
362 template<
363 class Tensor,
364 class Tuple,
365 std::enable_if_t<(IsTensor<Tensor>::value
366 && IsTupleLike<Tuple>::value
367 ), int> = 0>
368 decltype(auto) tensorValue(Tensor&& tensor, Tuple&& indices)
369 {
370 return tensorValueHelper(std::forward<Tensor>(tensor), std::forward<Tuple>(indices),
371 MakeIndexSequence<TensorTraits<Tensor>::rank>{});
372 }
373
374 template<
375 class Tensor,
376 std::size_t... Indices,
377 std::enable_if_t<(IsTensor<Tensor>::value
378 && sizeof...(Indices) == TensorTraits<Tensor>::rank
379 ), int> = 0>
380 decltype(auto) tensorValue(Tensor&& tensor, IndexSequence<Indices...>)
381 {
382 // could check whether Indices... is in range.
383 return std::forward<Tensor>(tensor)(IndexSequence<Indices...>{});
384 }
385
386 template<
387 class T, class Indices,
388 std::enable_if_t<(IsTensorOperand<T>::value
389 && !IsTensor<T>::value
390 ), int> = 0>
391 decltype(auto) tensorValue(T&& t, Indices&& indices)
392 {
393 return tensorValue(tensor(std::forward<T>(t)), std::forward<Indices>(indices));
394 }
395
399 template<class T, std::enable_if_t<!Expressions::IsClosure<T>::value && IsTensorOperand<T>::value, int> = 0>
400 constexpr auto name(T&& t)
401 {
402 return tensor(std::forward<T>(t)).name();
403 }
404
405 template<class T, std::enable_if_t<Expressions::IsClosure<T>::value && IsTensor<T>::value, int> = 0>
406 constexpr auto name(T&& t)
407 {
408 return std::forward<T>(t).name();
409 }
410
411 } // NS Tensor
412
413 using Tensor::HasTensorTraitsV;
414 using Tensor::IsTensor;
415 using Tensor::IsTensorOperand;
416 using Tensor::TensorTraits;
417 using Tensor::tensor;
418
419 } // NS ACFem
420
421} // NS Dune
422
423#endif // __DUNE_ACFEM_TENSORS_TENSORBASE_HH__
BoolConstant< ExpressionTraits< T >::isTypedValue > IsTypedValue
Compile-time true if T is a "typed value", e.g. a std::integral_constant.
Definition: expressiontraits.hh:90
constexpr std::size_t size()
Gives the number of elements in tuple-likes and std::integer_sequence.
Definition: size.hh:73
MakeSequence< std::size_t, N, Offset, Stride, Repeat > MakeIndexSequence
Make a sequence of std::size_t elements.
Definition: generators.hh:34
Sequence< std::size_t, V... > IndexSequence
Sequence of std::size_t values.
Definition: types.hh:64
typename MakeType< void, Other... >::Type VoidType
Generate void regardless of the template argument list.
Definition: types.hh:151
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
constexpr bool isZero
Shortcut identifying a zero model.
Definition: modeltraits.hh:642
static std::size_t constexpr multiDim(IndexSequence< Dimensions... >, IndexSequence< IndexPositions... >=IndexSequence< IndexPositions... >{})
Compute the "dimension" corresponding to the given signature, i.e.
Definition: multiindex.hh:171
STL namespace.
An expression closure is a wrapper class which wraps an expression in order to interface to other exi...
Definition: interface.hh:50
Definition: tensorbase.hh:117
Base class for all tensors.
Definition: tensorbase.hh:144
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)